summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2017-10-13 18:59:17 +0200
committerTimo Rothenpieler <timo@rothenpieler.org>2017-11-10 16:56:54 +0100
commit9f1cfd88af88a7d7d5c56a368a46639dfdfdef75 (patch)
tree3577d988bb3635da5ee09bb506591205577026c2
parent1fa3a9a31de11a2dee0efc75b89862e80ab3c90f (diff)
decode: add a method for attaching lavc-internal data to frames
Use the AVFrame.private_ref field. This new struct will be useful in the following commits. Merges Libav commit 359a8a3e2d1194b52b6c386f94fd0929567dfb67.
-rw-r--r--libavcodec/decode.c51
-rw-r--r--libavcodec/decode.h11
-rw-r--r--libavcodec/wrapped_avframe.c7
3 files changed, 67 insertions, 2 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 86fe5aef52..0f215d6915 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -613,6 +613,16 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
if (ret == AVERROR_EOF)
avci->draining_done = 1;
+ /* free the per-frame decode data */
+ if (!ret) {
+ /* the only case where decode data is not set should be decoders
+ * that do not call ff_get_buffer() */
+ av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) ||
+ !(avctx->codec->capabilities & AV_CODEC_CAP_DR1));
+
+ av_buffer_unref(&frame->private_ref);
+ }
+
return ret;
}
@@ -1552,6 +1562,37 @@ static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame)
}
}
+static void decode_data_free(void *opaque, uint8_t *data)
+{
+ FrameDecodeData *fdd = (FrameDecodeData*)data;
+
+ av_freep(&fdd);
+}
+
+int ff_attach_decode_data(AVFrame *frame)
+{
+ AVBufferRef *fdd_buf;
+ FrameDecodeData *fdd;
+
+ av_assert1(!frame->private_ref);
+ av_buffer_unref(&frame->private_ref);
+
+ 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);
+ }
+
+ frame->private_ref = fdd_buf;
+
+ return 0;
+}
+
static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
{
const AVHWAccel *hwaccel = avctx->hwaccel;
@@ -1588,8 +1629,14 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
avctx->sw_pix_fmt = avctx->pix_fmt;
ret = avctx->get_buffer2(avctx, frame, flags);
- if (ret >= 0)
- validate_avframe_allocation(avctx, frame);
+ if (ret < 0)
+ goto end;
+
+ validate_avframe_allocation(avctx, frame);
+
+ ret = ff_attach_decode_data(frame);
+ if (ret < 0)
+ goto end;
end:
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions &&
diff --git a/libavcodec/decode.h b/libavcodec/decode.h
index c9630228dc..519f875c98 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -21,9 +21,18 @@
#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
+ * private_ref.
+ */
+typedef struct FrameDecodeData {
+} FrameDecodeData;
+
+/**
* Called by decoders to get the next packet for decoding.
*
* @param pkt An empty packet to be filled with data.
@@ -36,4 +45,6 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt);
void ff_decode_bsfs_uninit(AVCodecContext *avctx);
+int ff_attach_decode_data(AVFrame *frame);
+
#endif /* AVCODEC_DECODE_H */
diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c
index 5f88a668b9..85ff32d13a 100644
--- a/libavcodec/wrapped_avframe.c
+++ b/libavcodec/wrapped_avframe.c
@@ -25,6 +25,7 @@
*/
#include "avcodec.h"
+#include "decode.h"
#include "internal.h"
#include "libavutil/internal.h"
@@ -98,6 +99,12 @@ static int wrapped_avframe_decode(AVCodecContext *avctx, void *data,
av_frame_move_ref(out, in);
+ err = ff_attach_decode_data(out);
+ if (err < 0) {
+ av_frame_unref(out);
+ return err;
+ }
+
*got_frame = 1;
return 0;
}