On 06/08/2013 01:01 PM, Sebastien Zwickert wrote:
> From: Xidorn Quan <[email protected]>
>
> This patch fixes a leak of buffer when seeking occurs.
> It adds a flag in struct vda_context for compatibility with apps which
> currently use it. If the flag is not set, the hwaccel will behave like
> before.
> ---
> libavcodec/vda.h | 11 +++++++++++
> libavcodec/vda_h264.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/libavcodec/vda.h b/libavcodec/vda.h
> index 987b94f..13e4fc5 100644
> --- a/libavcodec/vda.h
> +++ b/libavcodec/vda.h
> @@ -125,6 +125,17 @@ struct vda_context {
> * The reference size used for fast reallocation.
> */
> 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 6c1845a..564fc81 100644
> --- a/libavcodec/vda_h264.c
> +++ b/libavcodec/vda_h264.c
> @@ -28,6 +28,10 @@
> #include "h264.h"
> #include "vda.h"
>
> +struct vda_buffer {
> + CVPixelBufferRef cv_buffer;
> +};
It is an unneeded level of indirection IMHO.
> /* Decoder callback that adds the VDA frame to the queue in display order. */
> static void vda_decoder_callback(void *vda_hw_ctx,
> CFDictionaryRef user_info,
> @@ -107,12 +111,21 @@ 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;
CVPixelBufferRef *context = opaque
> + CVPixelBufferRelease(context->cv_buffer);
*context
> + 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;
> - int status;
> + struct vda_buffer *context;
> + AVBufferRef *buffer;
> + int status, i;
>
> if (!vda_ctx->decoder || !vda_ctx->priv_bitstream)
> return -1;
> @@ -123,6 +136,36 @@ 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;
> +
> + buffer = NULL;
> +
> + /* VDA workaround to release properly each core video buffers:
> + * we need to create an extra av buffer with a custom freeing callback.
> This extra buffer
> + * should not be ref counted to avoid potential memory leaks. That's why
> we put it
> + * after the first free entry of AVFrame.buf to not ref this extra
> buffer in
> + * AVFrame.av_frame_ref(). */
> + for (i = 1; i < AV_NUM_DATA_POINTERS; i++) {
> + if (!frame->buf[i] && !frame->buf[i-1]) {
> + context = av_mallocz(sizeof(*context));
what prevents context from being a CVPixelBufferRef ?
> + 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;
*context = vda_ctx->cv_buffer;
lu
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel