1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

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.
This commit is contained in:
Lynne
2025-01-05 15:27:30 +09:00
parent 53ff9005b5
commit 23eb499b28
2 changed files with 75 additions and 8 deletions

View File

@ -125,8 +125,10 @@ typedef struct FFV1Context {
int64_t picture_number; int64_t picture_number;
int key_frame; int key_frame;
ProgressFrame picture, last_picture; ProgressFrame picture, last_picture;
void *hwaccel_picture_private, *hwaccel_last_picture_private;
uint32_t crcref; uint32_t crcref;
enum AVPixelFormat pix_fmt; enum AVPixelFormat pix_fmt;
enum AVPixelFormat configured_pix_fmt;
const AVFrame *cur_enc_frame; const AVFrame *cur_enc_frame;
int plane_count; int plane_count;

View File

@ -41,6 +41,9 @@
#include "libavutil/refstruct.h" #include "libavutil/refstruct.h"
#include "thread.h" #include "thread.h"
#include "decode.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, static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
int bits) int bits)
@ -403,9 +406,12 @@ static int read_header(FFV1Context *f, RangeCoder *c)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (f->configured_pix_fmt != f->pix_fmt) {
f->avctx->pix_fmt = get_pixel_format(f); f->avctx->pix_fmt = get_pixel_format(f);
if (f->avctx->pix_fmt < 0) if (f->avctx->pix_fmt < 0)
return AVERROR(EINVAL); return AVERROR(EINVAL);
f->configured_pix_fmt = f->pix_fmt;
}
ff_dlog(f->avctx, "%d %d %d\n", ff_dlog(f->avctx, "%d %d %d\n",
f->chroma_h_shift, f->chroma_v_shift, f->pix_fmt); 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; FFV1Context *f = avctx->priv_data;
int ret; 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) if ((ret = ff_ffv1_common_init(avctx, f)) < 0)
return ret; return ret;
@ -682,13 +691,16 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
FFV1Context *f = avctx->priv_data; FFV1Context *f = avctx->priv_data;
int ret; int ret;
AVFrame *p; AVFrame *p;
const FFHWAccel *hwaccel = NULL;
/* This is copied onto the first slice's range coder context */ /* This is copied onto the first slice's range coder context */
RangeCoder c; RangeCoder c;
ff_progress_frame_unref(&f->last_picture); 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->avctx = avctx;
f->frame_damaged = 0; f->frame_damaged = 0;
@ -704,11 +716,18 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
if (avctx->skip_frame >= AVDISCARD_ALL) if (avctx->skip_frame >= AVDISCARD_ALL)
return avpkt->size; return avpkt->size;
if (avctx->hwaccel)
hwaccel = ffhwaccel(avctx->hwaccel);
ret = ff_progress_frame_get_buffer(avctx, &f->picture, ret = ff_progress_frame_get_buffer(avctx, &f->picture,
AV_GET_BUFFER_FLAG_REF); AV_GET_BUFFER_FLAG_REF);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = ff_hwaccel_frame_priv_alloc(avctx, &f->hwaccel_picture_private);
if (ret < 0)
return ret;
p = f->picture.f; p = f->picture.f;
p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P 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; 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); ff_thread_finish_setup(avctx);
/* 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); ret = decode_slices(avctx, c, avpkt);
if (ret < 0) if (ret < 0)
return ret; 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_report(&f->picture, INT_MAX);
ff_progress_frame_unref(&f->last_picture); 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) if ((ret = av_frame_ref(rframe, f->picture.f)) < 0)
return ret; return ret;
@ -758,6 +815,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
fdst->ac = fsrc->ac; fdst->ac = fsrc->ac;
fdst->colorspace = fsrc->colorspace; fdst->colorspace = fsrc->colorspace;
fdst->pix_fmt = fsrc->pix_fmt; fdst->pix_fmt = fsrc->pix_fmt;
fdst->configured_pix_fmt = fsrc->configured_pix_fmt;
fdst->ec = fsrc->ec; fdst->ec = fsrc->ec;
fdst->intra = fsrc->intra; 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); av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
ff_progress_frame_replace(&fdst->picture, &fsrc->picture); ff_progress_frame_replace(&fdst->picture, &fsrc->picture);
av_refstruct_replace(&fdst->hwaccel_picture_private,
fsrc->hwaccel_picture_private);
return 0; return 0;
} }
@ -803,8 +863,10 @@ static av_cold int ffv1_decode_close(AVCodecContext *avctx)
FFV1Context *const s = avctx->priv_data; FFV1Context *const s = avctx->priv_data;
ff_progress_frame_unref(&s->picture); ff_progress_frame_unref(&s->picture);
av_refstruct_unref(&s->hwaccel_picture_private);
ff_progress_frame_unref(&s->last_picture); ff_progress_frame_unref(&s->last_picture);
av_freep(&avctx->stats_out); av_refstruct_unref(&s->hwaccel_last_picture_private);
ff_ffv1_close(s); ff_ffv1_close(s);
@ -826,4 +888,7 @@ const FFCodec ff_ffv1_decoder = {
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP |
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM |
FF_CODEC_CAP_USES_PROGRESSFRAMES, FF_CODEC_CAP_USES_PROGRESSFRAMES,
.hw_configs = (const AVCodecHWConfigInternal *const []) {
NULL
},
}; };