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

Reply via email to