Instead of allocating/freeing, use objpool for data passed from an input frame to an output packet.
Signed-off-by: Rick Kern <ker...@gmail.com> --- libavcodec/videotoolboxenc.c | 80 ++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index dc9e321d3d..184feb029b 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -24,6 +24,7 @@ #include <TargetConditionals.h> #include <Availability.h> #include "avcodec.h" +#include "libavutil/objpool.h" #include "libavutil/opt.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -251,8 +252,49 @@ typedef struct VTEncContext { /* can't be bool type since AVOption will access it as int */ int a53_cc; + + AVObjPool *output_node_pool; } VTEncContext; +static BufNode *output_node_alloc(void) { return av_mallocz(sizeof(BufNode)); } +static void output_node_free(BufNode **node) { av_freep(node); } +static void output_node_reset(BufNode *node) { + if (node->cm_buffer != NULL) { + CFRelease(node->cm_buffer); + } + + if (node->sei != NULL) { + if (node->sei->data != NULL) { + av_free(node->sei->data); + } + + av_free(node->sei); + } + + memset(node, 0, sizeof(*node)); +} + +static int alloc_output_node_pool(AVObjPool **pool_out) { + AVObjPool *pool = NULL; + + if (pool_out == NULL) { + return AVERROR(EINVAL); + } + + pool = av_objpool_alloc( + (AVObjPoolCBAlloc)output_node_alloc, + (AVObjPoolCBReset)output_node_reset, + (AVObjPoolCBFree)output_node_free); + + if (pool == NULL) { + return AVERROR(ENOMEM); + } + + *pool_out = pool; + + return 0; +} + static int vtenc_populate_extradata(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, @@ -285,8 +327,7 @@ static void set_async_error(VTEncContext *vtctx, int err) while (info) { BufNode *next = info->next; - CFRelease(info->cm_buffer); - av_free(info); + av_objpool_release(vtctx->output_node_pool, (void**)&info); info = next; } @@ -336,22 +377,29 @@ static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, E pthread_mutex_unlock(&vtctx->lock); *buf = info->cm_buffer; + if (*buf != NULL) { + CFRetain(*buf); + } + if (sei && *buf) { *sei = info->sei; - } else if (info->sei) { - if (info->sei->data) av_free(info->sei->data); - av_free(info->sei); + info->sei = NULL; } - av_free(info); + av_objpool_release(vtctx->output_node_pool, (void**)&info); return 0; } static void vtenc_q_push(VTEncContext *vtctx, CMSampleBufferRef buffer, ExtraSEI *sei) { - BufNode *info = av_malloc(sizeof(BufNode)); - if (!info) { + BufNode *info = NULL; + int status = av_objpool_get(vtctx->output_node_pool, (void**)&info); + + if (status < 0) { + set_async_error(vtctx, status); + return; + } else if (!info) { set_async_error(vtctx, AVERROR(ENOMEM)); return; } @@ -1569,6 +1617,16 @@ static av_cold int vtenc_init(AVCodecContext *avctx) pthread_mutex_init(&vtctx->lock, NULL); pthread_cond_init(&vtctx->cv_sample_sent, NULL); + status = alloc_output_node_pool(&vtctx->output_node_pool); + + if (status < 0) { + av_log( + avctx, + AV_LOG_ERROR, + "Failed to allocate output pool (%d)\n", + status); + } + vtctx->session = NULL; status = vtenc_configure_encoder(avctx); if (status) return status; @@ -1589,7 +1647,7 @@ static av_cold int vtenc_init(AVCodecContext *avctx) } avctx->has_b_frames = vtctx->has_b_frames; - return 0; + return status; } static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame) @@ -2647,6 +2705,10 @@ static av_cold int vtenc_close(AVCodecContext *avctx) vtctx->ycbcr_matrix = NULL; } + if (vtctx->output_node_pool != NULL) { + av_objpool_free(&vtctx->output_node_pool); + } + return 0; } -- 2.38.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".