diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-05-27 09:31:51 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-05-27 09:32:22 +0200 |
commit | 1c711b6ecd535972ffc00f9424173ae111c67358 (patch) | |
tree | 2c6b56639a235deb7676c321286d11a13c80ddaa /libavcodec | |
parent | b7c6d1ed906453d9fcd3d8ef78f68dae68ae3ed1 (diff) | |
parent | 499b82f604616a6ce7de4bd8e15f4698702c1e6a (diff) | |
download | ffmpeg-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.h | 11 | ||||
-rw-r--r-- | libavcodec/vda_h264.c | 26 | ||||
-rw-r--r-- | libavcodec/vda_h264_dec.c | 3 |
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: |