[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