This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit dc52424419177fa2624a614d5edcfe69b53032d2 Author: Kacper Michajłow <[email protected]> AuthorDate: Thu Sep 10 04:32:34 2026 +0200 Commit: Kacper Michajłow <[email protected]> CommitDate: Wed Sep 23 13:46:13 2026 +0000 avcodec/mpegvideo_enc: point the input picture at the input pixels An input picture the encoder cannot take by reference is copied into a buffer that the reconstruction of the same picture later reuses from its start, so the copy sits INPLACE_OFFSET further in. The frame of such a picture kept pointing at the start of the buffer and every reader of the input had to know where the copy went. set_bframe_chain_length() did not, so get_intra_count() scored the padding margin of a copied picture rather than its pixels and picked the B frame chain length from the wrong data. The same encode came out different depending on whether the input buffer could be taken directly. The readers that did add the offset, the b_strategy 2 estimator, the frame skip check and the MPEG-4 B frame skip check, added it for every copied picture. With a VBV buffer a copied picture is stored without the offset, since it may have to be encoded again and the reconstruction gets a buffer of its own, so those three read 16 pixels to the right of the input in every VBV encode. Point the frame of a copied picture at the input when it is loaded and move it back to the start of the buffer once the picture is selected for encoding and the reconstruction takes the buffer over. The readers then find the input where the frame points, whichever way the picture was stored. Both mpeg4-adap tests were scored on the wrong pixels, hence their references change here. fate-vsynth1-mpeg4-layout-ref compares the layout reference with the adap one, so the encode of a picture taken by reference and of a copied one have to stay identical. Signed-off-by: Kacper Michajłow <[email protected]> --- libavcodec/mpeg4videoenc.c | 2 -- libavcodec/mpegvideo_enc.c | 33 ++++++++++++++------------------- tests/fate/vcodec.mak | 4 +++- tests/ref/vsynth/vsynth1-mpeg4-adap | 8 ++++---- tests/ref/vsynth/vsynth3-mpeg4-adap | 8 ++++---- 5 files changed, 25 insertions(+), 30 deletions(-) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index f7aa635d2e..a610c36856 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -624,8 +624,6 @@ static void mpeg4_encode_mb(MPVEncContext *const s, int16_t block[][64], break; b_pic = pic->f->data[0] + offset; - if (!pic->shared) - b_pic += INPLACE_OFFSET; if (x + 16 > s->c.width || y + 16 > s->c.height) { int x1, y1; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 6ce342dde8..2bbbe01b82 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1369,7 +1369,6 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg int w = AV_CEIL_RSHIFT(s->c.width , h_shift); int h = AV_CEIL_RSHIFT(s->c.height, v_shift); const uint8_t *src = pic_arg->data[i]; - uint8_t *dst = pic->f->data[i]; int vpad = 16; if ( s->c.codec_id == AV_CODEC_ID_MPEG2VIDEO @@ -1378,7 +1377,8 @@ static int load_input_picture(MPVMainEncContext *const m, const AVFrame *pic_arg vpad = 32; if (!s->c.avctx->rc_buffer_size) - dst += INPLACE_OFFSET; + pic->f->data[i] += INPLACE_OFFSET; + uint8_t *dst = pic->f->data[i]; if (src_stride == dst_stride) memcpy(dst, src, src_stride * h - src_stride + w); @@ -1442,8 +1442,7 @@ static int skip_check(MPVMainEncContext *const m, const int bw = plane ? 1 : 2; for (int y = 0; y < s->c.mb_height * bw; y++) { for (int x = 0; x < s->c.mb_width * bw; x++) { - int off = p->shared ? 0 : 16; - const uint8_t *dptr = p->f->data[plane] + 8 * (x + y * stride) + off; + const uint8_t *dptr = p->f->data[plane] + 8 * (x + y * stride); const uint8_t *rptr = ref->f->data[plane] + 8 * (x + y * stride); int v = m->frame_skip_cmp_fn(s, dptr, rptr, stride, 8); @@ -1524,29 +1523,22 @@ static int estimate_best_b_count(MPVMainEncContext *const m) s->c.next_pic.ptr; if (pre_input_ptr) { - const uint8_t *data[4]; - memcpy(data, pre_input_ptr->f->data, sizeof(data)); - - if (!pre_input_ptr->shared && i) { - data[0] += INPLACE_OFFSET; - data[1] += INPLACE_OFFSET; - data[2] += INPLACE_OFFSET; - } + const AVFrame *const pre_input = pre_input_ptr->f; s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[0], m->tmp_frames[i]->linesize[0], - data[0], - pre_input_ptr->f->linesize[0], + pre_input->data[0], + pre_input->linesize[0], width, height); s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[1], m->tmp_frames[i]->linesize[1], - data[1], - pre_input_ptr->f->linesize[1], + pre_input->data[1], + pre_input->linesize[1], width >> 1, height >> 1); s->mpvencdsp.shrink[scale](m->tmp_frames[i]->data[2], m->tmp_frames[i]->linesize[2], - data[2], - pre_input_ptr->f->linesize[2], + pre_input->data[2], + pre_input->linesize[2], width >> 1, height >> 1); } } @@ -1815,8 +1807,11 @@ static int select_input_picture(MPVMainEncContext *const m) ret = av_frame_ref(s->new_pic, m->reordered_input_picture[0]->f); if (ret < 0) goto fail; + // The input was stored INPLACE_OFFSET into the buffer, which + // new_pic now points at. Point the frame back at the start of + // the buffer for the reconstruction. for (int i = 0; i < MPV_MAX_PLANES; i++) - s->new_pic->data[i] += INPLACE_OFFSET; + m->reordered_input_picture[0]->f->data[i] -= INPLACE_OFFSET; } s->c.cur_pic.ptr = m->reordered_input_picture[0]; m->reordered_input_picture[0] = NULL; diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index eeaac71507..b24eebc61c 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -325,9 +325,11 @@ fate-vsynth%-mpeg4-adap: ENCOPTS = $(MPEG4_ADAP_OPTS) # This is the same test as fate-vsynth%-mpeg4-adap but with an input padded # so the encoder can use it without copy. FATE_VCODEC_LAYOUT-$(call ENCDEC, MPEG4, AVI, PAD_FILTER CROP_FILTER) += \ - fate-vsynth1-mpeg4-layout + fate-vsynth1-mpeg4-layout fate-vsynth1-mpeg4-layout-ref fate-vsynth%-mpeg4-layout: ENCOPTS = -vf pad=384:288:0:0,crop=352:288:0:0 \ $(MPEG4_ADAP_OPTS) +fate-vsynth%-mpeg4-layout-ref: CMD = sed s/mpeg4-layout/mpeg4-adap/g $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%-ref=%) +fate-vsynth%-mpeg4-layout-ref: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%-layout-ref=%)-adap fate-vsynth%-mpeg4-adv: ENCOPTS = -qscale 9 -flags +mv4+aic \ -data_partitioning 1 -trellis 1 \ diff --git a/tests/ref/vsynth/vsynth1-mpeg4-adap b/tests/ref/vsynth/vsynth1-mpeg4-adap index 8fd0384f31..8bde82345e 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4-adap +++ b/tests/ref/vsynth/vsynth1-mpeg4-adap @@ -1,4 +1,4 @@ -3a889f498a36c3bce59924887e73990f *tests/data/fate/vsynth1-mpeg4-adap.avi -264468 tests/data/fate/vsynth1-mpeg4-adap.avi -8333845e5dfdb913d08570b7edf8682f *tests/data/fate/vsynth1-mpeg4-adap.out.rawvideo -stddev: 13.94 PSNR: 25.24 MAXDIFF: 165 bytes: 7603200/ 7603200 +f268fdbe7f6810b87fd3f6069ef44a96 *tests/data/fate/vsynth1-mpeg4-adap.avi +260786 tests/data/fate/vsynth1-mpeg4-adap.avi +bab18a36ec88a100e6ba497bfc4928db *tests/data/fate/vsynth1-mpeg4-adap.out.rawvideo +stddev: 14.01 PSNR: 25.20 MAXDIFF: 164 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-mpeg4-adap b/tests/ref/vsynth/vsynth3-mpeg4-adap index d85d648729..f059c599ad 100644 --- a/tests/ref/vsynth/vsynth3-mpeg4-adap +++ b/tests/ref/vsynth/vsynth3-mpeg4-adap @@ -1,4 +1,4 @@ -974af2dfb1f81c8030d813617f989b9d *tests/data/fate/vsynth3-mpeg4-adap.avi -42096 tests/data/fate/vsynth3-mpeg4-adap.avi -96839ddca31edf7c9d392c358262a6d4 *tests/data/fate/vsynth3-mpeg4-adap.out.rawvideo -stddev: 4.94 PSNR: 34.25 MAXDIFF: 49 bytes: 86700/ 86700 +40b2c13177bb7fb95165ed5bc2d14a67 *tests/data/fate/vsynth3-mpeg4-adap.avi +41754 tests/data/fate/vsynth3-mpeg4-adap.avi +2df698f349ef31cb11b96c941a0dbd22 *tests/data/fate/vsynth3-mpeg4-adap.out.rawvideo +stddev: 5.05 PSNR: 34.06 MAXDIFF: 49 bytes: 86700/ 86700 -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
