[FFmpeg-devel] [PATCH] lavc/mjpegdec: hint next marker position in ff_mjpeg_find_marker

Matthieu Bouron matthieu.bouron at gmail.com
Thu Jan 26 18:47:51 EET 2017


Speeds up next marker search when a SOS marker is found.

ff_mjpeg_find_marker goes from 54% to 30% under perf record ffmpeg -i
sample_2992x4000.jpg
---
 libavcodec/mjpegdec.c | 31 +++++++++++++++++++++++++------
 libavcodec/mjpegdec.h |  2 +-
 libavcodec/mxpegdec.c |  5 +++--
 3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 7d17e3dfcb..29f40cb4e6 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -1921,13 +1921,23 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
 
 /* return the 8 bit start code value and update the search
    state. Return -1 if no start code found */
-static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
+static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_hint, const uint8_t *buf_end)
 {
     const uint8_t *buf_ptr;
     unsigned int v, v2;
     int val;
     int skipped = 0;
 
+    if (buf_hint && (buf_end - buf_hint > 1)) {
+        v = *buf_hint++;
+        v2 = *buf_hint;
+        if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_hint < buf_end) {
+            buf_ptr = buf_hint++;
+            val = v2;
+            goto found;
+        }
+    }
+
     buf_ptr = *pbuf_ptr;
     while (buf_end - buf_ptr > 1) {
         v  = *buf_ptr++;
@@ -1947,12 +1957,15 @@ found:
 }
 
 int ff_mjpeg_find_marker(MJpegDecodeContext *s,
-                         const uint8_t **buf_ptr, const uint8_t *buf_end,
+                         const uint8_t **buf_ptr,
+                         const uint8_t **buf_hint,
+                         const uint8_t *buf_end,
                          const uint8_t **unescaped_buf_ptr,
                          int *unescaped_buf_size)
 {
     int start_code;
-    start_code = find_marker(buf_ptr, buf_end);
+    start_code = find_marker(buf_ptr, *buf_hint, buf_end);
+    *buf_hint = NULL;
 
     av_fast_padded_malloc(&s->buffer, &s->buffer_size, buf_end - *buf_ptr);
     if (!s->buffer)
@@ -1963,6 +1976,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
         const uint8_t *src = *buf_ptr;
         const uint8_t *ptr = src;
         uint8_t *dst = s->buffer;
+        const uint8_t *next_marker = NULL;
 
         #define copy_data_segment(skip) do {       \
             ptrdiff_t length = (ptr - src) - (skip);  \
@@ -1999,8 +2013,10 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
 
                     if (x < 0xd0 || x > 0xd7) {
                         copy_data_segment(1);
-                        if (x)
+                        if (x) {
+                            next_marker = ptr - 2;
                             break;
+                        }
                     }
                 }
             }
@@ -2009,6 +2025,8 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
         }
         #undef copy_data_segment
 
+        if (next_marker)
+            *buf_hint = next_marker;
         *unescaped_buf_ptr  = s->buffer;
         *unescaped_buf_size = dst - s->buffer;
         memset(s->buffer + *unescaped_buf_size, 0,
@@ -2073,7 +2091,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     const uint8_t *buf = avpkt->data;
     int buf_size       = avpkt->size;
     MJpegDecodeContext *s = avctx->priv_data;
-    const uint8_t *buf_end, *buf_ptr;
+    const uint8_t *buf_end, *buf_hint, *buf_ptr;
     const uint8_t *unescaped_buf_ptr;
     int hshift, vshift;
     int unescaped_buf_size;
@@ -2087,10 +2105,11 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     s->adobe_transform = -1;
 
     buf_ptr = buf;
+    buf_hint = NULL;
     buf_end = buf + buf_size;
     while (buf_ptr < buf_end) {
         /* find start next marker */
-        start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end,
+        start_code = ff_mjpeg_find_marker(s, &buf_ptr, &buf_hint, buf_end,
                                           &unescaped_buf_ptr,
                                           &unescaped_buf_size);
         /* EOF */
diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h
index fb811294a1..c9d289187b 100644
--- a/libavcodec/mjpegdec.h
+++ b/libavcodec/mjpegdec.h
@@ -144,7 +144,7 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s,
                         const uint8_t *mb_bitmask,int mb_bitmask_size,
                         const AVFrame *reference);
 int ff_mjpeg_find_marker(MJpegDecodeContext *s,
-                         const uint8_t **buf_ptr, const uint8_t *buf_end,
+                         const uint8_t **buf_ptr, const uint8_t **buf_hint, const uint8_t *buf_end,
                          const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size);
 
 #endif /* AVCODEC_MJPEGDEC_H */
diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c
index 2e3ebe6e70..28a479a3b5 100644
--- a/libavcodec/mxpegdec.c
+++ b/libavcodec/mxpegdec.c
@@ -189,18 +189,19 @@ static int mxpeg_decode_frame(AVCodecContext *avctx,
     int buf_size = avpkt->size;
     MXpegDecodeContext *s = avctx->priv_data;
     MJpegDecodeContext *jpg = &s->jpg;
-    const uint8_t *buf_end, *buf_ptr;
+    const uint8_t *buf_end, *buf_hint, *buf_ptr;
     const uint8_t *unescaped_buf_ptr;
     int unescaped_buf_size;
     int start_code;
     int ret;
 
     buf_ptr = buf;
+    buf_hint = NULL;
     buf_end = buf + buf_size;
     jpg->got_picture = 0;
     s->got_mxm_bitmask = 0;
     while (buf_ptr < buf_end) {
-        start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end,
+        start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, &buf_hint, buf_end,
                                           &unescaped_buf_ptr, &unescaped_buf_size);
         if (start_code < 0)
             goto the_end;
-- 
2.11.0



More information about the ffmpeg-devel mailing list