From patchwork Thu Jun 27 12:59:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhong Li X-Patchwork-Id: 13725 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6EA4D44822E for ; Thu, 27 Jun 2019 15:59:21 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4E56A68AAA7; Thu, 27 Jun 2019 15:59:21 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E155168A741 for ; Thu, 27 Jun 2019 15:59:14 +0300 (EEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2019 05:59:13 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,423,1557212400"; d="scan'208";a="183445537" Received: from media_ffmpeg_skl_e3.sh.intel.com ([10.239.159.38]) by fmsmga001.fm.intel.com with ESMTP; 27 Jun 2019 05:59:12 -0700 From: Zhong Li To: ffmpeg-devel@ffmpeg.org Date: Thu, 27 Jun 2019 20:59:13 +0800 Message-Id: <1561640354-12545-2-git-send-email-zhong.li@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1561640354-12545-1-git-send-email-zhong.li@intel.com> References: <1561640354-12545-1-git-send-email-zhong.li@intel.com> Subject: [FFmpeg-devel] [PATCH 2/3] lavc/mjpeg_parser: use ff_mjpeg_decode_header to parse frame info X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Zhong Li MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Zhong Li --- 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, };