[FFmpeg-devel] [PATCH 2/3] lavc/mjpeg_parser: use ff_mjpeg_decode_header to parse frame info
Carl Eugen Hoyos
ceffmpeg at gmail.com
Thu Jun 27 22:05:21 EEST 2019
Am Do., 27. Juni 2019 um 14:59 Uhr schrieb Zhong Li <zhong.li at intel.com>:
>
> 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)) ) {
It may be just me but there are too many parentheses in these
lines (and not enough braces in the rest of the patch).
> + 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);
Does this patch have any effect (performance or otherwise) on
software decoding?
Carl Eugen
More information about the ffmpeg-devel
mailing list