[FFmpeg-devel] [PATCH 2/3] lavc/mjpeg_parser: use ff_mjpeg_decode_header to parse frame info

Zhong Li zhong.li at intel.com
Thu Jun 27 15:59:13 EEST 2019


Signed-off-by: Zhong Li <zhong.li at intel.com>
---
 libavcodec/mjpeg_parser.c | 158 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 157 insertions(+), 1 deletion(-)

diff --git a/libavcodec/mjpeg_parser.c b/libavcodec/mjpeg_parser.c
index 07a6b2b..f59aa3e 100644
--- a/libavcodec/mjpeg_parser.c
+++ b/libavcodec/mjpeg_parser.c
@@ -27,12 +27,131 @@
  */
 
 #include "parser.h"
+#include "mjpeg.h"
+#include "mjpegdec.h"
+#include "get_bits.h"
 
 typedef struct MJPEGParserContext{
     ParseContext pc;
+    MJpegDecodeContext dec_ctx;
     int size;
 }MJPEGParserContext;
 
+/* return the 8 bit start code value and update the search
+   state. Return -1 if no start code found */
+static int find_frame_header_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
+{
+    const uint8_t *buf_ptr;
+    unsigned int v, v2;
+    int val;
+    int skipped = 0;
+
+    buf_ptr = *pbuf_ptr;
+    while (buf_end - buf_ptr > 1) {
+        v  = *buf_ptr++;
+        v2 = *buf_ptr;
+        if ((v == 0xff) && buf_ptr < buf_end &&
+            ((v2 >= SOF0) && (v2 <= SOF3)) ) {
+            val = *buf_ptr++;
+            goto found;
+        }
+        skipped++;
+    }
+    buf_ptr = buf_end;
+    val = -1;
+found:
+    ff_dlog(NULL, "find_marker skipped %d bytes\n", skipped);
+    *pbuf_ptr = buf_ptr;
+    return val;
+}
+
+static void jpeg_set_interlace_polarity(AVCodecContext *avctx, MJpegDecodeContext *dec_ctx)
+{
+    if (avctx->extradata_size > 14
+        && AV_RL32(avctx->extradata) == 0x2C
+        && AV_RL32(avctx->extradata+4) == 0x18) {
+        if (avctx->extradata[12] == 1) /* NTSC */
+            dec_ctx->interlace_polarity = 1;
+        if (avctx->extradata[12] == 2) /* PAL */
+            dec_ctx->interlace_polarity = 0;
+    }
+}
+
+static int jpeg_parse_header(AVCodecParserContext *s, AVCodecContext *avctx,
+                               const uint8_t *buf, int buf_size)
+{
+    MJPEGParserContext *m = s->priv_data;
+    MJpegDecodeContext *dec_ctx = &m->dec_ctx;
+    int start_code;
+    const uint8_t *start, *end;
+    int ret=0;
+
+    start = buf;
+    end = buf + buf_size;
+    start_code = find_frame_header_marker(&start, end);
+    if (start_code < 0) {
+        av_log(avctx, AV_LOG_ERROR, "parse header failure:"
+            "can't find supported marker type (%x)\n", start_code);
+
+        return -1;
+    } else
+        av_log(avctx, AV_LOG_DEBUG, "marker=%x\n", start_code);
+
+    jpeg_set_interlace_polarity(avctx, dec_ctx);
+    init_get_bits8(&dec_ctx->gb, start, end - start);
+    dec_ctx->avctx = avctx;
+
+    switch(start_code) {
+    case SOF0:
+        avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT;
+        dec_ctx->lossless        = 0;
+        dec_ctx->progressive     = 0;
+        break;
+    case SOF1:
+        avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT;
+        dec_ctx->lossless        = 0;
+        dec_ctx->progressive     = 0;
+        break;
+    case SOF2:
+        avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT;
+        dec_ctx->lossless        = 0;
+        dec_ctx->progressive     = 1;
+        break;
+    case SOF3:
+        avctx->profile = FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS;
+        dec_ctx->lossless        = 1;
+        dec_ctx->progressive     = 0;
+        break;
+    default:
+       assert(0);
+    }
+
+    ret = ff_mjpeg_decode_header(dec_ctx);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_WARNING, "Failed to parse header\n");
+        return ret;
+    }
+
+    s->height = dec_ctx->height;
+    s->width  = dec_ctx->width;
+    s->coded_height = s->height;
+    s->coded_width  = s->width;
+    s->format       = avctx->pix_fmt;
+    s->pict_type    = AV_PICTURE_TYPE_I;
+    s->key_frame    = 1;
+
+    if (dec_ctx->interlaced) {
+        if (dec_ctx->bottom_field)
+            s->field_order = AV_FIELD_BB;
+        else
+            s->field_order = AV_FIELD_TT;
+    } else
+        s->field_order = AV_FIELD_PROGRESSIVE;
+
+    return 0;
+}
+
+
 /**
  * Find the end of the current frame in the bitstream.
  * @return the position of the first byte of the next frame, or -1
@@ -99,6 +218,40 @@ static int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_siz
     return END_NOT_FOUND;
 }
 
+static av_cold int jpeg_parse_init(AVCodecParserContext *s)
+{
+    MJPEGParserContext *m = s->priv_data;
+    MJpegDecodeContext *dec_ctx = &m->dec_ctx;
+
+    if (!dec_ctx->picture_ptr) {
+        dec_ctx->picture = av_frame_alloc();
+        if (!dec_ctx->picture)
+            return AVERROR(ENOMEM);
+        dec_ctx->picture_ptr = dec_ctx->picture;
+    }
+
+    dec_ctx->first_picture = 1;
+    dec_ctx->got_picture   = 0;
+    dec_ctx->org_height    = 0;
+    dec_ctx->ls            = 0;
+    return 0;
+}
+
+static av_cold void jpeg_parse_close(AVCodecParserContext *s)
+{
+    MJPEGParserContext *m = s->priv_data;
+    ParseContext *pc = &m->pc;
+    MJpegDecodeContext *dec_ctx = &m->dec_ctx;
+
+    av_freep(&pc->buffer);
+
+    if (dec_ctx->picture) {
+        av_frame_free(&dec_ctx->picture);
+        dec_ctx->picture_ptr = NULL;
+    } else if (dec_ctx->picture_ptr)
+        av_frame_unref(dec_ctx->picture_ptr);
+}
+
 static int jpeg_parse(AVCodecParserContext *s,
                       AVCodecContext *avctx,
                       const uint8_t **poutbuf, int *poutbuf_size,
@@ -120,6 +273,8 @@ static int jpeg_parse(AVCodecParserContext *s,
         }
     }
 
+    jpeg_parse_header(s, avctx, buf, buf_size);
+
     *poutbuf = buf;
     *poutbuf_size = buf_size;
     return next;
@@ -129,6 +284,7 @@ static int jpeg_parse(AVCodecParserContext *s,
 AVCodecParser ff_mjpeg_parser = {
     .codec_ids      = { AV_CODEC_ID_MJPEG, AV_CODEC_ID_JPEGLS },
     .priv_data_size = sizeof(MJPEGParserContext),
+    .parser_init      = jpeg_parse_init,
     .parser_parse   = jpeg_parse,
-    .parser_close   = ff_parse_close,
+    .parser_close   = jpeg_parse_close,
 };
-- 
2.7.4



More information about the ffmpeg-devel mailing list