ffmpeg | branch: master | Lynne <d...@lynne.ee> | Sun Jan 5 15:27:30 2025 +0900| [23eb499b282ab1952461872ddea008adc7f95413] | committer: Lynne
ffv1dec: add support for hwaccels This commit adds support for hardware accelerated decoding to the decoder. The previous commits already refactored the decoder, this commit simply adds calls to hooks to decode. > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=23eb499b282ab1952461872ddea008adc7f95413 --- libavcodec/ffv1.h | 2 ++ libavcodec/ffv1dec.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 6e0e035895..761c22d11d 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -125,8 +125,10 @@ typedef struct FFV1Context { int64_t picture_number; int key_frame; ProgressFrame picture, last_picture; + void *hwaccel_picture_private, *hwaccel_last_picture_private; uint32_t crcref; enum AVPixelFormat pix_fmt; + enum AVPixelFormat configured_pix_fmt; const AVFrame *cur_enc_frame; int plane_count; diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index aa60a6c31b..f221af7ad9 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -41,6 +41,9 @@ #include "libavutil/refstruct.h" #include "thread.h" #include "decode.h" +#include "hwconfig.h" +#include "hwaccel_internal.h" +#include "config_components.h" static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, int bits) @@ -403,9 +406,12 @@ static int read_header(FFV1Context *f, RangeCoder *c) if (ret < 0) return ret; - f->avctx->pix_fmt = get_pixel_format(f); - if (f->avctx->pix_fmt < 0) - return AVERROR(EINVAL); + if (f->configured_pix_fmt != f->pix_fmt) { + f->avctx->pix_fmt = get_pixel_format(f); + if (f->avctx->pix_fmt < 0) + return AVERROR(EINVAL); + f->configured_pix_fmt = f->pix_fmt; + } ff_dlog(f->avctx, "%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift, f->pix_fmt); @@ -498,6 +504,9 @@ static av_cold int decode_init(AVCodecContext *avctx) FFV1Context *f = avctx->priv_data; int ret; + f->pix_fmt = AV_PIX_FMT_NONE; + f->configured_pix_fmt = AV_PIX_FMT_NONE; + if ((ret = ff_ffv1_common_init(avctx, f)) < 0) return ret; @@ -682,13 +691,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, FFV1Context *f = avctx->priv_data; int ret; AVFrame *p; + const FFHWAccel *hwaccel = NULL; /* This is copied onto the first slice's range coder context */ RangeCoder c; ff_progress_frame_unref(&f->last_picture); - FFSWAP(ProgressFrame, f->picture, f->last_picture); + av_refstruct_unref(&f->hwaccel_last_picture_private); + FFSWAP(ProgressFrame, f->picture, f->last_picture); + FFSWAP(void *, f->hwaccel_picture_private, f->hwaccel_last_picture_private); f->avctx = avctx; f->frame_damaged = 0; @@ -704,11 +716,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, if (avctx->skip_frame >= AVDISCARD_ALL) return avpkt->size; + if (avctx->hwaccel) + hwaccel = ffhwaccel(avctx->hwaccel); + ret = ff_progress_frame_get_buffer(avctx, &f->picture, AV_GET_BUFFER_FLAG_REF); if (ret < 0) return ret; + ret = ff_hwaccel_frame_priv_alloc(avctx, &f->hwaccel_picture_private); + if (ret < 0) + return ret; + p = f->picture.f; p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P @@ -721,15 +740,53 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, p->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } + /* Start */ + if (hwaccel) { + ret = hwaccel->start_frame(avctx, avpkt->data, avpkt->size); + if (ret < 0) + return ret; + } + ff_thread_finish_setup(avctx); - ret = decode_slices(avctx, c, avpkt); - if (ret < 0) - return ret; + /* Decode slices */ + if (hwaccel) { + uint8_t *buf_end = avpkt->data + avpkt->size; + + if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f) + ff_progress_frame_await(&f->last_picture, f->slice_count - 1); + + for (int i = f->slice_count - 1; i >= 0; i--) { + uint8_t *pos; + uint32_t len; + ret = find_next_slice(avctx, avpkt->data, buf_end, i, + &pos, &len); + if (ret < 0) + return ret; + + buf_end -= len; + + ret = hwaccel->decode_slice(avctx, pos, len); + if (ret < 0) + return ret; + } + } else { + ret = decode_slices(avctx, c, avpkt); + if (ret < 0) + return ret; + } + + /* Finalize */ + if (hwaccel) { + ret = hwaccel->end_frame(avctx); + if (ret < 0) + return ret; + } ff_progress_frame_report(&f->picture, INT_MAX); ff_progress_frame_unref(&f->last_picture); + av_refstruct_unref(&f->hwaccel_last_picture_private); if ((ret = av_frame_ref(rframe, f->picture.f)) < 0) return ret; @@ -758,6 +815,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) fdst->ac = fsrc->ac; fdst->colorspace = fsrc->colorspace; fdst->pix_fmt = fsrc->pix_fmt; + fdst->configured_pix_fmt = fsrc->configured_pix_fmt; fdst->ec = fsrc->ec; fdst->intra = fsrc->intra; @@ -793,6 +851,8 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) av_assert1(fdst->max_slice_count == fsrc->max_slice_count); ff_progress_frame_replace(&fdst->picture, &fsrc->picture); + av_refstruct_replace(&fdst->hwaccel_picture_private, + fsrc->hwaccel_picture_private); return 0; } @@ -803,8 +863,10 @@ static av_cold int ffv1_decode_close(AVCodecContext *avctx) FFV1Context *const s = avctx->priv_data; ff_progress_frame_unref(&s->picture); + av_refstruct_unref(&s->hwaccel_picture_private); + ff_progress_frame_unref(&s->last_picture); - av_freep(&avctx->stats_out); + av_refstruct_unref(&s->hwaccel_last_picture_private); ff_ffv1_close(s); @@ -826,4 +888,7 @@ const FFCodec ff_ffv1_decoder = { .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_USES_PROGRESSFRAMES, + .hw_configs = (const AVCodecHWConfigInternal *const []) { + NULL + }, }; _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog To unsubscribe, visit link above, or email ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".