mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-25 00:32:31 +00:00
decode: add a method for attaching lavc-internal data to frames
Use the AVFrame.opaque_ref field. The original user's opaque_ref is wrapped in the lavc struct and then unwrapped before the frame is returned to the caller. This new struct will be useful in the following commits.
This commit is contained in:
parent
de77671438
commit
359a8a3e2d
@ -406,6 +406,26 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
|
||||
if (ret == AVERROR_EOF)
|
||||
avci->draining_done = 1;
|
||||
|
||||
/* unwrap the per-frame decode data and restore the original opaque_ref*/
|
||||
if (!ret) {
|
||||
/* the only case where decode data is not set should be decoders
|
||||
* that do not call ff_get_buffer() */
|
||||
av_assert0((frame->opaque_ref && frame->opaque_ref->size == sizeof(FrameDecodeData)) ||
|
||||
!(avctx->codec->capabilities & AV_CODEC_CAP_DR1));
|
||||
|
||||
if (frame->opaque_ref) {
|
||||
FrameDecodeData *fdd;
|
||||
AVBufferRef *user_opaque_ref;
|
||||
|
||||
fdd = (FrameDecodeData*)frame->opaque_ref->data;
|
||||
|
||||
user_opaque_ref = fdd->user_opaque_ref;
|
||||
fdd->user_opaque_ref = NULL;
|
||||
av_buffer_unref(&frame->opaque_ref);
|
||||
frame->opaque_ref = user_opaque_ref;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -988,6 +1008,37 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_data_free(void *opaque, uint8_t *data)
|
||||
{
|
||||
FrameDecodeData *fdd = (FrameDecodeData*)data;
|
||||
|
||||
av_buffer_unref(&fdd->user_opaque_ref);
|
||||
|
||||
av_freep(&fdd);
|
||||
}
|
||||
|
||||
static int attach_decode_data(AVFrame *frame)
|
||||
{
|
||||
AVBufferRef *fdd_buf;
|
||||
FrameDecodeData *fdd;
|
||||
|
||||
fdd = av_mallocz(sizeof(*fdd));
|
||||
if (!fdd)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free,
|
||||
NULL, AV_BUFFER_FLAG_READONLY);
|
||||
if (!fdd_buf) {
|
||||
av_freep(&fdd);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
fdd->user_opaque_ref = frame->opaque_ref;
|
||||
frame->opaque_ref = fdd_buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
|
||||
{
|
||||
const AVHWAccel *hwaccel = avctx->hwaccel;
|
||||
@ -1061,6 +1112,12 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
|
||||
avctx->sw_pix_fmt = avctx->pix_fmt;
|
||||
|
||||
ret = avctx->get_buffer2(avctx, frame, flags);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
ret = attach_decode_data(frame);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
end:
|
||||
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions &&
|
||||
|
@ -21,8 +21,21 @@
|
||||
#ifndef AVCODEC_DECODE_H
|
||||
#define AVCODEC_DECODE_H
|
||||
|
||||
#include "libavutil/buffer.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
/**
|
||||
* This struct stores per-frame lavc-internal data and is attached to it via
|
||||
* opaque_ref.
|
||||
*/
|
||||
typedef struct FrameDecodeData {
|
||||
/**
|
||||
* The original user-set opaque_ref.
|
||||
*/
|
||||
AVBufferRef *user_opaque_ref;
|
||||
} FrameDecodeData;
|
||||
|
||||
/**
|
||||
* Called by decoders to get the next packet for decoding.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user