std/vp8: calculate the predicted values This commit, part of a series, is inspired by pull request PR #168 by Damian Kaczmarek (with AI assistance), with some modifications. Updates PR #168
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c index f8b059c..30f100b 100644 --- a/release/c/wuffs-unsupported-snapshot.c +++ b/release/c/wuffs-unsupported-snapshot.c
@@ -15532,6 +15532,7 @@ uint16_t f_dequants[4][3][2]; uint32_t f_prob_skip; uint8_t f_mb_subblock_modes[16]; + uint8_t f_yuv_cache[26][32]; uint32_t f_dst_x; uint32_t f_dst_y; wuffs_base__pixel_swizzler f_swizzler; @@ -80976,6 +80977,138 @@ }; static const uint8_t +WUFFS_VP8__CLAMP[1024] WUFFS_BASE__POTENTIALLY_UNUSED = { + 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, + 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, + 16u, 17u, 18u, 19u, 20u, 21u, 22u, 23u, + 24u, 25u, 26u, 27u, 28u, 29u, 30u, 31u, + 32u, 33u, 34u, 35u, 36u, 37u, 38u, 39u, + 40u, 41u, 42u, 43u, 44u, 45u, 46u, 47u, + 48u, 49u, 50u, 51u, 52u, 53u, 54u, 55u, + 56u, 57u, 58u, 59u, 60u, 61u, 62u, 63u, + 64u, 65u, 66u, 67u, 68u, 69u, 70u, 71u, + 72u, 73u, 74u, 75u, 76u, 77u, 78u, 79u, + 80u, 81u, 82u, 83u, 84u, 85u, 86u, 87u, + 88u, 89u, 90u, 91u, 92u, 93u, 94u, 95u, + 96u, 97u, 98u, 99u, 100u, 101u, 102u, 103u, + 104u, 105u, 106u, 107u, 108u, 109u, 110u, 111u, + 112u, 113u, 114u, 115u, 116u, 117u, 118u, 119u, + 120u, 121u, 122u, 123u, 124u, 125u, 126u, 127u, + 128u, 129u, 130u, 131u, 132u, 133u, 134u, 135u, + 136u, 137u, 138u, 139u, 140u, 141u, 142u, 143u, + 144u, 145u, 146u, 147u, 148u, 149u, 150u, 151u, + 152u, 153u, 154u, 155u, 156u, 157u, 158u, 159u, + 160u, 161u, 162u, 163u, 164u, 165u, 166u, 167u, + 168u, 169u, 170u, 171u, 172u, 173u, 174u, 175u, + 176u, 177u, 178u, 179u, 180u, 181u, 182u, 183u, + 184u, 185u, 186u, 187u, 188u, 189u, 190u, 191u, + 192u, 193u, 194u, 195u, 196u, 197u, 198u, 199u, + 200u, 201u, 202u, 203u, 204u, 205u, 206u, 207u, + 208u, 209u, 210u, 211u, 212u, 213u, 214u, 215u, + 216u, 217u, 218u, 219u, 220u, 221u, 222u, 223u, + 224u, 225u, 226u, 227u, 228u, 229u, 230u, 231u, + 232u, 233u, 234u, 235u, 236u, 237u, 238u, 239u, + 240u, 241u, 242u, 243u, 244u, 245u, 246u, 247u, + 248u, 249u, 250u, 251u, 252u, 253u, 254u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, +}; + +static const uint8_t WUFFS_VP8__SUBBLOCK_MODE_PROBS[10][10][9] WUFFS_BASE__POTENTIALLY_UNUSED = { { { @@ -81688,8 +81821,7 @@ uint32_t a_mbx, uint32_t a_mby, uint32_t a_seg, - uint32_t a_luma_mode, - uint32_t a_chroma_mode); + uint32_t a_luma_mode); WUFFS_BASE__GENERATED_C_CODE static wuffs_base__empty_struct @@ -81806,6 +81938,51 @@ uint8_t a_left_mode); WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_y4( + wuffs_vp8__decoder* self, + uint32_t a_b); + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_y16( + wuffs_vp8__decoder* self, + uint32_t a_mode); + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_uv8( + wuffs_vp8__decoder* self, + uint32_t a_b, + uint32_t a_mode); + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__reconstruct( + wuffs_vp8__decoder* self, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_mbx, + uint32_t a_mby, + uint32_t a_luma_mode, + uint32_t a_chroma_mode); + +WUFFS_BASE__GENERATED_C_CODE +static uint32_t +wuffs_vp8__decoder__substitute_dc_top_left( + const wuffs_vp8__decoder* self, + uint32_t a_mode, + uint32_t a_mbx, + uint32_t a_mby); + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__prepare_yuv_cache( + wuffs_vp8__decoder* self, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_mbx, + uint32_t a_mby); + +WUFFS_BASE__GENERATED_C_CODE static wuffs_base__status wuffs_vp8__decoder__do_decode_image_config( wuffs_vp8__decoder* self, @@ -82040,8 +82217,7 @@ uint32_t a_mbx, uint32_t a_mby, uint32_t a_seg, - uint32_t a_luma_mode, - uint32_t a_chroma_mode) { + uint32_t a_luma_mode) { uint32_t v_bc = 0; uint32_t v_by = 0; uint32_t v_bx = 0; @@ -82679,9 +82855,14 @@ a_mbx, a_mby, v_seg, - v_luma_mode, - v_chroma_mode); + v_luma_mode); } + wuffs_vp8__decoder__reconstruct(self, + a_workbuf, + a_mbx, + a_mby, + v_luma_mode, + v_chroma_mode); return wuffs_base__make_empty_struct(); } @@ -82830,6 +83011,869 @@ return 9u; } +// -------- func vp8.decoder.predict_y4 + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_y4( + wuffs_vp8__decoder* self, + uint32_t a_b) { + uint32_t v_cachey = 0; + uint32_t v_cachex = 0; + uint32_t v_mode = 0; + uint32_t v_z = 0; + uint8_t v_avg = 0; + uint32_t v_tm0 = 0; + uint32_t v_tm1 = 0; + uint32_t v_tm2 = 0; + uint32_t v_a = 0; + uint32_t v_b = 0; + uint32_t v_c = 0; + uint32_t v_d = 0; + uint32_t v_e = 0; + uint32_t v_f = 0; + uint32_t v_g = 0; + uint32_t v_h = 0; + uint32_t v_i = 0; + uint32_t v_p = 0; + uint32_t v_q = 0; + uint32_t v_r = 0; + uint32_t v_s = 0; + uint8_t v_ab = 0; + uint8_t v_bc = 0; + uint8_t v_cd = 0; + uint8_t v_de = 0; + uint8_t v_ef = 0; + uint8_t v_pa = 0; + uint8_t v_qp = 0; + uint8_t v_rq = 0; + uint8_t v_sr = 0; + uint8_t v_abc = 0; + uint8_t v_bcd = 0; + uint8_t v_cde = 0; + uint8_t v_def = 0; + uint8_t v_efg = 0; + uint8_t v_fgh = 0; + uint8_t v_ghi = 0; + uint8_t v_hii = 0; + uint8_t v_pab = 0; + uint8_t v_qpa = 0; + uint8_t v_rqp = 0; + uint8_t v_srq = 0; + uint8_t v_ssr = 0; + uint8_t v_sss = 0; + + v_cachey = ((a_b & 12u) + 1u); + v_cachex = (((a_b & 3u) * 4u) + 8u); + v_mode = ((uint32_t)(self->private_impl.f_mb_subblock_modes[a_b])); + if (v_mode == 0u) { + v_avg = ((uint8_t)(((4u + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)]))) / 8u))); + v_z = 0u; + while (v_z < 16u) { + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 2u))][(v_cachex + (v_z & 3u))] = v_avg; + v_z += 1u; + } + } else if (v_mode == 1u) { + v_tm0 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_z = 0u; + while (v_z < 16u) { + v_tm1 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 2u))][(v_cachex - 1u)])); + v_tm2 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + (v_z & 3u))])); + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 2u))][(v_cachex + (v_z & 3u))] = WUFFS_VP8__CLAMP[(((uint32_t)((v_tm1 + v_tm2) - v_tm0)) & 1023u)]; + v_z += 1u; + } + } else if (v_mode == 2u) { + v_a = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_e = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])); + v_f = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 4u)])); + v_def = ((uint8_t)(((v_d + + (2u * v_e) + + v_f + + 2u) / 4u))); + v_cde = ((uint8_t)(((v_c + + (2u * v_d) + + v_e + + 2u) / 4u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + v_abc = ((uint8_t)(((v_a + + (2u * v_b) + + v_c + + 2u) / 4u))); + v_z = 0u; + while (v_z < 4u) { + self->private_impl.f_yuv_cache[(v_cachey + v_z)][v_cachex] = v_abc; + self->private_impl.f_yuv_cache[(v_cachey + v_z)][(v_cachex + 1u)] = v_bcd; + self->private_impl.f_yuv_cache[(v_cachey + v_z)][(v_cachex + 2u)] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + v_z)][(v_cachex + 3u)] = v_def; + v_z += 1u; + } + } else if (v_mode == 3u) { + v_s = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])); + v_r = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])); + v_q = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])); + v_p = ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])); + v_a = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_qpa = ((uint8_t)(((v_q + + (2u * v_p) + + v_a + + 2u) / 4u))); + v_rqp = ((uint8_t)(((v_r + + (2u * v_q) + + v_p + + 2u) / 4u))); + v_srq = ((uint8_t)(((v_s + + (2u * v_r) + + v_q + + 2u) / 4u))); + v_ssr = ((uint8_t)(((v_s + + (2u * v_s) + + v_r + + 2u) / 4u))); + v_z = 0u; + while (v_z < 4u) { + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + v_z)] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + v_z)] = v_rqp; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + v_z)] = v_srq; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + v_z)] = v_ssr; + v_z += 1u; + } + } else if (v_mode == 4u) { + v_s = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])); + v_r = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])); + v_q = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])); + v_p = ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])); + v_a = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_e = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])); + v_cde = ((uint8_t)(((v_c + + (2u * v_d) + + v_e + + 2u) / 4u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + v_abc = ((uint8_t)(((v_a + + (2u * v_b) + + v_c + + 2u) / 4u))); + v_pab = ((uint8_t)(((v_p + + (2u * v_a) + + v_b + + 2u) / 4u))); + v_qpa = ((uint8_t)(((v_q + + (2u * v_p) + + v_a + + 2u) / 4u))); + v_rqp = ((uint8_t)(((v_r + + (2u * v_q) + + v_p + + 2u) / 4u))); + v_srq = ((uint8_t)(((v_s + + (2u * v_r) + + v_q + + 2u) / 4u))); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_pab; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_abc; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_bcd; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_pab; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_abc; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_bcd; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_rqp; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_pab; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_abc; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_srq; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_rqp; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_pab; + } else if (v_mode == 5u) { + v_r = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])); + v_q = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])); + v_p = ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])); + v_a = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_e = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])); + v_ab = ((uint8_t)(((v_a + v_b + 1u) / 2u))); + v_bc = ((uint8_t)(((v_b + v_c + 1u) / 2u))); + v_cd = ((uint8_t)(((v_c + v_d + 1u) / 2u))); + v_de = ((uint8_t)(((v_d + v_e + 1u) / 2u))); + v_cde = ((uint8_t)(((v_c + + (2u * v_d) + + v_e + + 2u) / 4u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + v_abc = ((uint8_t)(((v_a + + (2u * v_b) + + v_c + + 2u) / 4u))); + v_pab = ((uint8_t)(((v_p + + (2u * v_a) + + v_b + + 2u) / 4u))); + v_qpa = ((uint8_t)(((v_q + + (2u * v_p) + + v_a + + 2u) / 4u))); + v_rqp = ((uint8_t)(((v_r + + (2u * v_q) + + v_p + + 2u) / 4u))); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_ab; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_bc; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_cd; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_de; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_pab; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_abc; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_bcd; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_ab; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_bc; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_cd; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_rqp; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_pab; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_abc; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_bcd; + } else if (v_mode == 6u) { + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_e = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])); + v_f = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 4u)])); + v_g = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 5u)])); + v_h = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 6u)])); + v_i = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 7u)])); + v_hii = ((uint8_t)(((v_h + + (2u * v_i) + + v_i + + 2u) / 4u))); + v_ghi = ((uint8_t)(((v_g + + (2u * v_h) + + v_i + + 2u) / 4u))); + v_fgh = ((uint8_t)(((v_f + + (2u * v_g) + + v_h + + 2u) / 4u))); + v_efg = ((uint8_t)(((v_e + + (2u * v_f) + + v_g + + 2u) / 4u))); + v_def = ((uint8_t)(((v_d + + (2u * v_e) + + v_f + + 2u) / 4u))); + v_cde = ((uint8_t)(((v_c + + (2u * v_d) + + v_e + + 2u) / 4u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_bcd; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_cde; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_def; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_def; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_fgh; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_def; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_fgh; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_ghi; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_fgh; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_ghi; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_hii; + } else if (v_mode == 7u) { + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_e = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])); + v_f = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 4u)])); + v_g = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 5u)])); + v_h = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 6u)])); + v_i = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 7u)])); + v_ef = ((uint8_t)(((v_e + v_f + 1u) / 2u))); + v_de = ((uint8_t)(((v_d + v_e + 1u) / 2u))); + v_cd = ((uint8_t)(((v_c + v_d + 1u) / 2u))); + v_bc = ((uint8_t)(((v_b + v_c + 1u) / 2u))); + v_ghi = ((uint8_t)(((v_g + + (2u * v_h) + + v_i + + 2u) / 4u))); + v_fgh = ((uint8_t)(((v_f + + (2u * v_g) + + v_h + + 2u) / 4u))); + v_efg = ((uint8_t)(((v_e + + (2u * v_f) + + v_g + + 2u) / 4u))); + v_def = ((uint8_t)(((v_d + + (2u * v_e) + + v_f + + 2u) / 4u))); + v_cde = ((uint8_t)(((v_c + + (2u * v_d) + + v_e + + 2u) / 4u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_bc; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_cd; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_de; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_ef; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_bcd; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_def; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_cd; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_de; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_ef; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_fgh; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_cde; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_def; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_efg; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_ghi; + } else if (v_mode == 8u) { + v_s = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])); + v_r = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])); + v_q = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])); + v_p = ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])); + v_a = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_b = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])); + v_c = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])); + v_d = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])); + v_sr = ((uint8_t)(((v_s + v_r + 1u) / 2u))); + v_rq = ((uint8_t)(((v_r + v_q + 1u) / 2u))); + v_qp = ((uint8_t)(((v_q + v_p + 1u) / 2u))); + v_pa = ((uint8_t)(((v_p + v_a + 1u) / 2u))); + v_bcd = ((uint8_t)(((v_b + + (2u * v_c) + + v_d + + 2u) / 4u))); + v_abc = ((uint8_t)(((v_a + + (2u * v_b) + + v_c + + 2u) / 4u))); + v_pab = ((uint8_t)(((v_p + + (2u * v_a) + + v_b + + 2u) / 4u))); + v_qpa = ((uint8_t)(((v_q + + (2u * v_p) + + v_a + + 2u) / 4u))); + v_rqp = ((uint8_t)(((v_r + + (2u * v_q) + + v_p + + 2u) / 4u))); + v_srq = ((uint8_t)(((v_s + + (2u * v_r) + + v_q + + 2u) / 4u))); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_pa; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_pab; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_abc; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_bcd; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_qp; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_pa; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_pab; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_rq; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_rqp; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_qp; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_qpa; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_sr; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_srq; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_rq; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_rqp; + } else { + v_s = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])); + v_r = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])); + v_q = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])); + v_p = ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])); + v_sr = ((uint8_t)(((v_s + v_r + 1u) / 2u))); + v_rq = ((uint8_t)(((v_r + v_q + 1u) / 2u))); + v_qp = ((uint8_t)(((v_q + v_p + 1u) / 2u))); + v_rqp = ((uint8_t)(((v_r + + (2u * v_q) + + v_p + + 2u) / 4u))); + v_srq = ((uint8_t)(((v_s + + (2u * v_r) + + v_q + + 2u) / 4u))); + v_ssr = ((uint8_t)(((v_s + + (2u * v_s) + + v_r + + 2u) / 4u))); + v_sss = ((uint8_t)(v_s)); + self->private_impl.f_yuv_cache[v_cachey][v_cachex] = v_qp; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 1u)] = v_rqp; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 2u)] = v_rq; + self->private_impl.f_yuv_cache[v_cachey][(v_cachex + 3u)] = v_srq; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][v_cachex] = v_rq; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 1u)] = v_srq; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 2u)] = v_sr; + self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex + 3u)] = v_ssr; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][v_cachex] = v_sr; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 1u)] = v_ssr; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 2u)] = v_sss; + self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex + 3u)] = v_sss; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][v_cachex] = v_sss; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 1u)] = v_sss; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 2u)] = v_sss; + self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex + 3u)] = v_sss; + } + return wuffs_base__make_empty_struct(); +} + +// -------- func vp8.decoder.predict_y16 + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_y16( + wuffs_vp8__decoder* self, + uint32_t a_mode) { + uint32_t v_x = 0; + uint32_t v_y = 0; + uint32_t v_z = 0; + uint8_t v_avg = 0; + uint8_t v_val = 0; + uint32_t v_tm0 = 0; + uint32_t v_tm1 = 0; + uint32_t v_tm2 = 0; + + if (a_mode == 0u) { + v_avg = ((uint8_t)(((16u + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][8u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][9u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][10u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][11u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][12u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][13u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][14u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][15u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][16u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][17u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][18u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][19u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][20u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][21u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][22u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][23u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[1u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[2u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[3u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[4u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[5u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[6u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[7u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[8u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[9u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[10u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[11u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[12u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[13u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[14u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[15u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[16u][7u]))) / 32u))); + v_z = 0u; + while (v_z < 256u) { + self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][(8u + (v_z & 15u))] = v_avg; + v_z += 1u; + } + } else if (a_mode == 1u) { + v_tm0 = ((uint32_t)(self->private_impl.f_yuv_cache[0u][7u])); + v_z = 0u; + while (v_z < 256u) { + v_tm1 = ((uint32_t)(self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][7u])); + v_tm2 = ((uint32_t)(self->private_impl.f_yuv_cache[0u][(8u + (v_z & 15u))])); + self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][(8u + (v_z & 15u))] = WUFFS_VP8__CLAMP[(((uint32_t)((v_tm1 + v_tm2) - v_tm0)) & 1023u)]; + v_z += 1u; + } + } else if (a_mode == 2u) { + v_x = 0u; + while (v_x < 16u) { + v_val = self->private_impl.f_yuv_cache[0u][(8u + v_x)]; + v_y = 0u; + while (v_y < 16u) { + self->private_impl.f_yuv_cache[(1u + v_y)][(8u + v_x)] = v_val; + v_y += 1u; + } + v_x += 1u; + } + } else if (a_mode == 3u) { + v_y = 0u; + while (v_y < 16u) { + v_val = self->private_impl.f_yuv_cache[(1u + v_y)][7u]; + v_x = 0u; + while (v_x < 16u) { + self->private_impl.f_yuv_cache[(1u + v_y)][(8u + v_x)] = v_val; + v_x += 1u; + } + v_y += 1u; + } + } else if (a_mode <= 10u) { + v_avg = ((uint8_t)(((8u + + ((uint32_t)(self->private_impl.f_yuv_cache[1u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[2u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[3u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[4u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[5u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[6u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[7u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[8u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[9u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[10u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[11u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[12u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[13u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[14u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[15u][7u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[16u][7u]))) / 16u))); + v_z = 0u; + while (v_z < 256u) { + self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][(8u + (v_z & 15u))] = v_avg; + v_z += 1u; + } + } else if (a_mode == 11u) { + v_avg = ((uint8_t)(((8u + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][8u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][9u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][10u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][11u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][12u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][13u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][14u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][15u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][16u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][17u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][18u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][19u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][20u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][21u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][22u])) + + ((uint32_t)(self->private_impl.f_yuv_cache[0u][23u]))) / 16u))); + v_z = 0u; + while (v_z < 256u) { + self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][(8u + (v_z & 15u))] = v_avg; + v_z += 1u; + } + } else { + v_z = 0u; + while (v_z < 256u) { + self->private_impl.f_yuv_cache[(1u + (v_z >> 4u))][(8u + (v_z & 15u))] = 128u; + v_z += 1u; + } + } + return wuffs_base__make_empty_struct(); +} + +// -------- func vp8.decoder.predict_uv8 + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__predict_uv8( + wuffs_vp8__decoder* self, + uint32_t a_b, + uint32_t a_mode) { + uint32_t v_cachey = 0; + uint32_t v_cachex = 0; + uint32_t v_x = 0; + uint32_t v_y = 0; + uint32_t v_z = 0; + uint8_t v_avg = 0; + uint8_t v_val = 0; + uint32_t v_tm0 = 0; + uint32_t v_tm1 = 0; + uint32_t v_tm2 = 0; + + v_cachey = 18u; + v_cachex = ((a_b * 16u) + 8u); + if (a_mode == 0u) { + v_avg = ((uint8_t)(((8u + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 4u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 5u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 6u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 7u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 4u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 5u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 6u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 7u)][(v_cachex - 1u)]))) / 16u))); + v_z = 0u; + while (v_z < 64u) { + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex + (v_z & 7u))] = v_avg; + v_z += 1u; + } + } else if (a_mode == 1u) { + v_tm0 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex - 1u)])); + v_z = 0u; + while (v_z < 64u) { + v_tm1 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex - 1u)])); + v_tm2 = ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + (v_z & 7u))])); + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex + (v_z & 7u))] = WUFFS_VP8__CLAMP[(((uint32_t)((v_tm1 + v_tm2) - v_tm0)) & 1023u)]; + v_z += 1u; + } + } else if (a_mode == 2u) { + v_x = 0u; + while (v_x < 8u) { + v_val = self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + v_x)]; + v_y = 0u; + while (v_y < 8u) { + self->private_impl.f_yuv_cache[(v_cachey + v_y)][(v_cachex + v_x)] = v_val; + v_y += 1u; + } + v_x += 1u; + } + } else if (a_mode == 3u) { + v_y = 0u; + while (v_y < 8u) { + v_val = self->private_impl.f_yuv_cache[(v_cachey + v_y)][(v_cachex - 1u)]; + v_x = 0u; + while (v_x < 8u) { + self->private_impl.f_yuv_cache[(v_cachey + v_y)][(v_cachex + v_x)] = v_val; + v_x += 1u; + } + v_y += 1u; + } + } else if (a_mode <= 10u) { + v_avg = ((uint8_t)(((4u + + ((uint32_t)(self->private_impl.f_yuv_cache[v_cachey][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 1u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 2u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 3u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 4u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 5u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 6u)][(v_cachex - 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey + 7u)][(v_cachex - 1u)]))) / 8u))); + v_z = 0u; + while (v_z < 64u) { + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex + (v_z & 7u))] = v_avg; + v_z += 1u; + } + } else if (a_mode == 11u) { + v_avg = ((uint8_t)(((4u + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][v_cachex])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 1u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 2u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 3u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 4u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 5u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 6u)])) + + ((uint32_t)(self->private_impl.f_yuv_cache[(v_cachey - 1u)][(v_cachex + 7u)]))) / 8u))); + v_z = 0u; + while (v_z < 64u) { + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex + (v_z & 7u))] = v_avg; + v_z += 1u; + } + } else { + v_z = 0u; + while (v_z < 64u) { + self->private_impl.f_yuv_cache[(v_cachey + (v_z >> 3u))][(v_cachex + (v_z & 7u))] = 128u; + v_z += 1u; + } + } + return wuffs_base__make_empty_struct(); +} + +// -------- func vp8.decoder.reconstruct + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__reconstruct( + wuffs_vp8__decoder* self, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_mbx, + uint32_t a_mby, + uint32_t a_luma_mode, + uint32_t a_chroma_mode) { + uint32_t v_mode = 0; + uint32_t v_b = 0; + + wuffs_vp8__decoder__prepare_yuv_cache(self, a_workbuf, a_mbx, a_mby); + if (a_luma_mode < 4u) { + v_mode = wuffs_vp8__decoder__substitute_dc_top_left(self, a_luma_mode, a_mbx, a_mby); + wuffs_vp8__decoder__predict_y16(self, v_mode); + } else { + v_b = 0u; + while (v_b < 16u) { + wuffs_vp8__decoder__predict_y4(self, v_b); + v_b += 1u; + } + } + v_mode = wuffs_vp8__decoder__substitute_dc_top_left(self, a_chroma_mode, a_mbx, a_mby); + wuffs_vp8__decoder__predict_uv8(self, 0u, v_mode); + wuffs_vp8__decoder__predict_uv8(self, 1u, v_mode); + return wuffs_base__make_empty_struct(); +} + +// -------- func vp8.decoder.substitute_dc_top_left + +WUFFS_BASE__GENERATED_C_CODE +static uint32_t +wuffs_vp8__decoder__substitute_dc_top_left( + const wuffs_vp8__decoder* self, + uint32_t a_mode, + uint32_t a_mbx, + uint32_t a_mby) { + if (a_mode == 0u) { + if (a_mby == 0u) { + if (a_mbx == 0u) { + return 11u; + } else { + return 12u; + } + } else if (a_mby == 0u) { + return 10u; + } + } + return a_mode; +} + +// -------- func vp8.decoder.prepare_yuv_cache + +WUFFS_BASE__GENERATED_C_CODE +static wuffs_base__empty_struct +wuffs_vp8__decoder__prepare_yuv_cache( + wuffs_vp8__decoder* self, + wuffs_base__slice_u8 a_workbuf, + uint32_t a_mbx, + uint32_t a_mby) { + uint32_t v_i = 0; + uint32_t v_j = 0; + uint64_t v_offset = 0; + uint64_t v_o = 0; + + if (a_mbx <= 0u) { + v_j = 0u; + while (v_j < 17u) { + self->private_impl.f_yuv_cache[v_j][7u] = 129u; + v_j += 1u; + } + while (v_j < 26u) { + self->private_impl.f_yuv_cache[v_j][7u] = 129u; + self->private_impl.f_yuv_cache[v_j][23u] = 129u; + v_j += 1u; + } + } else { + v_j = 0u; + while (v_j < 17u) { + self->private_impl.f_yuv_cache[v_j][7u] = self->private_impl.f_yuv_cache[v_j][23u]; + v_j += 1u; + } + while (v_j < 26u) { + self->private_impl.f_yuv_cache[v_j][7u] = self->private_impl.f_yuv_cache[v_j][15u]; + self->private_impl.f_yuv_cache[v_j][23u] = self->private_impl.f_yuv_cache[v_j][31u]; + v_j += 1u; + } + } + if (a_mby <= 0u) { + v_i = 0u; + while (v_i < 32u) { + self->private_impl.f_yuv_cache[0u][v_i] = 127u; + v_i += 1u; + } + v_i = 0u; + while (v_i < 32u) { + self->private_impl.f_yuv_cache[17u][v_i] = 127u; + v_i += 1u; + } + } else { + v_offset = ((uint64_t)(((((a_mby - 1u) * self->private_impl.f_workbuf_yuv_y_stride) + a_mbx) * 16u))); + v_i = 0u; + while (v_i < 16u) { + v_o = (v_offset + ((uint64_t)(v_i))); + if (v_o < ((uint64_t)(a_workbuf.len))) { + self->private_impl.f_yuv_cache[0u][(8u + v_i)] = a_workbuf.ptr[v_o]; + } + v_i += 1u; + } + if ((a_mbx + 1u) < self->private_impl.f_mbw) { + while (v_i < 20u) { + v_o = (v_offset + ((uint64_t)(v_i))); + if (v_o < ((uint64_t)(a_workbuf.len))) { + self->private_impl.f_yuv_cache[0u][(8u + v_i)] = a_workbuf.ptr[v_o]; + } + v_i += 1u; + } + } else { + while (v_i < 20u) { + v_o = (v_offset + ((uint64_t)(15u))); + if (v_o < ((uint64_t)(a_workbuf.len))) { + self->private_impl.f_yuv_cache[0u][(8u + v_i)] = a_workbuf.ptr[v_o]; + } + v_i += 1u; + } + } + v_offset = (self->private_impl.f_workbuf_yuv_y_end + ((uint64_t)(((((a_mby - 1u) * self->private_impl.f_workbuf_yuv_uv_stride) + a_mbx) * 8u)))); + v_i = 0u; + while (v_i < 8u) { + v_o = (v_offset + ((uint64_t)(v_i))); + if (v_o < ((uint64_t)(a_workbuf.len))) { + self->private_impl.f_yuv_cache[17u][(8u + v_i)] = a_workbuf.ptr[v_o]; + } + v_i += 1u; + } + v_offset = (self->private_impl.f_workbuf_yuv_u_end + ((uint64_t)(((((a_mby - 1u) * self->private_impl.f_workbuf_yuv_uv_stride) + a_mbx) * 8u)))); + v_i = 0u; + while (v_i < 8u) { + v_o = (v_offset + ((uint64_t)(v_i))); + if (v_o < ((uint64_t)(a_workbuf.len))) { + self->private_impl.f_yuv_cache[17u][(24u + v_i)] = a_workbuf.ptr[v_o]; + } + v_i += 1u; + } + } + v_j = 4u; + while (v_j < 16u) { + self->private_impl.f_yuv_cache[v_j][24u] = self->private_impl.f_yuv_cache[0u][24u]; + self->private_impl.f_yuv_cache[v_j][25u] = self->private_impl.f_yuv_cache[0u][25u]; + self->private_impl.f_yuv_cache[v_j][26u] = self->private_impl.f_yuv_cache[0u][26u]; + self->private_impl.f_yuv_cache[v_j][27u] = self->private_impl.f_yuv_cache[0u][27u]; + v_j += 4u; + } + return wuffs_base__make_empty_struct(); +} + // -------- func vp8.decoder.get_quirk WUFFS_BASE__GENERATED_C_CODE
diff --git a/std/vp8/common_consts.wuffs b/std/vp8/common_consts.wuffs index a849d60..a2e7861 100644 --- a/std/vp8/common_consts.wuffs +++ b/std/vp8/common_consts.wuffs
@@ -111,6 +111,80 @@ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, ] +pri const CLAMP : roarray[1024] base.u8 = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +] + // RFC 6386 Section 11.5. Subblock Mode Probability Table. // // Note that the specification (the RFC) differs from the implementation
diff --git a/std/vp8/decode_coefficients.wuffs b/std/vp8/decode_coefficients.wuffs index fcb718d..42512e2 100644 --- a/std/vp8/decode_coefficients.wuffs +++ b/std/vp8/decode_coefficients.wuffs
@@ -13,8 +13,7 @@ mbx: base.u32[..= 0x3FF], mby: base.u32[..= 0x3FF], seg: base.u32[..= 3], - luma_mode: base.u32[..= 4], - chroma_mode: base.u32[..= 3]) { + luma_mode: base.u32[..= 4]) { var bc : base.u32 var by : base.u32 var bx : base.u32
diff --git a/std/vp8/decode_macroblocks.wuffs b/std/vp8/decode_macroblocks.wuffs index e5359ba..7fbb434 100644 --- a/std/vp8/decode_macroblocks.wuffs +++ b/std/vp8/decode_macroblocks.wuffs
@@ -82,8 +82,12 @@ } else { this.decode_coefficients!( workbuf: args.workbuf, mbx: args.mbx, mby: args.mby, - seg: seg, luma_mode: luma_mode, chroma_mode: chroma_mode) + seg: seg, luma_mode: luma_mode) } + + this.reconstruct!( + workbuf: args.workbuf, mbx: args.mbx, mby: args.mby, + luma_mode: luma_mode, chroma_mode: chroma_mode) } // RFC 6386 Section 11.2. Luma Modes.
diff --git a/std/vp8/decode_predict_default.wuffs b/std/vp8/decode_predict_default.wuffs new file mode 100644 index 0000000..cacf5ca --- /dev/null +++ b/std/vp8/decode_predict_default.wuffs
@@ -0,0 +1,675 @@ +// Copyright 2026 The Wuffs Authors. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// -------- + +// Predicts a 4×4 luma block, the Xs below, based on samples top and left. +// +// a b c d e f g h i +// p X X X X +// q X X X X +// r X X X X +// s X X X X +pri func decoder.predict_y4!(b: base.u32[..= 15]) { + var cachey : base.u32[..= 13] + var cachex : base.u32[..= 20] + var mode : base.u32[..= 9] + var z : base.u32 + + var avg : base.u8 + + var tm0 : base.u32 + var tm1 : base.u32 + var tm2 : base.u32 + + var a : base.u32 + var b : base.u32 + var c : base.u32 + var d : base.u32 + var e : base.u32 + var f : base.u32 + var g : base.u32 + var h : base.u32 + var i : base.u32 + var p : base.u32 + var q : base.u32 + var r : base.u32 + var s : base.u32 + + var ab : base.u8 + var bc : base.u8 + var cd : base.u8 + var de : base.u8 + var ef : base.u8 + var pa : base.u8 + var qp : base.u8 + var rq : base.u8 + var sr : base.u8 + + var abc : base.u8 + var bcd : base.u8 + var cde : base.u8 + var def : base.u8 + var efg : base.u8 + var fgh : base.u8 + var ghi : base.u8 + var hii : base.u8 + var pab : base.u8 + var qpa : base.u8 + var rqp : base.u8 + var srq : base.u8 + var ssr : base.u8 + var sss : base.u8 + + cachey = ((args.b & 0xC) * 1) + 1 + cachex = ((args.b & 0x3) * 4) + 8 + mode = this.mb_subblock_modes[args.b] as base.u32 + + if mode == 0 { // DC. + avg = ((4 + + (this.yuv_cache[cachey - 1][cachex + 0] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 1] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 2] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 3] as base.u32) + + (this.yuv_cache[cachey + 0][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 1][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 2][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 3][cachex - 1] as base.u32)) / 8) as base.u8 + + z = 0 + while z < 16 { + this.yuv_cache[cachey + (z >> 2)][cachex + (z & 3)] = avg + z += 1 + } + + } else if mode == 1 { // TM. + tm0 = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + z = 0 + while z < 16, + inv cachey >= 1, + inv cachex >= 8, + { + tm1 = this.yuv_cache[cachey + (z >> 2)][cachex - 1] as base.u32 + tm2 = this.yuv_cache[cachey - 1][cachex + (z & 3)] as base.u32 + this.yuv_cache[cachey + (z >> 2)][cachex + (z & 3)] = + CLAMP[((tm1 + tm2) ~mod- tm0) & 1023] + z += 1 + } + + } else if mode == 2 { // VE. + a = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + e = this.yuv_cache[cachey - 1][cachex + 3] as base.u32 + f = this.yuv_cache[cachey - 1][cachex + 4] as base.u32 + + def = (((d + (2 * e) + f + 2) / 4) & 0xFF) as base.u8 + cde = (((c + (2 * d) + e + 2) / 4) & 0xFF) as base.u8 + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + abc = (((a + (2 * b) + c + 2) / 4) & 0xFF) as base.u8 + + z = 0 + while z < 4 { + this.yuv_cache[cachey + z][cachex + 0] = abc + this.yuv_cache[cachey + z][cachex + 1] = bcd + this.yuv_cache[cachey + z][cachex + 2] = cde + this.yuv_cache[cachey + z][cachex + 3] = def + z += 1 + } + + } else if mode == 3 { // HE. + s = this.yuv_cache[cachey + 3][cachex - 1] as base.u32 + r = this.yuv_cache[cachey + 2][cachex - 1] as base.u32 + q = this.yuv_cache[cachey + 1][cachex - 1] as base.u32 + p = this.yuv_cache[cachey + 0][cachex - 1] as base.u32 + a = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + + qpa = (((q + (2 * p) + a + 2) / 4) & 0xFF) as base.u8 + rqp = (((r + (2 * q) + p + 2) / 4) & 0xFF) as base.u8 + srq = (((s + (2 * r) + q + 2) / 4) & 0xFF) as base.u8 + ssr = (((s + (2 * s) + r + 2) / 4) & 0xFF) as base.u8 + + z = 0 + while z < 4 { + this.yuv_cache[cachey + 0][cachex + z] = qpa + this.yuv_cache[cachey + 1][cachex + z] = rqp + this.yuv_cache[cachey + 2][cachex + z] = srq + this.yuv_cache[cachey + 3][cachex + z] = ssr + z += 1 + } + + } else if mode == 4 { // RD. + s = this.yuv_cache[cachey + 3][cachex - 1] as base.u32 + r = this.yuv_cache[cachey + 2][cachex - 1] as base.u32 + q = this.yuv_cache[cachey + 1][cachex - 1] as base.u32 + p = this.yuv_cache[cachey + 0][cachex - 1] as base.u32 + a = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + e = this.yuv_cache[cachey - 1][cachex + 3] as base.u32 + + cde = (((c + (2 * d) + e + 2) / 4) & 0xFF) as base.u8 + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + abc = (((a + (2 * b) + c + 2) / 4) & 0xFF) as base.u8 + pab = (((p + (2 * a) + b + 2) / 4) & 0xFF) as base.u8 + qpa = (((q + (2 * p) + a + 2) / 4) & 0xFF) as base.u8 + rqp = (((r + (2 * q) + p + 2) / 4) & 0xFF) as base.u8 + srq = (((s + (2 * r) + q + 2) / 4) & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = pab + this.yuv_cache[cachey + 0][cachex + 1] = abc + this.yuv_cache[cachey + 0][cachex + 2] = bcd + this.yuv_cache[cachey + 0][cachex + 3] = cde + + this.yuv_cache[cachey + 1][cachex + 0] = qpa + this.yuv_cache[cachey + 1][cachex + 1] = pab + this.yuv_cache[cachey + 1][cachex + 2] = abc + this.yuv_cache[cachey + 1][cachex + 3] = bcd + + this.yuv_cache[cachey + 2][cachex + 0] = rqp + this.yuv_cache[cachey + 2][cachex + 1] = qpa + this.yuv_cache[cachey + 2][cachex + 2] = pab + this.yuv_cache[cachey + 2][cachex + 3] = abc + + this.yuv_cache[cachey + 3][cachex + 0] = srq + this.yuv_cache[cachey + 3][cachex + 1] = rqp + this.yuv_cache[cachey + 3][cachex + 2] = qpa + this.yuv_cache[cachey + 3][cachex + 3] = pab + + } else if mode == 5 { // VR. + r = this.yuv_cache[cachey + 2][cachex - 1] as base.u32 + q = this.yuv_cache[cachey + 1][cachex - 1] as base.u32 + p = this.yuv_cache[cachey + 0][cachex - 1] as base.u32 + a = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + e = this.yuv_cache[cachey - 1][cachex + 3] as base.u32 + + ab = (((a + b + 1) / 2) & 0xFF) as base.u8 + bc = (((b + c + 1) / 2) & 0xFF) as base.u8 + cd = (((c + d + 1) / 2) & 0xFF) as base.u8 + de = (((d + e + 1) / 2) & 0xFF) as base.u8 + + cde = (((c + (2 * d) + e + 2) / 4) & 0xFF) as base.u8 + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + abc = (((a + (2 * b) + c + 2) / 4) & 0xFF) as base.u8 + pab = (((p + (2 * a) + b + 2) / 4) & 0xFF) as base.u8 + qpa = (((q + (2 * p) + a + 2) / 4) & 0xFF) as base.u8 + rqp = (((r + (2 * q) + p + 2) / 4) & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = ab + this.yuv_cache[cachey + 0][cachex + 1] = bc + this.yuv_cache[cachey + 0][cachex + 2] = cd + this.yuv_cache[cachey + 0][cachex + 3] = de + + this.yuv_cache[cachey + 1][cachex + 0] = pab + this.yuv_cache[cachey + 1][cachex + 1] = abc + this.yuv_cache[cachey + 1][cachex + 2] = bcd + this.yuv_cache[cachey + 1][cachex + 3] = cde + + this.yuv_cache[cachey + 2][cachex + 0] = qpa + this.yuv_cache[cachey + 2][cachex + 1] = ab + this.yuv_cache[cachey + 2][cachex + 2] = bc + this.yuv_cache[cachey + 2][cachex + 3] = cd + + this.yuv_cache[cachey + 3][cachex + 0] = rqp + this.yuv_cache[cachey + 3][cachex + 1] = pab + this.yuv_cache[cachey + 3][cachex + 2] = abc + this.yuv_cache[cachey + 3][cachex + 3] = bcd + + } else if mode == 6 { // LD. + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + e = this.yuv_cache[cachey - 1][cachex + 3] as base.u32 + f = this.yuv_cache[cachey - 1][cachex + 4] as base.u32 + g = this.yuv_cache[cachey - 1][cachex + 5] as base.u32 + h = this.yuv_cache[cachey - 1][cachex + 6] as base.u32 + i = this.yuv_cache[cachey - 1][cachex + 7] as base.u32 + + hii = (((h + (2 * i) + i + 2) / 4) & 0xFF) as base.u8 + ghi = (((g + (2 * h) + i + 2) / 4) & 0xFF) as base.u8 + fgh = (((f + (2 * g) + h + 2) / 4) & 0xFF) as base.u8 + efg = (((e + (2 * f) + g + 2) / 4) & 0xFF) as base.u8 + def = (((d + (2 * e) + f + 2) / 4) & 0xFF) as base.u8 + cde = (((c + (2 * d) + e + 2) / 4) & 0xFF) as base.u8 + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = bcd + this.yuv_cache[cachey + 0][cachex + 1] = cde + this.yuv_cache[cachey + 0][cachex + 2] = def + this.yuv_cache[cachey + 0][cachex + 3] = efg + + this.yuv_cache[cachey + 1][cachex + 0] = cde + this.yuv_cache[cachey + 1][cachex + 1] = def + this.yuv_cache[cachey + 1][cachex + 2] = efg + this.yuv_cache[cachey + 1][cachex + 3] = fgh + + this.yuv_cache[cachey + 2][cachex + 0] = def + this.yuv_cache[cachey + 2][cachex + 1] = efg + this.yuv_cache[cachey + 2][cachex + 2] = fgh + this.yuv_cache[cachey + 2][cachex + 3] = ghi + + this.yuv_cache[cachey + 3][cachex + 0] = efg + this.yuv_cache[cachey + 3][cachex + 1] = fgh + this.yuv_cache[cachey + 3][cachex + 2] = ghi + this.yuv_cache[cachey + 3][cachex + 3] = hii + + } else if mode == 7 { // VL. + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + e = this.yuv_cache[cachey - 1][cachex + 3] as base.u32 + f = this.yuv_cache[cachey - 1][cachex + 4] as base.u32 + g = this.yuv_cache[cachey - 1][cachex + 5] as base.u32 + h = this.yuv_cache[cachey - 1][cachex + 6] as base.u32 + i = this.yuv_cache[cachey - 1][cachex + 7] as base.u32 + + ef = (((e + f + 1) / 2) & 0xFF) as base.u8 + de = (((d + e + 1) / 2) & 0xFF) as base.u8 + cd = (((c + d + 1) / 2) & 0xFF) as base.u8 + bc = (((b + c + 1) / 2) & 0xFF) as base.u8 + + ghi = (((g + (2 * h) + i + 2) / 4) & 0xFF) as base.u8 + fgh = (((f + (2 * g) + h + 2) / 4) & 0xFF) as base.u8 + efg = (((e + (2 * f) + g + 2) / 4) & 0xFF) as base.u8 + def = (((d + (2 * e) + f + 2) / 4) & 0xFF) as base.u8 + cde = (((c + (2 * d) + e + 2) / 4) & 0xFF) as base.u8 + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = bc + this.yuv_cache[cachey + 0][cachex + 1] = cd + this.yuv_cache[cachey + 0][cachex + 2] = de + this.yuv_cache[cachey + 0][cachex + 3] = ef + + this.yuv_cache[cachey + 1][cachex + 0] = bcd + this.yuv_cache[cachey + 1][cachex + 1] = cde + this.yuv_cache[cachey + 1][cachex + 2] = def + this.yuv_cache[cachey + 1][cachex + 3] = efg + + this.yuv_cache[cachey + 2][cachex + 0] = cd + this.yuv_cache[cachey + 2][cachex + 1] = de + this.yuv_cache[cachey + 2][cachex + 2] = ef + this.yuv_cache[cachey + 2][cachex + 3] = fgh + + this.yuv_cache[cachey + 3][cachex + 0] = cde + this.yuv_cache[cachey + 3][cachex + 1] = def + this.yuv_cache[cachey + 3][cachex + 2] = efg + this.yuv_cache[cachey + 3][cachex + 3] = ghi + + } else if mode == 8 { // HD. + s = this.yuv_cache[cachey + 3][cachex - 1] as base.u32 + r = this.yuv_cache[cachey + 2][cachex - 1] as base.u32 + q = this.yuv_cache[cachey + 1][cachex - 1] as base.u32 + p = this.yuv_cache[cachey + 0][cachex - 1] as base.u32 + a = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + b = this.yuv_cache[cachey - 1][cachex + 0] as base.u32 + c = this.yuv_cache[cachey - 1][cachex + 1] as base.u32 + d = this.yuv_cache[cachey - 1][cachex + 2] as base.u32 + + sr = (((s + r + 1) / 2) & 0xFF) as base.u8 + rq = (((r + q + 1) / 2) & 0xFF) as base.u8 + qp = (((q + p + 1) / 2) & 0xFF) as base.u8 + pa = (((p + a + 1) / 2) & 0xFF) as base.u8 + + bcd = (((b + (2 * c) + d + 2) / 4) & 0xFF) as base.u8 + abc = (((a + (2 * b) + c + 2) / 4) & 0xFF) as base.u8 + pab = (((p + (2 * a) + b + 2) / 4) & 0xFF) as base.u8 + qpa = (((q + (2 * p) + a + 2) / 4) & 0xFF) as base.u8 + rqp = (((r + (2 * q) + p + 2) / 4) & 0xFF) as base.u8 + srq = (((s + (2 * r) + q + 2) / 4) & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = pa + this.yuv_cache[cachey + 0][cachex + 1] = pab + this.yuv_cache[cachey + 0][cachex + 2] = abc + this.yuv_cache[cachey + 0][cachex + 3] = bcd + + this.yuv_cache[cachey + 1][cachex + 0] = qp + this.yuv_cache[cachey + 1][cachex + 1] = qpa + this.yuv_cache[cachey + 1][cachex + 2] = pa + this.yuv_cache[cachey + 1][cachex + 3] = pab + + this.yuv_cache[cachey + 2][cachex + 0] = rq + this.yuv_cache[cachey + 2][cachex + 1] = rqp + this.yuv_cache[cachey + 2][cachex + 2] = qp + this.yuv_cache[cachey + 2][cachex + 3] = qpa + + this.yuv_cache[cachey + 3][cachex + 0] = sr + this.yuv_cache[cachey + 3][cachex + 1] = srq + this.yuv_cache[cachey + 3][cachex + 2] = rq + this.yuv_cache[cachey + 3][cachex + 3] = rqp + + } else { // HU. + s = this.yuv_cache[cachey + 3][cachex - 1] as base.u32 + r = this.yuv_cache[cachey + 2][cachex - 1] as base.u32 + q = this.yuv_cache[cachey + 1][cachex - 1] as base.u32 + p = this.yuv_cache[cachey + 0][cachex - 1] as base.u32 + + sr = (((s + r + 1) / 2) & 0xFF) as base.u8 + rq = (((r + q + 1) / 2) & 0xFF) as base.u8 + qp = (((q + p + 1) / 2) & 0xFF) as base.u8 + + rqp = (((r + (2 * q) + p + 2) / 4) & 0xFF) as base.u8 + srq = (((s + (2 * r) + q + 2) / 4) & 0xFF) as base.u8 + ssr = (((s + (2 * s) + r + 2) / 4) & 0xFF) as base.u8 + sss = (s & 0xFF) as base.u8 + + this.yuv_cache[cachey + 0][cachex + 0] = qp + this.yuv_cache[cachey + 0][cachex + 1] = rqp + this.yuv_cache[cachey + 0][cachex + 2] = rq + this.yuv_cache[cachey + 0][cachex + 3] = srq + + this.yuv_cache[cachey + 1][cachex + 0] = rq + this.yuv_cache[cachey + 1][cachex + 1] = srq + this.yuv_cache[cachey + 1][cachex + 2] = sr + this.yuv_cache[cachey + 1][cachex + 3] = ssr + + this.yuv_cache[cachey + 2][cachex + 0] = sr + this.yuv_cache[cachey + 2][cachex + 1] = ssr + this.yuv_cache[cachey + 2][cachex + 2] = sss + this.yuv_cache[cachey + 2][cachex + 3] = sss + + this.yuv_cache[cachey + 3][cachex + 0] = sss + this.yuv_cache[cachey + 3][cachex + 1] = sss + this.yuv_cache[cachey + 3][cachex + 2] = sss + this.yuv_cache[cachey + 3][cachex + 3] = sss + } +} + +pri func decoder.predict_y16!(mode: base.u32[..= 12]) { + var x : base.u32 + var y : base.u32 + var z : base.u32 + + var avg : base.u8 + var val : base.u8 + + var tm0 : base.u32 + var tm1 : base.u32 + var tm2 : base.u32 + + if args.mode == 0 { // DC. + avg = ((16 + + (this.yuv_cache[0x00][0x08] as base.u32) + + (this.yuv_cache[0x00][0x09] as base.u32) + + (this.yuv_cache[0x00][0x0A] as base.u32) + + (this.yuv_cache[0x00][0x0B] as base.u32) + + (this.yuv_cache[0x00][0x0C] as base.u32) + + (this.yuv_cache[0x00][0x0D] as base.u32) + + (this.yuv_cache[0x00][0x0E] as base.u32) + + (this.yuv_cache[0x00][0x0F] as base.u32) + + (this.yuv_cache[0x00][0x10] as base.u32) + + (this.yuv_cache[0x00][0x11] as base.u32) + + (this.yuv_cache[0x00][0x12] as base.u32) + + (this.yuv_cache[0x00][0x13] as base.u32) + + (this.yuv_cache[0x00][0x14] as base.u32) + + (this.yuv_cache[0x00][0x15] as base.u32) + + (this.yuv_cache[0x00][0x16] as base.u32) + + (this.yuv_cache[0x00][0x17] as base.u32) + + (this.yuv_cache[0x01][0x07] as base.u32) + + (this.yuv_cache[0x02][0x07] as base.u32) + + (this.yuv_cache[0x03][0x07] as base.u32) + + (this.yuv_cache[0x04][0x07] as base.u32) + + (this.yuv_cache[0x05][0x07] as base.u32) + + (this.yuv_cache[0x06][0x07] as base.u32) + + (this.yuv_cache[0x07][0x07] as base.u32) + + (this.yuv_cache[0x08][0x07] as base.u32) + + (this.yuv_cache[0x09][0x07] as base.u32) + + (this.yuv_cache[0x0A][0x07] as base.u32) + + (this.yuv_cache[0x0B][0x07] as base.u32) + + (this.yuv_cache[0x0C][0x07] as base.u32) + + (this.yuv_cache[0x0D][0x07] as base.u32) + + (this.yuv_cache[0x0E][0x07] as base.u32) + + (this.yuv_cache[0x0F][0x07] as base.u32) + + (this.yuv_cache[0x10][0x07] as base.u32)) / 32) as base.u8 + + z = 0 + while z < 256 { + this.yuv_cache[0x01 + (z >> 4)][0x08 + (z & 15)] = avg + z += 1 + } + + } else if args.mode == 1 { // TM. + tm0 = this.yuv_cache[0x00][0x07] as base.u32 + z = 0 + while z < 256 { + tm1 = this.yuv_cache[0x01 + (z >> 4)][0x07] as base.u32 + tm2 = this.yuv_cache[0x00][0x08 + (z & 15)] as base.u32 + this.yuv_cache[0x01 + (z >> 4)][0x08 + (z & 15)] = + CLAMP[((tm1 + tm2) ~mod- tm0) & 1023] + z += 1 + } + + } else if args.mode == 2 { // VE. + x = 0 + while x < 16 { + val = this.yuv_cache[0x00][0x08 + x] + y = 0 + while y < 16, + inv x < 16, + { + this.yuv_cache[0x01 + y][0x08 + x] = val + y += 1 + } + x += 1 + } + + } else if args.mode == 3 { // HE. + y = 0 + while y < 16 { + val = this.yuv_cache[0x01 + y][0x07] + x = 0 + while x < 16, + inv y < 16, + { + this.yuv_cache[0x01 + y][0x08 + x] = val + x += 1 + } + y += 1 + } + + } else if args.mode <= 10 { // DCTop. + avg = ((8 + + (this.yuv_cache[0x01][0x07] as base.u32) + + (this.yuv_cache[0x02][0x07] as base.u32) + + (this.yuv_cache[0x03][0x07] as base.u32) + + (this.yuv_cache[0x04][0x07] as base.u32) + + (this.yuv_cache[0x05][0x07] as base.u32) + + (this.yuv_cache[0x06][0x07] as base.u32) + + (this.yuv_cache[0x07][0x07] as base.u32) + + (this.yuv_cache[0x08][0x07] as base.u32) + + (this.yuv_cache[0x09][0x07] as base.u32) + + (this.yuv_cache[0x0A][0x07] as base.u32) + + (this.yuv_cache[0x0B][0x07] as base.u32) + + (this.yuv_cache[0x0C][0x07] as base.u32) + + (this.yuv_cache[0x0D][0x07] as base.u32) + + (this.yuv_cache[0x0E][0x07] as base.u32) + + (this.yuv_cache[0x0F][0x07] as base.u32) + + (this.yuv_cache[0x10][0x07] as base.u32)) / 16) as base.u8 + + z = 0 + while z < 256 { + this.yuv_cache[0x01 + (z >> 4)][0x08 + (z & 15)] = avg + z += 1 + } + + } else if args.mode == 11 { // DCLeft. + avg = ((8 + + (this.yuv_cache[0x00][0x08] as base.u32) + + (this.yuv_cache[0x00][0x09] as base.u32) + + (this.yuv_cache[0x00][0x0A] as base.u32) + + (this.yuv_cache[0x00][0x0B] as base.u32) + + (this.yuv_cache[0x00][0x0C] as base.u32) + + (this.yuv_cache[0x00][0x0D] as base.u32) + + (this.yuv_cache[0x00][0x0E] as base.u32) + + (this.yuv_cache[0x00][0x0F] as base.u32) + + (this.yuv_cache[0x00][0x10] as base.u32) + + (this.yuv_cache[0x00][0x11] as base.u32) + + (this.yuv_cache[0x00][0x12] as base.u32) + + (this.yuv_cache[0x00][0x13] as base.u32) + + (this.yuv_cache[0x00][0x14] as base.u32) + + (this.yuv_cache[0x00][0x15] as base.u32) + + (this.yuv_cache[0x00][0x16] as base.u32) + + (this.yuv_cache[0x00][0x17] as base.u32)) / 16) as base.u8 + + z = 0 + while z < 256 { + this.yuv_cache[0x01 + (z >> 4)][0x08 + (z & 15)] = avg + z += 1 + } + + } else { // DCTopLeft. + z = 0 + while z < 256 { + this.yuv_cache[0x01 + (z >> 4)][0x08 + (z & 15)] = 0x80 + z += 1 + } + } +} + +pri func decoder.predict_uv8!(b: base.u32[..= 1], mode: base.u32[..= 12]) { + var cachey : base.u32[..= 18] + var cachex : base.u32[..= 24] + var x : base.u32 + var y : base.u32 + var z : base.u32 + + var avg : base.u8 + var val : base.u8 + + var tm0 : base.u32 + var tm1 : base.u32 + var tm2 : base.u32 + + cachey = 0x12 + cachex = (args.b * 16) + 8 + + if args.mode == 0 { // DC. + avg = ((8 + + (this.yuv_cache[cachey - 1][cachex + 0] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 1] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 2] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 3] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 4] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 5] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 6] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 7] as base.u32) + + (this.yuv_cache[cachey + 0][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 1][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 2][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 3][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 4][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 5][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 6][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 7][cachex - 1] as base.u32)) / 16) as base.u8 + + z = 0 + while z < 64 { + this.yuv_cache[cachey + (z >> 3)][cachex + (z & 7)] = avg + z += 1 + } + + } else if args.mode == 1 { // TM. + tm0 = this.yuv_cache[cachey - 1][cachex - 1] as base.u32 + z = 0 + while z < 64, + inv cachey == 0x12, + inv cachex >= 8, + { + tm1 = this.yuv_cache[cachey + (z >> 3)][cachex - 1] as base.u32 + tm2 = this.yuv_cache[cachey - 1][cachex + (z & 7)] as base.u32 + this.yuv_cache[cachey + (z >> 3)][cachex + (z & 7)] = + CLAMP[((tm1 + tm2) ~mod- tm0) & 1023] + z += 1 + } + + } else if args.mode == 2 { // VE. + x = 0 + while x < 8, + inv cachey == 0x12, + inv cachex >= 8, + { + val = this.yuv_cache[cachey - 1][cachex + x] + y = 0 + while y < 8, + inv cachey == 0x12, + inv cachex >= 8, + inv x < 8, + { + this.yuv_cache[cachey + y][cachex + x] = val + y += 1 + } + x += 1 + } + + } else if args.mode == 3 { // HE. + y = 0 + while y < 8, + inv cachey == 0x12, + inv cachex >= 8, + { + val = this.yuv_cache[cachey + y][cachex - 1] + x = 0 + while x < 8, + inv cachey == 0x12, + inv cachex >= 8, + inv y < 8, + { + this.yuv_cache[cachey + y][cachex + x] = val + x += 1 + } + y += 1 + } + + } else if args.mode <= 10 { // DCTop. + avg = ((4 + + (this.yuv_cache[cachey + 0][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 1][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 2][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 3][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 4][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 5][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 6][cachex - 1] as base.u32) + + (this.yuv_cache[cachey + 7][cachex - 1] as base.u32)) / 8) as base.u8 + + z = 0 + while z < 64 { + this.yuv_cache[cachey + (z >> 3)][cachex + (z & 7)] = avg + z += 1 + } + + } else if args.mode == 11 { // DCLeft. + avg = ((4 + + (this.yuv_cache[cachey - 1][cachex + 0] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 1] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 2] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 3] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 4] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 5] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 6] as base.u32) + + (this.yuv_cache[cachey - 1][cachex + 7] as base.u32)) / 8) as base.u8 + + z = 0 + while z < 64 { + this.yuv_cache[cachey + (z >> 3)][cachex + (z & 7)] = avg + z += 1 + } + + } else { // DCTopLeft. + z = 0 + while z < 64 { + this.yuv_cache[cachey + (z >> 3)][cachex + (z & 7)] = 0x80 + z += 1 + } + } +}
diff --git a/std/vp8/decode_reconstruct.wuffs b/std/vp8/decode_reconstruct.wuffs new file mode 100644 index 0000000..fbaa8a9 --- /dev/null +++ b/std/vp8/decode_reconstruct.wuffs
@@ -0,0 +1,176 @@ +// Copyright 2026 The Wuffs Authors. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + +pri func decoder.reconstruct!( + workbuf: slice base.u8, + mbx: base.u32[..= 0x3FF], + mby: base.u32[..= 0x3FF], + luma_mode: base.u32[..= 4], + chroma_mode: base.u32[..= 3]) { + var mode : base.u32[..= 12] + var b : base.u32 + + this.prepare_yuv_cache!(workbuf: args.workbuf, mbx: args.mbx, mby: args.mby) + + if args.luma_mode < 4 { + mode = this.substitute_dc_top_left(mode: args.luma_mode, mbx: args.mbx, mby: args.mby) + this.predict_y16!(mode: mode) + + } else { + b = 0 + while b < 16 { + this.predict_y4!(b: b) + b += 1 + } + } + + mode = this.substitute_dc_top_left(mode: args.chroma_mode, mbx: args.mbx, mby: args.mby) + + this.predict_uv8!(b: 0, mode: mode) + + this.predict_uv8!(b: 1, mode: mode) +} + +pri func decoder.substitute_dc_top_left( + mode: base.u32[..= 3], + mbx: base.u32[..= 0x3FF], + mby: base.u32[..= 0x3FF]) base.u32[..= 12] { + if args.mode == 0 { // DC. + if args.mby == 0 { + if args.mbx == 0 { + return 11 // DCLeft. + } else { + return 12 // DCTopLeft. + } + } else if args.mby == 0 { + return 10 // DCTop. + } + } + return args.mode +} + +pri func decoder.prepare_yuv_cache!( + workbuf: roslice base.u8, + mbx: base.u32[..= 0x3FF], + mby: base.u32[..= 0x3FF]) { + var i : base.u32 + var j : base.u32 + var offset : base.u64[..= 0x17FE_1FF8] + var o : base.u64 + + if args.mbx <= 0 { + j = 0x00 + while j < 0x11 { + this.yuv_cache[j][0x07] = 0x81 + j += 1 + } + while j < 0x1A { + this.yuv_cache[j][0x07] = 0x81 + this.yuv_cache[j][0x17] = 0x81 + j += 1 + } + + } else { + j = 0x00 + while j < 0x11 { + this.yuv_cache[j][0x07] = this.yuv_cache[j][0x17] + j += 1 + } + while j < 0x1A { + this.yuv_cache[j][0x07] = this.yuv_cache[j][0x0F] + this.yuv_cache[j][0x17] = this.yuv_cache[j][0x1F] + j += 1 + } + } + + if args.mby <= 0 { + i = 0x00 + while i < 0x20 { + this.yuv_cache[0x00][i] = 0x7F + i += 1 + } + i = 0x00 + while i < 0x20 { + this.yuv_cache[0x11][i] = 0x7F + i += 1 + } + + } else { + offset = 0 + + (((((args.mby - 1) * this.workbuf_yuv_y_stride) + args.mbx) * 16) as base.u64) + i = 0x00 + while i < 0x10, + inv args.mby > 0, + { + o = offset + (i as base.u64) + if o < args.workbuf.length() { + this.yuv_cache[0x00][0x08 + i] = args.workbuf[o] + } + i += 1 + } + + if (args.mbx + 1) < this.mbw { + while i < 0x14, + inv args.mby > 0, + { + o = offset + (i as base.u64) + if o < args.workbuf.length() { + this.yuv_cache[0x00][0x08 + i] = args.workbuf[o] + } + i += 1 + } + } else { + while i < 0x14, + inv args.mby > 0, + { + o = offset + (0x0F as base.u64) + if o < args.workbuf.length() { + this.yuv_cache[0x00][0x08 + i] = args.workbuf[o] + } + i += 1 + } + } + + offset = this.workbuf_yuv_y_end + + (((((args.mby - 1) * this.workbuf_yuv_uv_stride) + args.mbx) * 8) as base.u64) + i = 0x00 + while i < 0x08, + inv args.mby > 0, + { + o = offset + (i as base.u64) + if o < args.workbuf.length() { + this.yuv_cache[0x11][0x08 + i] = args.workbuf[o] + } + i += 1 + } + + offset = this.workbuf_yuv_u_end + + (((((args.mby - 1) * this.workbuf_yuv_uv_stride) + args.mbx) * 8) as base.u64) + i = 0x00 + while i < 0x08, + inv args.mby > 0, + { + o = offset + (i as base.u64) + if o < args.workbuf.length() { + this.yuv_cache[0x11][0x18 + i] = args.workbuf[o] + } + i += 1 + } + } + + j = 0x04 + while j < 0x10 { + this.yuv_cache[j][0x18] = this.yuv_cache[0][0x18] + this.yuv_cache[j][0x19] = this.yuv_cache[0][0x19] + this.yuv_cache[j][0x1A] = this.yuv_cache[0][0x1A] + this.yuv_cache[j][0x1B] = this.yuv_cache[0][0x1B] + j += 4 + } +}
diff --git a/std/vp8/decode_vp8.wuffs b/std/vp8/decode_vp8.wuffs index 67a247e..a374bb3 100644 --- a/std/vp8/decode_vp8.wuffs +++ b/std/vp8/decode_vp8.wuffs
@@ -100,6 +100,8 @@ mb_subblock_modes : array[16] base.u8[..= 9], + yuv_cache : array[26] array[32] base.u8, + dst_x : base.u32, dst_y : base.u32,
diff --git a/test/c/std/vp8.c b/test/c/std/vp8.c index 6d4eeb9..bcd3a4f 100644 --- a/test/c/std/vp8.c +++ b/test/c/std/vp8.c
@@ -65,7 +65,296 @@ // ---------------- VP8 Tests -// No VP8 tests. +void // +initialize_decoder_test_state(wuffs_vp8__decoder* dec) { + // Initialize the top and left luma (Y) pixels to the digits of pi. + + dec->private_impl.f_yuv_cache[0x00][0x07] = 0x31; + dec->private_impl.f_yuv_cache[0x00][0x08] = 0x41; + dec->private_impl.f_yuv_cache[0x00][0x09] = 0x59; + dec->private_impl.f_yuv_cache[0x00][0x0A] = 0x26; + dec->private_impl.f_yuv_cache[0x00][0x0B] = 0x53; + dec->private_impl.f_yuv_cache[0x00][0x0C] = 0x58; + dec->private_impl.f_yuv_cache[0x00][0x0D] = 0x97; + dec->private_impl.f_yuv_cache[0x00][0x0E] = 0x93; + dec->private_impl.f_yuv_cache[0x00][0x0F] = 0x23; + dec->private_impl.f_yuv_cache[0x00][0x10] = 0x84; + dec->private_impl.f_yuv_cache[0x00][0x11] = 0x62; + dec->private_impl.f_yuv_cache[0x00][0x12] = 0x64; + dec->private_impl.f_yuv_cache[0x00][0x13] = 0x33; + dec->private_impl.f_yuv_cache[0x00][0x14] = 0x83; + dec->private_impl.f_yuv_cache[0x00][0x15] = 0x27; + dec->private_impl.f_yuv_cache[0x00][0x16] = 0x95; + dec->private_impl.f_yuv_cache[0x00][0x17] = 0x02; + + dec->private_impl.f_yuv_cache[0x01][0x07] = 0x88; + dec->private_impl.f_yuv_cache[0x02][0x07] = 0x41; + dec->private_impl.f_yuv_cache[0x03][0x07] = 0x97; + dec->private_impl.f_yuv_cache[0x04][0x07] = 0x16; + dec->private_impl.f_yuv_cache[0x05][0x07] = 0x93; + dec->private_impl.f_yuv_cache[0x06][0x07] = 0x99; + dec->private_impl.f_yuv_cache[0x07][0x07] = 0x37; + dec->private_impl.f_yuv_cache[0x08][0x07] = 0x51; + dec->private_impl.f_yuv_cache[0x09][0x07] = 0x05; + dec->private_impl.f_yuv_cache[0x0A][0x07] = 0x82; + dec->private_impl.f_yuv_cache[0x0B][0x07] = 0x09; + dec->private_impl.f_yuv_cache[0x0C][0x07] = 0x74; + dec->private_impl.f_yuv_cache[0x0D][0x07] = 0x94; + dec->private_impl.f_yuv_cache[0x0E][0x07] = 0x45; + dec->private_impl.f_yuv_cache[0x0F][0x07] = 0x92; + dec->private_impl.f_yuv_cache[0x10][0x07] = 0x30; + + // Initialize the top and left chroma-blue (U) pixels to the digits of e. + + dec->private_impl.f_yuv_cache[0x11][0x07] = 0x27; + dec->private_impl.f_yuv_cache[0x11][0x08] = 0x18; + dec->private_impl.f_yuv_cache[0x11][0x09] = 0x28; + dec->private_impl.f_yuv_cache[0x11][0x0A] = 0x18; + dec->private_impl.f_yuv_cache[0x11][0x0B] = 0x28; + dec->private_impl.f_yuv_cache[0x11][0x0C] = 0x45; + dec->private_impl.f_yuv_cache[0x11][0x0D] = 0x90; + dec->private_impl.f_yuv_cache[0x11][0x0E] = 0x45; + dec->private_impl.f_yuv_cache[0x11][0x0F] = 0x23; + + dec->private_impl.f_yuv_cache[0x12][0x07] = 0x53; + dec->private_impl.f_yuv_cache[0x13][0x07] = 0x60; + dec->private_impl.f_yuv_cache[0x14][0x07] = 0x28; + dec->private_impl.f_yuv_cache[0x15][0x07] = 0x74; + dec->private_impl.f_yuv_cache[0x16][0x07] = 0x71; + dec->private_impl.f_yuv_cache[0x17][0x07] = 0x35; + dec->private_impl.f_yuv_cache[0x18][0x07] = 0x26; + dec->private_impl.f_yuv_cache[0x19][0x07] = 0x62; +} + +const char* // +test_wuffs_vp8_decode_predict_uv8() { + CHECK_FOCUS(__func__); + + const uint64_t test_cases[13][8] = { + {0x4444444444444444, 0x4444444444444444, 0x4444444444444444, + 0x4444444444444444, 0x4444444444444444, 0x4444444444444444, + 0x4444444444444444, 0x4444444444444444}, + {0x4454445471BC714F, 0x516151617EC97E5C, 0x1929192946914624, + 0x6575657592DD9270, 0x627262728FDA8F6D, 0x26362636539E5331, + 0x17271727448F4422, 0x5363536380CB805E}, + {0x1828182845904523, 0x1828182845904523, 0x1828182845904523, + 0x1828182845904523, 0x1828182845904523, 0x1828182845904523, + 0x1828182845904523, 0x1828182845904523}, + {0x5353535353535353, 0x6060606060606060, 0x2828282828282828, + 0x7474747474747474, 0x7171717171717171, 0x3535353535353535, + 0x2626262626262626, 0x6262626262626262}, + + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + + {0x5050505050505050, 0x5050505050505050, 0x5050505050505050, + 0x5050505050505050, 0x5050505050505050, 0x5050505050505050, + 0x5050505050505050, 0x5050505050505050}, + {0x3838383838383838, 0x3838383838383838, 0x3838383838383838, + 0x3838383838383838, 0x3838383838383838, 0x3838383838383838, + 0x3838383838383838, 0x3838383838383838}, + {0x8080808080808080, 0x8080808080808080, 0x8080808080808080, + 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, + 0x8080808080808080, 0x8080808080808080}, + }; + + wuffs_vp8__decoder dec = {0}; + for (int mode = 0; mode < 13; mode++) { + uint64_t w0 = test_cases[mode][0]; + uint64_t w1 = test_cases[mode][1]; + uint64_t w2 = test_cases[mode][2]; + uint64_t w3 = test_cases[mode][3]; + uint64_t w4 = test_cases[mode][4]; + uint64_t w5 = test_cases[mode][5]; + uint64_t w6 = test_cases[mode][6]; + uint64_t w7 = test_cases[mode][7]; + + if (w0 == 0) { + continue; + } + + initialize_decoder_test_state(&dec); + + wuffs_vp8__decoder__predict_uv8(&dec, 0, mode); + + uint64_t h0 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x12][8]); + uint64_t h1 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x13][8]); + uint64_t h2 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x14][8]); + uint64_t h3 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x15][8]); + uint64_t h4 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x16][8]); + uint64_t h5 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x17][8]); + uint64_t h6 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x18][8]); + uint64_t h7 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x19][8]); + + if ((h0 != w0) || (h1 != w1) || (h2 != w2) || (h3 != w3) || // + (h4 != w4) || (h5 != w5) || (h6 != w6) || (h7 != w7)) { + RETURN_FAIL( + "mode=%d:" // + "\nhave %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + "\nwant %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64, // + mode, h0, h1, h2, h3, h4, h5, h6, h7, w0, w1, w2, w3, w4, w5, w6, w7); + } + } + + return NULL; +} + +const char* // +test_wuffs_vp8_decode_predict_y16() { + CHECK_FOCUS(__func__); + + const uint64_t test_cases[13][9] = { + + {0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A, + 0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A, 0x5A5A5A5A5A5A5A5A}, + {0x98B07DAAAFEEEA7A, 0x5169366368A7A333, 0xA7BF8CB9BEFDF989, + 0x263E0B383D7C7808, 0xA3BB88B5BAF9F585, 0xA9C18EBBC0FFFB8B, + 0x475F2C595E9D9929, 0x6179467378B7B343, 0x152D00272C6B6700}, + {0x4159265358979323, 0x4159265358979323, 0x4159265358979323, + 0x4159265358979323, 0x4159265358979323, 0x4159265358979323, + 0x4159265358979323, 0x4159265358979323, 0x4159265358979323}, + {0x8888888888888888, 0x4141414141414141, 0x9797979797979797, + 0x1616161616161616, 0x9393939393939393, 0x9999999999999999, + 0x3737373737373737, 0x5151515151515151, 0x0505050505050505}, + + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + + {0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D, + 0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D, + 0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D, 0x5D5D5D5D5D5D5D5D}, + {0x5757575757575757, 0x5757575757575757, 0x5757575757575757, + 0x5757575757575757, 0x5757575757575757, 0x5757575757575757, + 0x5757575757575757, 0x5757575757575757, 0x5757575757575757}, + {0x8080808080808080, 0x8080808080808080, 0x8080808080808080, + 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, + 0x8080808080808080, 0x8080808080808080, 0x8080808080808080}, + }; + + wuffs_vp8__decoder dec = {0}; + for (int mode = 0; mode < 13; mode++) { + uint64_t w0 = test_cases[mode][0]; + uint64_t w1 = test_cases[mode][1]; + uint64_t w2 = test_cases[mode][2]; + uint64_t w3 = test_cases[mode][3]; + uint64_t w4 = test_cases[mode][4]; + uint64_t w5 = test_cases[mode][5]; + uint64_t w6 = test_cases[mode][6]; + uint64_t w7 = test_cases[mode][7]; + uint64_t w8 = test_cases[mode][8]; + + if (w0 == 0) { + continue; + } + + initialize_decoder_test_state(&dec); + + wuffs_vp8__decoder__predict_y16(&dec, mode); + + uint64_t h0 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x01][8]); + uint64_t h1 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x02][8]); + uint64_t h2 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x03][8]); + uint64_t h3 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x04][8]); + uint64_t h4 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x05][8]); + uint64_t h5 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x06][8]); + uint64_t h6 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x07][8]); + uint64_t h7 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x08][8]); + uint64_t h8 = wuffs_base__peek_u64be__no_bounds_check( + &dec.private_impl.f_yuv_cache[0x09][8]); + + if ((h0 != w0) || (h1 != w1) || (h2 != w2) || (h3 != w3) || // + (h4 != w4) || (h5 != w5) || (h6 != w6) || (h7 != w7) || (h8 != w8)) { + RETURN_FAIL( + "mode=%d:" // + "\nhave %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64 // + "\nwant %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 " %016" PRIX64 // + " %016" PRIX64, // + mode, h0, h1, h2, h3, h4, h5, h6, h7, h8, // + w0, w1, w2, w3, w4, w5, w6, w7, w8); + } + } + + return NULL; +} + +const char* // +test_wuffs_vp8_decode_predict_y4() { + CHECK_FOCUS(__func__); + + const uint32_t test_cases[10][4] = { + {0x51515151, 0x51515151, 0x51515151, 0x51515151}, + {0x98B07DAA, 0x51693663, 0xA7BF8CB9, 0x263E0B38}, + {0x43463E49, 0x43463E49, 0x43463E49, 0x43463E49}, + {0x61616161, 0x68686868, 0x61616161, 0x36363636}, + {0x4B43463E, 0x614B4346, 0x68614B43, 0x6168614B}, + {0x394D403D, 0x4B43463E, 0x61394D40, 0x684B4346}, + {0x463E4967, 0x3E496786, 0x49678678, 0x6786783F}, + {0x4D403D56, 0x463E4967, 0x403D5686, 0x3E496778}, + {0x5D4B4346, 0x65615D4B, 0x6C686561, 0x57616C68}, + {0x65686C61, 0x6C615736, 0x57361616, 0x16161616}, + }; + + wuffs_vp8__decoder dec = {0}; + for (int mode = 0; mode < 10; mode++) { + uint32_t w0 = test_cases[mode][0]; + uint32_t w1 = test_cases[mode][1]; + uint32_t w2 = test_cases[mode][2]; + uint32_t w3 = test_cases[mode][3]; + + initialize_decoder_test_state(&dec); + + dec.private_impl.f_mb_subblock_modes[0] = mode; + wuffs_vp8__decoder__predict_y4(&dec, 0); + + uint32_t h0 = wuffs_base__peek_u32be__no_bounds_check( + &dec.private_impl.f_yuv_cache[1][8]); + uint32_t h1 = wuffs_base__peek_u32be__no_bounds_check( + &dec.private_impl.f_yuv_cache[2][8]); + uint32_t h2 = wuffs_base__peek_u32be__no_bounds_check( + &dec.private_impl.f_yuv_cache[3][8]); + uint32_t h3 = wuffs_base__peek_u32be__no_bounds_check( + &dec.private_impl.f_yuv_cache[4][8]); + + if ((h0 != w0) || (h1 != w1) || (h2 != w2) || (h3 != w3)) { + RETURN_FAIL( + "mode=%d:" // + "\nhave %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32 // + "\nwant %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32, // + mode, h0, h1, h2, h3, w0, w1, w2, w3); + } + } + return NULL; +} // ---------------- Mimic Tests @@ -91,7 +380,9 @@ proc g_tests[] = { -// No VP8 tests. + test_wuffs_vp8_decode_predict_uv8, + test_wuffs_vp8_decode_predict_y16, + test_wuffs_vp8_decode_predict_y4, #ifdef WUFFS_MIMIC