[FFmpeg-cvslog] decode: add a method for attaching lavc-internal data to frames

Anton Khirnov git at videolan.org
Sat Nov 11 00:45:59 EET 2017


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sat Jul  1 11:12:44 2017 +0200| [359a8a3e2d1194b52b6c386f94fd0929567dfb67] | committer: Anton Khirnov

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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=359a8a3e2d1194b52b6c386f94fd0929567dfb67
---

 libavcodec/decode.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/decode.h | 13 ++++++++++++
 2 files changed, 70 insertions(+)

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 &&
diff --git a/libavcodec/decode.h b/libavcodec/decode.h
index 2f29cf6107..61b53b2445 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -21,9 +21,22 @@
 #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.
  *
  * @param pkt An empty packet to be filled with data.



More information about the ffmpeg-cvslog mailing list