Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2017-07-01 12:12:44 +0300
committerAnton Khirnov <anton@khirnov.net>2017-07-27 00:23:58 +0300
commit359a8a3e2d1194b52b6c386f94fd0929567dfb67 (patch)
tree28e98962aad413bf35d0fd25149c8a0e711eceb3 /libavcodec/decode.c
parentde77671438c24ffea93398c8dc885d4dd04477de (diff)
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.
Diffstat (limited to 'libavcodec/decode.c')
-rw-r--r--libavcodec/decode.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index f7cd7f6870..bcc119c829 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -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 &&