Signed-off-by: Zhong Li <zhong...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".