[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