std/vp8: simplify swizzle_one_row_of_macroblocks Prior to 381e186f "std/vp8: swizzle_ycck once, not once per MB row", we swizzled one row of macroblocks at a time. After 381e186f, we swizzled the whole image in one pass, but kept the option of, in the future, amending the swizzle_ycck implementation to allow ((y_min_incl > 0) and (ycc_upsampling == FANCY_ETC)) at the same time. However, 381e186f didn't show a performance loss so large that it seems worth complicating the swizzle_ycck implementation in that way. So we just drop, in this commit, the option of that amendment.
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c index c99c264..54e2655 100644 --- a/release/c/wuffs-unsupported-snapshot.c +++ b/release/c/wuffs-unsupported-snapshot.c
@@ -82114,11 +82114,10 @@ WUFFS_BASE__GENERATED_C_CODE static wuffs_base__status -wuffs_vp8__decoder__swizzle_one_row_of_macroblocks( +wuffs_vp8__decoder__swizzle( wuffs_vp8__decoder* self, wuffs_base__pixel_buffer* a_dst, - wuffs_base__slice_u8 a_workbuf, - uint32_t a_mby); + wuffs_base__slice_u8 a_workbuf); WUFFS_BASE__GENERATED_C_CODE static wuffs_base__empty_struct @@ -83995,14 +83994,13 @@ v_mby += 1u; } if (self->private_impl.f_mbh > 0u) { - v_mby = (self->private_impl.f_mbh - 1u); if (self->private_impl.f_filt_level <= 0u) { } else if (self->private_impl.f_filt_simple) { - wuffs_vp8__decoder__filter_simple(self, a_workbuf, v_mby); + wuffs_vp8__decoder__filter_simple(self, a_workbuf, (self->private_impl.f_mbh - 1u)); } else { - wuffs_vp8__decoder__filter_normal(self, a_workbuf, v_mby); + wuffs_vp8__decoder__filter_normal(self, a_workbuf, (self->private_impl.f_mbh - 1u)); } - v_status = wuffs_vp8__decoder__swizzle_one_row_of_macroblocks(self, a_dst, a_workbuf, v_mby); + v_status = wuffs_vp8__decoder__swizzle(self, a_dst, a_workbuf); if ( ! wuffs_base__status__is_ok(&v_status)) { return wuffs_private_impl__status__ensure_not_a_suspension(v_status); } @@ -84263,62 +84261,41 @@ return wuffs_base__make_empty_struct(); } -// -------- func vp8.decoder.swizzle_one_row_of_macroblocks +// -------- func vp8.decoder.swizzle WUFFS_BASE__GENERATED_C_CODE static wuffs_base__status -wuffs_vp8__decoder__swizzle_one_row_of_macroblocks( +wuffs_vp8__decoder__swizzle( wuffs_vp8__decoder* self, wuffs_base__pixel_buffer* a_dst, - wuffs_base__slice_u8 a_workbuf, - uint32_t a_mby) { - uint32_t v_y_min_incl = 0; - uint32_t v_y_max_excl = 0; - uint64_t v_o = 0; - wuffs_base__slice_u8 v_src0 = {0}; - wuffs_base__slice_u8 v_src1 = {0}; - wuffs_base__slice_u8 v_src2 = {0}; + wuffs_base__slice_u8 a_workbuf) { wuffs_base__status v_status = wuffs_base__make_status(NULL); if ((self->private_impl.f_workbuf_yuv_y_end > self->private_impl.f_workbuf_yuv_u_end) || (self->private_impl.f_workbuf_yuv_u_end > self->private_impl.f_workbuf_yuv_v_end) || (self->private_impl.f_workbuf_yuv_v_end > ((uint64_t)(a_workbuf.len)))) { return wuffs_base__make_status(wuffs_base__error__bad_workbuf_length); } - v_y_min_incl = wuffs_base__u32__sat_sub((a_mby * 16u), 6u); - v_y_min_incl = 0u; - v_y_max_excl = ((a_mby * 16u) + 10u); - if ((a_mby + 1u) >= self->private_impl.f_mbh) { - v_y_max_excl = self->private_impl.f_height; - } - v_o = ((uint64_t)((v_y_min_incl * self->private_impl.f_workbuf_yuv_y_stride))); - if (v_o < self->private_impl.f_workbuf_yuv_y_end) { - v_src0 = wuffs_base__slice_u8__subslice_ij(a_workbuf, v_o, self->private_impl.f_workbuf_yuv_y_end); - } - v_o = (((uint64_t)(((v_y_min_incl / 2u) * self->private_impl.f_workbuf_yuv_uv_stride))) + self->private_impl.f_workbuf_yuv_y_end); - if (v_o < self->private_impl.f_workbuf_yuv_u_end) { - v_src1 = wuffs_base__slice_u8__subslice_ij(a_workbuf, v_o, self->private_impl.f_workbuf_yuv_u_end); - } - v_o = (((uint64_t)(((v_y_min_incl / 2u) * self->private_impl.f_workbuf_yuv_uv_stride))) + self->private_impl.f_workbuf_yuv_u_end); - if (v_o < self->private_impl.f_workbuf_yuv_v_end) { - v_src2 = wuffs_base__slice_u8__subslice_ij(a_workbuf, v_o, self->private_impl.f_workbuf_yuv_v_end); - } v_status = wuffs_base__pixel_swizzler__swizzle_ycck(&self->private_impl.f_swizzler, a_dst, wuffs_base__pixel_buffer__palette(a_dst), 0u, self->private_impl.f_width, - v_y_min_incl, - v_y_max_excl, - v_src0, - v_src1, - v_src2, + 0u, + self->private_impl.f_height, + wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_workbuf_yuv_y_end), + wuffs_base__slice_u8__subslice_ij(a_workbuf, + self->private_impl.f_workbuf_yuv_y_end, + self->private_impl.f_workbuf_yuv_u_end), + wuffs_base__slice_u8__subslice_ij(a_workbuf, + self->private_impl.f_workbuf_yuv_u_end, + self->private_impl.f_workbuf_yuv_v_end), wuffs_base__utility__empty_slice_u8(), (self->private_impl.f_mbw * 16u), (self->private_impl.f_mbw * 8u), (self->private_impl.f_mbw * 8u), 0u, - wuffs_base__u32__sat_sub((self->private_impl.f_mbh * 16u), v_y_min_incl), - wuffs_base__u32__sat_sub((self->private_impl.f_mbh * 8u), (v_y_min_incl / 2u)), - wuffs_base__u32__sat_sub((self->private_impl.f_mbh * 8u), (v_y_min_incl / 2u)), + (self->private_impl.f_mbh * 16u), + (self->private_impl.f_mbh * 8u), + (self->private_impl.f_mbh * 8u), 0u, (self->private_impl.f_mbw * 16u), (self->private_impl.f_mbw * 8u),
diff --git a/std/vp8/decode_macroblocks.wuffs b/std/vp8/decode_macroblocks.wuffs index 5c608fd..8bf1460 100644 --- a/std/vp8/decode_macroblocks.wuffs +++ b/std/vp8/decode_macroblocks.wuffs
@@ -47,29 +47,21 @@ } else { this.filter_normal!(workbuf: args.workbuf, mby: mby - 1) } - - // TODO(§): re-enable this when swizzle_ycck can take y_min_incl > 0. - // - // status = this.swizzle_one_row_of_macroblocks!(dst: args.dst, workbuf: args.workbuf, mby: mby - 1) - // if not status.is_ok() { - // return status - // } } mby += 1 } if this.mbh > 0 { - mby = this.mbh - 1 if this.filt_level <= 0 { // No-op. } else if this.filt_simple { - this.filter_simple!(workbuf: args.workbuf, mby: mby) + this.filter_simple!(workbuf: args.workbuf, mby: this.mbh - 1) } else { - this.filter_normal!(workbuf: args.workbuf, mby: mby) + this.filter_normal!(workbuf: args.workbuf, mby: this.mbh - 1) } - status = this.swizzle_one_row_of_macroblocks!(dst: args.dst, workbuf: args.workbuf, mby: mby) + status = this.swizzle!(dst: args.dst, workbuf: args.workbuf) if not status.is_ok() { return status } @@ -349,18 +341,9 @@ } } -pri func decoder.swizzle_one_row_of_macroblocks!( +pri func decoder.swizzle!( dst: ptr base.pixel_buffer, - workbuf: slice base.u8, - mby: base.u32[..= 0x3FF]) base.status { - var y_min_incl : base.u32[..= 0x3FFF] - var y_max_excl : base.u32[..= 0x3FFF] - - var o : base.u64 - var src0 : slice base.u8 - var src1 : slice base.u8 - var src2 : slice base.u8 - + workbuf: slice base.u8) base.status { var status : base.status if (this.workbuf_yuv_y_end > this.workbuf_yuv_u_end) or @@ -371,49 +354,24 @@ assert this.workbuf_yuv_u_end <= args.workbuf.length() via "a <= b: a <= c; c <= b"(c: this.workbuf_yuv_v_end) assert this.workbuf_yuv_y_end <= args.workbuf.length() via "a <= b: a <= c; c <= b"(c: this.workbuf_yuv_u_end) - // There are 16 rows of pixels per macroblock. However, the bottom 6 rows - // of pixels (the bottom 3 rows of samples, at 4:2:0 chroma subsampling) - // can be modified by the the macroblock below's loop filtering (which - // happens after decoder.swizzle_one_row_of_macroblocks returns), unless - // we're swizzling the bottom-most row of macroblocks. - y_min_incl = (args.mby * 16) ~sat- 6 - y_min_incl = 0 // TODO(§): delete this. - y_max_excl = (args.mby * 16) + 10 - if (args.mby + 1) >= this.mbh { - y_max_excl = this.height - } - - o = (y_min_incl * this.workbuf_yuv_y_stride) as base.u64 - if o < this.workbuf_yuv_y_end { - src0 = args.workbuf[o .. this.workbuf_yuv_y_end] - } - o = (((y_min_incl / 2) * this.workbuf_yuv_uv_stride) as base.u64) + this.workbuf_yuv_y_end - if o < this.workbuf_yuv_u_end { - src1 = args.workbuf[o .. this.workbuf_yuv_u_end] - } - o = (((y_min_incl / 2) * this.workbuf_yuv_uv_stride) as base.u64) + this.workbuf_yuv_u_end - if o < this.workbuf_yuv_v_end { - src2 = args.workbuf[o .. this.workbuf_yuv_v_end] - } - status = this.swizzler.swizzle_ycck!( dst: args.dst, dst_palette: args.dst.palette(), x_min_incl: 0, x_max_excl: this.width, - y_min_incl: y_min_incl, - y_max_excl: y_max_excl, - src0: src0, - src1: src1, - src2: src2, + y_min_incl: 0, + y_max_excl: this.height, + src0: args.workbuf[.. this.workbuf_yuv_y_end], + src1: args.workbuf[this.workbuf_yuv_y_end .. this.workbuf_yuv_u_end], + src2: args.workbuf[this.workbuf_yuv_u_end .. this.workbuf_yuv_v_end], src3: this.util.empty_slice_u8(), width0: this.mbw * 16, width1: this.mbw * 8, width2: this.mbw * 8, width3: 0, - height0: (this.mbh * 16) ~sat- y_min_incl, - height1: (this.mbh * 8) ~sat- (y_min_incl / 2), - height2: (this.mbh * 8) ~sat- (y_min_incl / 2), + height0: this.mbh * 16, + height1: this.mbh * 8, + height2: this.mbh * 8, height3: 0, stride0: this.mbw * 16, stride1: this.mbw * 8, @@ -428,7 +386,6 @@ v2: 1, v3: 0, ycc_model: base.YCC_MODEL__BT_601_STUDIO_RANGE as base.u8, - // TODO(§): let fancy upsampling work with y_min_incl > 0. ycc_upsampling: base.YCC_UPSAMPLING__FANCY_LIKE_LIBWEBP as base.u8, scratch_buffer_2k: this.swizzle_ycck_scratch_buffer_2k[..]) return status