Commit 79d8801e8e for ffmpeg

commit 79d8801e8e14fedd7153be6f775a671175263c9c
Author: Baptiste Coudurier <baptiste.coudurier@gmail.com>
Date:   Sat Oct 17 11:17:16 2026 -0700

    avcodec/mjpegenc: fix restart markers for pictures one macroblock wide

    The row of the restart marker was derived from the macroblock position,
    as the previous row when called at the start of a new row (mb_x == 0)
    and the current row at the end of a slice (mb_x == mb_width - 1).

    With a single macroblock column both cases have mb_x == 0, so the end of
    a slice wrote the marker of the previous row, and a marker after the
    last row. Pass the row of the last coded macroblock explicitly.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index 4305f11774..4bdeef8b66 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -233,13 +233,13 @@ static void mjpeg_build_optimal_huffman(MJpegContext *m)
  * Header + values + stuffing.
  *
  * @param s The MPVEncContext.
+ * @param last_mb_y Row of the last coded macroblock.
  * @return int Error code, 0 if successful.
  */
-int ff_mjpeg_encode_stuffing(MPVEncContext *const s)
+int ff_mjpeg_encode_stuffing(MPVEncContext *const s, int last_mb_y)
 {
     MJpegContext *const m = s->mjpeg_ctx;
     PutBitContext *pbc = &s->pb;
-    int mb_y = s->c.mb_y - !s->c.mb_x;
     int ret;

 #if CONFIG_MJPEG_ENCODER
@@ -273,8 +273,8 @@ int ff_mjpeg_encode_stuffing(MPVEncContext *const s)

     ff_mjpeg_escape_FF(pbc, s->esc_pos);

-    if (s->c.slice_context_count > 1 && mb_y < s->c.mb_height - 1)
-        put_marker(pbc, RST0 + (mb_y&7));
+    if (s->c.slice_context_count > 1 && last_mb_y < s->c.mb_height - 1)
+        put_marker(pbc, RST0 + (last_mb_y & 7));
     s->esc_pos = put_bytes_count(pbc, 0);

 fail:
diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h
index 865f13f50e..0db364e648 100644
--- a/libavcodec/mjpegenc.h
+++ b/libavcodec/mjpegenc.h
@@ -97,6 +97,6 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code)

 typedef struct MPVEncContext MPVEncContext;

-int ff_mjpeg_encode_stuffing(MPVEncContext *s);
+int ff_mjpeg_encode_stuffing(MPVEncContext *s, int last_mb_y);

 #endif /* AVCODEC_MJPEGENC_H */
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 8180436ed1..b160626610 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -2864,7 +2864,10 @@ static int mb_var_thread(AVCodecContext *c, void *arg){
     return 0;
 }

-static void write_slice_end(MPVEncContext *const s)
+/**
+ * @param last_mb_y row of the last coded macroblock
+ */
+static void write_slice_end(MPVEncContext *const s, int last_mb_y)
 {
     if (CONFIG_MPEG4_ENCODER && s->c.codec_id == AV_CODEC_ID_MPEG4) {
         if (s->partitioned_frame)
@@ -2873,7 +2876,7 @@ static void write_slice_end(MPVEncContext *const s)
         ff_mpeg4_stuffing(&s->pb);
     } else if ((CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER) &&
                s->c.out_format == FMT_MJPEG) {
-        ff_mjpeg_encode_stuffing(s);
+        ff_mjpeg_encode_stuffing(s, last_mb_y);
     } else if (CONFIG_SPEEDHQ_ENCODER && s->c.out_format == FMT_SPEEDHQ) {
         ff_speedhq_end_slice(s);
     }
@@ -3082,7 +3085,7 @@ static int encode_thread(AVCodecContext *c, void *arg){

                 if(is_gob_start){
                     if (s->c.start_mb_y != mb_y || mb_x != 0) {
-                        write_slice_end(s);
+                        write_slice_end(s, mb_y - !mb_x);

                         if (CONFIG_MPEG4_ENCODER && s->c.codec_id == AV_CODEC_ID_MPEG4 && s->partitioned_frame)
                             ff_mpeg4_init_partitions(s);
@@ -3586,7 +3589,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
         ff_msmpeg4_encode_ext_header(s);
 #endif

-    write_slice_end(s);
+    write_slice_end(s, s->c.mb_y);

     return 0;
 }