aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2013-05-27 09:31:51 +0200
committerMichael Niedermayer <michaelni@gmx.at>2013-05-27 09:32:22 +0200
commit1c711b6ecd535972ffc00f9424173ae111c67358 (patch)
tree2c6b56639a235deb7676c321286d11a13c80ddaa /libavcodec
parentb7c6d1ed906453d9fcd3d8ef78f68dae68ae3ed1 (diff)
parent499b82f604616a6ce7de4bd8e15f4698702c1e6a (diff)
downloadffmpeg-1c711b6ecd535972ffc00f9424173ae111c67358.tar.gz
Merge remote-tracking branch 'dilaroga/master'
* dilaroga/master: avcodec/vda_h264_dec: fix a memory leak avcodec/vda_h264: use av_buffer to manage buffers Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/vda.h11
-rw-r--r--libavcodec/vda_h264.c26
-rw-r--r--libavcodec/vda_h264_dec.c3
3 files changed, 40 insertions, 0 deletions
diff --git a/libavcodec/vda.h b/libavcodec/vda.h
index 281785f294..b3d6399a65 100644
--- a/libavcodec/vda.h
+++ b/libavcodec/vda.h
@@ -134,6 +134,17 @@ struct vda_context {
* - decoding: Set/Unset by libavcodec.
*/
int priv_allocated_size;
+
+ /**
+ * Use av_buffer to manage buffer.
+ * When the flag is set, the CVPixelBuffers returned by the decoder will
+ * be released automatically, so you have to retain them if necessary.
+ * Not setting this flag may cause memory leak.
+ *
+ * encoding: unused
+ * decoding: Set by user.
+ */
+ int use_ref_buffer;
};
/** Create the video decoder. */
diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c
index d0237c2279..c01a21a533 100644
--- a/libavcodec/vda_h264.c
+++ b/libavcodec/vda_h264.c
@@ -28,6 +28,9 @@
#include "libavutil/avutil.h"
#include "h264.h"
+struct vda_buffer {
+ CVPixelBufferRef cv_buffer;
+};
/* Decoder callback that adds the vda frame to the queue in display order. */
static void vda_decoder_callback (void *vda_hw_ctx,
@@ -108,11 +111,20 @@ static int vda_h264_decode_slice(AVCodecContext *avctx,
return 0;
}
+static void vda_h264_release_buffer(void *opaque, uint8_t *data)
+{
+ struct vda_buffer *context = opaque;
+ CVPixelBufferRelease(context->cv_buffer);
+ av_free(context);
+}
+
static int vda_h264_end_frame(AVCodecContext *avctx)
{
H264Context *h = avctx->priv_data;
struct vda_context *vda_ctx = avctx->hwaccel_context;
AVFrame *frame = &h->cur_pic_ptr->f;
+ struct vda_buffer *context;
+ AVBufferRef *buffer;
int status;
if (!vda_ctx->decoder || !vda_ctx->priv_bitstream)
@@ -124,6 +136,20 @@ static int vda_h264_end_frame(AVCodecContext *avctx)
if (status)
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
+ if (!vda_ctx->use_ref_buffer || status)
+ return status;
+
+ context = av_mallocz(sizeof(*context));
+ buffer = av_buffer_create(NULL, 0, vda_h264_release_buffer, context, 0);
+ if (!context || !buffer) {
+ CVPixelBufferRelease(vda_ctx->cv_buffer);
+ av_free(context);
+ return -1;
+ }
+
+ context->cv_buffer = vda_ctx->cv_buffer;
+ frame->buf[3] = buffer;
+
return status;
}
diff --git a/libavcodec/vda_h264_dec.c b/libavcodec/vda_h264_dec.c
index 4e60de0126..5857e0a365 100644
--- a/libavcodec/vda_h264_dec.c
+++ b/libavcodec/vda_h264_dec.c
@@ -102,6 +102,8 @@ static int vdadec_decode(AVCodecContext *avctx,
AVBufferRef *buffer = pic->buf[0];
VDABufferContext *context = av_buffer_get_opaque(buffer);
CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
+
+ CVPixelBufferRetain(cv_buffer);
CVPixelBufferLockBaseAddress(cv_buffer, 0);
context->cv_buffer = cv_buffer;
pic->format = ctx->pix_fmt;
@@ -202,6 +204,7 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
vda_ctx->height = avctx->height;
vda_ctx->format = 'avc1';
vda_ctx->use_sync_decoding = 1;
+ vda_ctx->use_ref_buffer = 1;
ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
switch (ctx->pix_fmt) {
case AV_PIX_FMT_UYVY422: