avcodec/decode: Extend ff_hwaccel_frame_priv_alloc()'s task
All usages of ff_hwaccel_frame_priv_alloc() have the same pattern: Check for whether a hwaccel is in use; check whether it needs private frame-specific data; allocate the AVBuffer and set it. This commit modifies ff_hwaccel_frame_priv_alloc() to perform this task on its own. (It also seems that the H.264 decoder did not perform proper cleanup in case the buffer could not be allocated. This has been changed.) Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
dcc1847b18
commit
c48cc9c6e9
@ -907,17 +907,11 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avctx->hwaccel) {
|
ret = ff_hwaccel_frame_priv_alloc(avctx, &f->hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel = avctx->hwaccel;
|
&f->hwaccel_priv_buf);
|
||||||
if (hwaccel->frame_priv_data_size) {
|
if (ret < 0)
|
||||||
f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, hwaccel);
|
|
||||||
if (!f->hwaccel_priv_buf) {
|
|
||||||
ret = AVERROR(ENOMEM);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1788,24 +1788,36 @@ int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx,
|
int ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, void **hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel)
|
AVBufferRef **hwaccel_priv_buf)
|
||||||
{
|
{
|
||||||
|
const AVHWAccel *hwaccel = avctx->hwaccel;
|
||||||
AVBufferRef *ref;
|
AVBufferRef *ref;
|
||||||
AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
|
AVHWFramesContext *frames_ctx;
|
||||||
uint8_t *data = av_mallocz(hwaccel->frame_priv_data_size);
|
uint8_t *data;
|
||||||
|
|
||||||
|
if (!hwaccel || !hwaccel->frame_priv_data_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
av_assert0(!*hwaccel_picture_private);
|
||||||
|
data = av_mallocz(hwaccel->frame_priv_data_size);
|
||||||
if (!data)
|
if (!data)
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
|
||||||
|
|
||||||
ref = av_buffer_create(data, hwaccel->frame_priv_data_size,
|
ref = av_buffer_create(data, hwaccel->frame_priv_data_size,
|
||||||
hwaccel->free_frame_priv,
|
hwaccel->free_frame_priv,
|
||||||
frames_ctx->device_ctx, 0);
|
frames_ctx->device_ctx, 0);
|
||||||
if (!ref) {
|
if (!ref) {
|
||||||
av_free(data);
|
av_free(data);
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref;
|
*hwaccel_priv_buf = ref;
|
||||||
|
*hwaccel_picture_private = ref->data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_decode_flush_buffers(AVCodecContext *avctx)
|
void ff_decode_flush_buffers(AVCodecContext *avctx)
|
||||||
|
@ -140,14 +140,17 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame,
|
|||||||
enum AVMatrixEncoding matrix_encoding);
|
enum AVMatrixEncoding matrix_encoding);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a hwaccel frame private data and create an AVBufferRef
|
* Allocate a hwaccel frame private data if the provided avctx
|
||||||
* from it.
|
* uses a hwaccel method that needs it. The private data will
|
||||||
|
* be refcounted via the AVBuffer API (if allocated).
|
||||||
*
|
*
|
||||||
* @param avctx The codec context which to attach as an opaque value
|
* @param avctx The codec context
|
||||||
* @param hwaccel The hwaccel for which to allocate
|
* @param hwaccel_picture_private Pointer to return hwaccel_picture_private
|
||||||
* @return The allocated buffer
|
* @param hwaccel_priv_buf Pointer to return the AVBufferRef owning
|
||||||
|
* hwaccel_picture_private
|
||||||
|
* @return 0 on success, < 0 on error
|
||||||
*/
|
*/
|
||||||
AVBufferRef *ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx,
|
int ff_hwaccel_frame_priv_alloc(AVCodecContext *avctx, void **hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel);
|
AVBufferRef **hwaccel_priv_buf);
|
||||||
|
|
||||||
#endif /* AVCODEC_DECODE_H */
|
#endif /* AVCODEC_DECODE_H */
|
||||||
|
@ -205,16 +205,11 @@ static int alloc_picture(H264Context *h, H264Picture *pic)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->avctx->hwaccel) {
|
ret = ff_hwaccel_frame_priv_alloc(h->avctx, &pic->hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel = h->avctx->hwaccel;
|
&pic->hwaccel_priv_buf);
|
||||||
av_assert0(!pic->hwaccel_picture_private);
|
if (ret < 0)
|
||||||
if (hwaccel->frame_priv_data_size) {
|
goto fail;
|
||||||
pic->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(h->avctx, hwaccel);
|
|
||||||
if (!pic->hwaccel_priv_buf)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CONFIG_GRAY && !h->avctx->hwaccel && h->flags & AV_CODEC_FLAG_GRAY && pic->f->data[2]) {
|
if (CONFIG_GRAY && !h->avctx->hwaccel && h->flags & AV_CODEC_FLAG_GRAY && pic->f->data[2]) {
|
||||||
int h_chroma_shift, v_chroma_shift;
|
int h_chroma_shift, v_chroma_shift;
|
||||||
av_pix_fmt_get_chroma_sub_sample(pic->f->format,
|
av_pix_fmt_get_chroma_sub_sample(pic->f->format,
|
||||||
|
@ -118,16 +118,10 @@ static HEVCFrame *alloc_frame(HEVCContext *s)
|
|||||||
(s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD))
|
(s->sei.picture_timing.picture_struct == AV_PICTURE_STRUCTURE_BOTTOM_FIELD))
|
||||||
frame->frame->flags |= AV_FRAME_FLAG_INTERLACED;
|
frame->frame->flags |= AV_FRAME_FLAG_INTERLACED;
|
||||||
|
|
||||||
if (s->avctx->hwaccel) {
|
ret = ff_hwaccel_frame_priv_alloc(s->avctx, &frame->hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel = s->avctx->hwaccel;
|
&frame->hwaccel_priv_buf);
|
||||||
av_assert0(!frame->hwaccel_picture_private);
|
if (ret < 0)
|
||||||
if (hwaccel->frame_priv_data_size) {
|
|
||||||
frame->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(s->avctx, hwaccel);
|
|
||||||
if (!frame->hwaccel_priv_buf)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
frame->hwaccel_picture_private = frame->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
fail:
|
fail:
|
||||||
|
@ -171,17 +171,10 @@ static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic,
|
|||||||
pic->f->height = avctx->height;
|
pic->f->height = avctx->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avctx->hwaccel) {
|
ret = ff_hwaccel_frame_priv_alloc(avctx, &pic->hwaccel_picture_private,
|
||||||
assert(!pic->hwaccel_picture_private);
|
&pic->hwaccel_priv_buf);
|
||||||
if (avctx->hwaccel->frame_priv_data_size) {
|
if (ret < 0)
|
||||||
pic->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, avctx->hwaccel);
|
return ret;
|
||||||
if (!pic->hwaccel_priv_buf) {
|
|
||||||
av_log(avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((linesize && linesize != pic->f->linesize[0]) ||
|
if ((linesize && linesize != pic->f->linesize[0]) ||
|
||||||
(uvlinesize && uvlinesize != pic->f->linesize[1])) {
|
(uvlinesize && uvlinesize != pic->f->linesize[1])) {
|
||||||
|
@ -104,23 +104,21 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref)
|
|||||||
if ((ret = ff_thread_get_ext_buffer(s->avctx, &f->tf,
|
if ((ret = ff_thread_get_ext_buffer(s->avctx, &f->tf,
|
||||||
ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
|
ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height)))
|
if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) {
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
if (s->avctx->hwaccel) {
|
}
|
||||||
const AVHWAccel *hwaccel = s->avctx->hwaccel;
|
ret = ff_hwaccel_frame_priv_alloc(s->avctx, &f->hwaccel_picture_private,
|
||||||
if (hwaccel->frame_priv_data_size) {
|
&f->hwaccel_priv_buf);
|
||||||
f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(s->avctx, hwaccel);
|
if (ret < 0)
|
||||||
if (!f->hwaccel_priv_buf)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
av_buffer_unref(&f->seg_map);
|
av_buffer_unref(&f->seg_map);
|
||||||
ff_thread_release_ext_buffer(s->avctx, &f->tf);
|
ff_thread_release_ext_buffer(s->avctx, &f->tf);
|
||||||
return AVERROR(ENOMEM);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vp8_release_frame(VP8Context *s, VP8Frame *f)
|
static void vp8_release_frame(VP8Context *s, VP8Frame *f)
|
||||||
|
@ -119,12 +119,14 @@ static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f)
|
|||||||
s->frame_extradata_pool = av_buffer_pool_init(sz * (1 + sizeof(VP9mvrefPair)), NULL);
|
s->frame_extradata_pool = av_buffer_pool_init(sz * (1 + sizeof(VP9mvrefPair)), NULL);
|
||||||
if (!s->frame_extradata_pool) {
|
if (!s->frame_extradata_pool) {
|
||||||
s->frame_extradata_pool_size = 0;
|
s->frame_extradata_pool_size = 0;
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->frame_extradata_pool_size = sz;
|
s->frame_extradata_pool_size = sz;
|
||||||
}
|
}
|
||||||
f->extradata = av_buffer_pool_get(s->frame_extradata_pool);
|
f->extradata = av_buffer_pool_get(s->frame_extradata_pool);
|
||||||
if (!f->extradata) {
|
if (!f->extradata) {
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
memset(f->extradata->data, 0, f->extradata->size);
|
memset(f->extradata->data, 0, f->extradata->size);
|
||||||
@ -132,22 +134,16 @@ static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f)
|
|||||||
f->segmentation_map = f->extradata->data;
|
f->segmentation_map = f->extradata->data;
|
||||||
f->mv = (VP9mvrefPair *) (f->extradata->data + sz);
|
f->mv = (VP9mvrefPair *) (f->extradata->data + sz);
|
||||||
|
|
||||||
if (avctx->hwaccel) {
|
ret = ff_hwaccel_frame_priv_alloc(avctx, &f->hwaccel_picture_private,
|
||||||
const AVHWAccel *hwaccel = avctx->hwaccel;
|
&f->hwaccel_priv_buf);
|
||||||
av_assert0(!f->hwaccel_picture_private);
|
if (ret < 0)
|
||||||
if (hwaccel->frame_priv_data_size) {
|
|
||||||
f->hwaccel_priv_buf = ff_hwaccel_frame_priv_alloc(avctx, hwaccel);
|
|
||||||
if (!f->hwaccel_priv_buf)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
vp9_frame_unref(avctx, f);
|
vp9_frame_unref(avctx, f);
|
||||||
return AVERROR(ENOMEM);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vp9_frame_ref(AVCodecContext *avctx, VP9Frame *dst, VP9Frame *src)
|
static int vp9_frame_ref(AVCodecContext *avctx, VP9Frame *dst, VP9Frame *src)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user