Re: [FFmpeg-devel] [PATCH 7/9] mjpegdec: convert to receive_frame()
On 12/1/2020 5:19 PM, Anton Khirnov wrote: This will be useful in the following commit. --- libavcodec/jpeglsdec.c| 2 +- libavcodec/mjpegdec.c | 71 +-- libavcodec/mjpegdec.h | 8 ++-- libavcodec/sp5xdec.c | 28 ++ tests/ref/fate/exif-image-jpg | 4 +- 5 files changed, 72 insertions(+), 41 deletions(-) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 0b1e139048..e72f9f2315 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -551,7 +551,7 @@ AVCodec ff_jpegls_decoder = { .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, -.decode = ff_mjpeg_decode_frame, +.receive_frame = ff_mjpeg_receive_frame, .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 147dd819e5..96dfc3dc19 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -36,6 +36,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "copy_block.h" +#include "decode.h" #include "hwconfig.h" #include "idctdsp.h" #include "internal.h" @@ -163,6 +164,10 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->picture_ptr = s->picture; } +s->pkt = av_packet_alloc(); +if (!s->pkt) +return AVERROR(ENOMEM); + s->avctx = avctx; ff_blockdsp_init(>bdsp, avctx); ff_hpeldsp_init(>hdsp, avctx->flags); @@ -2336,12 +2341,32 @@ static void reset_icc_profile(MJpegDecodeContext *s) s->iccnum = 0; } -int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mjpeg_get_packet(AVCodecContext *avctx) +{ +MJpegDecodeContext *s = avctx->priv_data; +int ret; + +av_packet_unref(s->pkt); +ret = ff_decode_get_packet(avctx, s->pkt); +if (ret < 0) +return ret; + +#if CONFIG_SP5X_DECODER || CONFIG_AMV_DECODER +if (avctx->codec_id == AV_CODEC_ID_SP5X || +avctx->codec_id == AV_CODEC_ID_AMV) { +ret = ff_sp5x_process_packet(avctx, s->pkt); +if (ret < 0) +return ret; +} +#endif + +s->buf_size = s->pkt->size; + +return 0; +} + +int ff_mjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) { -AVFrame *frame = data; -const uint8_t *buf = avpkt->data; -int buf_size = avpkt->size; MJpegDecodeContext *s = avctx->priv_data; const uint8_t *buf_end, *buf_ptr; const uint8_t *unescaped_buf_ptr; @@ -2352,8 +2377,6 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int ret = 0; int is16bit; -s->buf_size = buf_size; - av_dict_free(>exif_metadata); av_freep(>stereo3d); s->adobe_transform = -1; @@ -2361,8 +2384,12 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->iccnum != 0) reset_icc_profile(s); -buf_ptr = buf; -buf_end = buf + buf_size; +ret = mjpeg_get_packet(avctx); +if (ret < 0) +return ret; + +buf_ptr = s->pkt->data; +buf_end = s->pkt->data + s->pkt->size; while (buf_ptr < buf_end) { /* find start next marker */ start_code = ff_mjpeg_find_marker(s, _ptr, buf_end, @@ -2374,7 +2401,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } else if (unescaped_buf_size > INT_MAX / 8) { av_log(avctx, AV_LOG_ERROR, "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n", - start_code, unescaped_buf_size, buf_size); + start_code, unescaped_buf_size, s->pkt->size); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n", @@ -2511,6 +2538,7 @@ eoi_parser: } if (avctx->skip_frame == AVDISCARD_ALL) { s->got_picture = 0; +ret = AVERROR(EAGAIN); goto the_end_no_picture; } if (s->avctx->hwaccel) { @@ -2522,9 +2550,10 @@ eoi_parser: } if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0) return ret; -*got_frame = 1; s->got_picture = 0; +frame->pkt_dts = s->pkt->dts; You should set FF_CODEC_CAP_SETS_PKT_DTS for this (Not too important considering it's only checked for AVCodec->decode() decoders, but it could change in the future, so might as well keep the decoder ready for it). + if (!s->lossless) { int qp = FFMAX3(s->qscale[0], s->qscale[1], @@ -2533,7 +2562,7 @@ eoi_parser: AVBufferRef *qp_table_buf = av_buffer_alloc(qpw);
[FFmpeg-devel] [PATCH 7/9] mjpegdec: convert to receive_frame()
This will be useful in the following commit. --- libavcodec/jpeglsdec.c| 2 +- libavcodec/mjpegdec.c | 71 +-- libavcodec/mjpegdec.h | 8 ++-- libavcodec/sp5xdec.c | 28 ++ tests/ref/fate/exif-image-jpg | 4 +- 5 files changed, 72 insertions(+), 41 deletions(-) diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 0b1e139048..e72f9f2315 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -551,7 +551,7 @@ AVCodec ff_jpegls_decoder = { .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, -.decode = ff_mjpeg_decode_frame, +.receive_frame = ff_mjpeg_receive_frame, .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 147dd819e5..96dfc3dc19 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -36,6 +36,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "copy_block.h" +#include "decode.h" #include "hwconfig.h" #include "idctdsp.h" #include "internal.h" @@ -163,6 +164,10 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->picture_ptr = s->picture; } +s->pkt = av_packet_alloc(); +if (!s->pkt) +return AVERROR(ENOMEM); + s->avctx = avctx; ff_blockdsp_init(>bdsp, avctx); ff_hpeldsp_init(>hdsp, avctx->flags); @@ -2336,12 +2341,32 @@ static void reset_icc_profile(MJpegDecodeContext *s) s->iccnum = 0; } -int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mjpeg_get_packet(AVCodecContext *avctx) +{ +MJpegDecodeContext *s = avctx->priv_data; +int ret; + +av_packet_unref(s->pkt); +ret = ff_decode_get_packet(avctx, s->pkt); +if (ret < 0) +return ret; + +#if CONFIG_SP5X_DECODER || CONFIG_AMV_DECODER +if (avctx->codec_id == AV_CODEC_ID_SP5X || +avctx->codec_id == AV_CODEC_ID_AMV) { +ret = ff_sp5x_process_packet(avctx, s->pkt); +if (ret < 0) +return ret; +} +#endif + +s->buf_size = s->pkt->size; + +return 0; +} + +int ff_mjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) { -AVFrame *frame = data; -const uint8_t *buf = avpkt->data; -int buf_size = avpkt->size; MJpegDecodeContext *s = avctx->priv_data; const uint8_t *buf_end, *buf_ptr; const uint8_t *unescaped_buf_ptr; @@ -2352,8 +2377,6 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int ret = 0; int is16bit; -s->buf_size = buf_size; - av_dict_free(>exif_metadata); av_freep(>stereo3d); s->adobe_transform = -1; @@ -2361,8 +2384,12 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->iccnum != 0) reset_icc_profile(s); -buf_ptr = buf; -buf_end = buf + buf_size; +ret = mjpeg_get_packet(avctx); +if (ret < 0) +return ret; + +buf_ptr = s->pkt->data; +buf_end = s->pkt->data + s->pkt->size; while (buf_ptr < buf_end) { /* find start next marker */ start_code = ff_mjpeg_find_marker(s, _ptr, buf_end, @@ -2374,7 +2401,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } else if (unescaped_buf_size > INT_MAX / 8) { av_log(avctx, AV_LOG_ERROR, "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n", - start_code, unescaped_buf_size, buf_size); + start_code, unescaped_buf_size, s->pkt->size); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n", @@ -2511,6 +2538,7 @@ eoi_parser: } if (avctx->skip_frame == AVDISCARD_ALL) { s->got_picture = 0; +ret = AVERROR(EAGAIN); goto the_end_no_picture; } if (s->avctx->hwaccel) { @@ -2522,9 +2550,10 @@ eoi_parser: } if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0) return ret; -*got_frame = 1; s->got_picture = 0; +frame->pkt_dts = s->pkt->dts; + if (!s->lossless) { int qp = FFMAX3(s->qscale[0], s->qscale[1], @@ -2533,7 +2562,7 @@ eoi_parser: AVBufferRef *qp_table_buf = av_buffer_alloc(qpw); if (qp_table_buf) { memset(qp_table_buf->data, qp, qpw); -av_frame_set_qp_table(data, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1); +av_frame_set_qp_table(frame, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1); } if(avctx->debug &