Commit 1c711b6e authored by Michael Niedermayer's avatar Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents b7c6d1ed 499b82f6
...@@ -134,6 +134,17 @@ struct vda_context { ...@@ -134,6 +134,17 @@ struct vda_context {
* - decoding: Set/Unset by libavcodec. * - decoding: Set/Unset by libavcodec.
*/ */
int priv_allocated_size; 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. */ /** Create the video decoder. */
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#include "h264.h" #include "h264.h"
struct vda_buffer {
CVPixelBufferRef cv_buffer;
};
/* Decoder callback that adds the vda frame to the queue in display order. */ /* Decoder callback that adds the vda frame to the queue in display order. */
static void vda_decoder_callback (void *vda_hw_ctx, static void vda_decoder_callback (void *vda_hw_ctx,
...@@ -108,11 +111,20 @@ static int vda_h264_decode_slice(AVCodecContext *avctx, ...@@ -108,11 +111,20 @@ static int vda_h264_decode_slice(AVCodecContext *avctx,
return 0; 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) static int vda_h264_end_frame(AVCodecContext *avctx)
{ {
H264Context *h = avctx->priv_data; H264Context *h = avctx->priv_data;
struct vda_context *vda_ctx = avctx->hwaccel_context; struct vda_context *vda_ctx = avctx->hwaccel_context;
AVFrame *frame = &h->cur_pic_ptr->f; AVFrame *frame = &h->cur_pic_ptr->f;
struct vda_buffer *context;
AVBufferRef *buffer;
int status; int status;
if (!vda_ctx->decoder || !vda_ctx->priv_bitstream) if (!vda_ctx->decoder || !vda_ctx->priv_bitstream)
...@@ -124,6 +136,20 @@ static int vda_h264_end_frame(AVCodecContext *avctx) ...@@ -124,6 +136,20 @@ static int vda_h264_end_frame(AVCodecContext *avctx)
if (status) if (status)
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", 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; return status;
} }
......
...@@ -102,6 +102,8 @@ static int vdadec_decode(AVCodecContext *avctx, ...@@ -102,6 +102,8 @@ static int vdadec_decode(AVCodecContext *avctx,
AVBufferRef *buffer = pic->buf[0]; AVBufferRef *buffer = pic->buf[0];
VDABufferContext *context = av_buffer_get_opaque(buffer); VDABufferContext *context = av_buffer_get_opaque(buffer);
CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3]; CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
CVPixelBufferRetain(cv_buffer);
CVPixelBufferLockBaseAddress(cv_buffer, 0); CVPixelBufferLockBaseAddress(cv_buffer, 0);
context->cv_buffer = cv_buffer; context->cv_buffer = cv_buffer;
pic->format = ctx->pix_fmt; pic->format = ctx->pix_fmt;
...@@ -202,6 +204,7 @@ static av_cold int vdadec_init(AVCodecContext *avctx) ...@@ -202,6 +204,7 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
vda_ctx->height = avctx->height; vda_ctx->height = avctx->height;
vda_ctx->format = 'avc1'; vda_ctx->format = 'avc1';
vda_ctx->use_sync_decoding = 1; vda_ctx->use_sync_decoding = 1;
vda_ctx->use_ref_buffer = 1;
ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
switch (ctx->pix_fmt) { switch (ctx->pix_fmt) {
case AV_PIX_FMT_UYVY422: case AV_PIX_FMT_UYVY422:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment