[FFmpeg-cvslog] avcodec/mjpegenc: Bypass the 2 pass encoding when optimal tables are not requested

Michael Niedermayer git at videolan.org
Fri Feb 10 01:14:30 EET 2017


ffmpeg | branch: master | Michael Niedermayer <michael at niedermayer.cc> | Thu Feb  9 23:24:15 2017 +0100| [3e1507a9547ac09b6ff4372123cde09f19218f3d] | committer: Michael Niedermayer

avcodec/mjpegenc: Bypass the 2 pass encoding when optimal tables are not requested

This limits the bugs, speedloss and extra memory allocation to the case when
optimal tables are needed.
Fixes regressions with slice multi-threading

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3e1507a9547ac09b6ff4372123cde09f19218f3d
---

 libavcodec/mjpegenc.c        | 144 +++++++++++++++++++++++++++++++++++--------
 libavcodec/mjpegenc_common.c |  11 ++--
 libavcodec/mpegvideo_enc.c   |   5 +-
 3 files changed, 128 insertions(+), 32 deletions(-)

diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index 550338f..cc917ed 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -79,7 +79,7 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
         return AVERROR(EINVAL);
     }
 
-    m = av_malloc(sizeof(MJpegContext));
+    m = av_mallocz(sizeof(MJpegContext));
     if (!m)
         return AVERROR(ENOMEM);
 
@@ -117,7 +117,10 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
     m->huff_ncode = 0;
     s->mjpeg_ctx = m;
 
-    return alloc_huffman(s);
+    if(s->huffman == HUFFMAN_TABLE_OPTIMAL)
+        return alloc_huffman(s);
+
+    return 0;
 }
 
 av_cold void ff_mjpeg_encode_close(MpegEncContext *s)
@@ -224,7 +227,7 @@ static void ff_mjpeg_encode_coef(MJpegContext *s, uint8_t table_id, int val, int
  * @param block The block.
  * @param n The block's index or number.
  */
-static void encode_block(MpegEncContext *s, int16_t *block, int n)
+static void record_block(MpegEncContext *s, int16_t *block, int n)
 {
     int i, j, table_id;
     int component, dc, last_index, val, run;
@@ -267,36 +270,127 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n)
         ff_mjpeg_encode_code(m, table_id, 0);
 }
 
+static void encode_block(MpegEncContext *s, int16_t *block, int n)
+{
+    int mant, nbits, code, i, j;
+    int component, dc, run, last_index, val;
+    MJpegContext *m = s->mjpeg_ctx;
+    uint8_t *huff_size_ac;
+    uint16_t *huff_code_ac;
+
+    /* DC coef */
+    component = (n <= 3 ? 0 : (n&1) + 1);
+    dc = block[0]; /* overflow is impossible */
+    val = dc - s->last_dc[component];
+    if (n < 4) {
+        ff_mjpeg_encode_dc(&s->pb, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance);
+        huff_size_ac = m->huff_size_ac_luminance;
+        huff_code_ac = m->huff_code_ac_luminance;
+    } else {
+        ff_mjpeg_encode_dc(&s->pb, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance);
+        huff_size_ac = m->huff_size_ac_chrominance;
+        huff_code_ac = m->huff_code_ac_chrominance;
+    }
+    s->last_dc[component] = dc;
+
+    /* AC coefs */
+
+    run = 0;
+    last_index = s->block_last_index[n];
+    for(i=1;i<=last_index;i++) {
+        j = s->intra_scantable.permutated[i];
+        val = block[j];
+        if (val == 0) {
+            run++;
+        } else {
+            while (run >= 16) {
+                put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]);
+                run -= 16;
+            }
+            mant = val;
+            if (val < 0) {
+                val = -val;
+                mant--;
+            }
+
+            nbits= av_log2_16bit(val) + 1;
+            code = (run << 4) | nbits;
+
+            put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]);
+
+            put_sbits(&s->pb, nbits, mant);
+            run = 0;
+        }
+    }
+
+    /* output EOB only if not already 64 values */
+    if (last_index < 63 || run != 0)
+        put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]);
+}
+
 void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64])
 {
     int i;
-    if (s->chroma_format == CHROMA_444) {
-        encode_block(s, block[0], 0);
-        encode_block(s, block[2], 2);
-        encode_block(s, block[4], 4);
-        encode_block(s, block[8], 8);
-        encode_block(s, block[5], 5);
-        encode_block(s, block[9], 9);
-
-        if (16*s->mb_x+8 < s->width) {
-            encode_block(s, block[1], 1);
-            encode_block(s, block[3], 3);
-            encode_block(s, block[6], 6);
-            encode_block(s, block[10], 10);
-            encode_block(s, block[7], 7);
-            encode_block(s, block[11], 11);
+    if (s->huffman == HUFFMAN_TABLE_OPTIMAL) {
+        if (s->chroma_format == CHROMA_444) {
+            record_block(s, block[0], 0);
+            record_block(s, block[2], 2);
+            record_block(s, block[4], 4);
+            record_block(s, block[8], 8);
+            record_block(s, block[5], 5);
+            record_block(s, block[9], 9);
+
+            if (16*s->mb_x+8 < s->width) {
+                record_block(s, block[1], 1);
+                record_block(s, block[3], 3);
+                record_block(s, block[6], 6);
+                record_block(s, block[10], 10);
+                record_block(s, block[7], 7);
+                record_block(s, block[11], 11);
+            }
+        } else {
+            for(i=0;i<5;i++) {
+                record_block(s, block[i], i);
+            }
+            if (s->chroma_format == CHROMA_420) {
+                record_block(s, block[5], 5);
+            } else {
+                record_block(s, block[6], 6);
+                record_block(s, block[5], 5);
+                record_block(s, block[7], 7);
+            }
         }
     } else {
-        for(i=0;i<5;i++) {
-            encode_block(s, block[i], i);
-        }
-        if (s->chroma_format == CHROMA_420) {
+        if (s->chroma_format == CHROMA_444) {
+            encode_block(s, block[0], 0);
+            encode_block(s, block[2], 2);
+            encode_block(s, block[4], 4);
+            encode_block(s, block[8], 8);
             encode_block(s, block[5], 5);
+            encode_block(s, block[9], 9);
+
+            if (16*s->mb_x+8 < s->width) {
+                encode_block(s, block[1], 1);
+                encode_block(s, block[3], 3);
+                encode_block(s, block[6], 6);
+                encode_block(s, block[10], 10);
+                encode_block(s, block[7], 7);
+                encode_block(s, block[11], 11);
+            }
         } else {
-            encode_block(s, block[6], 6);
-            encode_block(s, block[5], 5);
-            encode_block(s, block[7], 7);
+            for(i=0;i<5;i++) {
+                encode_block(s, block[i], i);
+            }
+            if (s->chroma_format == CHROMA_420) {
+                encode_block(s, block[5], 5);
+            } else {
+                encode_block(s, block[6], 6);
+                encode_block(s, block[5], 5);
+                encode_block(s, block[7], 7);
+            }
         }
+
+        s->i_tex_bits += get_bits_diff(s);
     }
 }
 
diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c
index e53a45c..722ad5e 100644
--- a/libavcodec/mjpegenc_common.c
+++ b/libavcodec/mjpegenc_common.c
@@ -480,7 +480,8 @@ static void ff_mjpeg_build_optimal_huffman(MJpegContext *m)
 }
 
 /**
- * Writes the complete JPEG frame.
+ * Writes the complete JPEG frame when optimal huffman tables are enabled,
+ * otherwise writes the stuffing.
  *
  * Header + values + stuffing.
  *
@@ -508,11 +509,11 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s)
         s->intra_ac_vlc_last_length = m->uni_ac_vlc_len;
         s->intra_chroma_ac_vlc_length      =
         s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len;
-    }
 
-    ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
-                                   s->pred, s->intra_matrix, s->chroma_intra_matrix);
-    ff_mjpeg_encode_picture_frame(s);
+        ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
+                                       s->pred, s->intra_matrix, s->chroma_intra_matrix);
+        ff_mjpeg_encode_picture_frame(s);
+    }
 
     ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100,
                                             put_bits_count(&s->pb) / 4 + 1000);
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index b1d8dae..0e4cbe8 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -3942,8 +3942,9 @@ static int encode_picture(MpegEncContext *s, int picture_number)
     s->last_bits= put_bits_count(&s->pb);
     switch(s->out_format) {
     case FMT_MJPEG:
-        /* The MJPEG headers are printed after the initial encoding so that the
-         * optimal huffman encoding can be found. */
+        if (CONFIG_MJPEG_ENCODER && s->huffman != HUFFMAN_TABLE_OPTIMAL)
+            ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable,
+                                           s->pred, s->intra_matrix, s->chroma_intra_matrix);
         break;
     case FMT_H261:
         if (CONFIG_H261_ENCODER)



More information about the ffmpeg-cvslog mailing list