summaryrefslogtreecommitdiff
path: root/libavcodec/pthread_frame.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2017-01-15 13:46:27 +0100
committerAnton Khirnov <anton@khirnov.net>2020-04-10 15:45:16 +0200
commitb630a270f55647a758fefc1deb91932c0521c3c4 (patch)
treef8d614a54d01aef3ae8447bff83a7e9dbfb85aac /libavcodec/pthread_frame.c
parente40107c1ad12a53bb7d81538f35b85ed3d11c4b0 (diff)
pthread_frame: do not embed full AVFrame structs into per-thread contexts
Use the AVFrame API to properly allocate and free frames for delayed release.
Diffstat (limited to 'libavcodec/pthread_frame.c')
-rw-r--r--libavcodec/pthread_frame.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 1ad43d438a..2a3c15549f 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -93,9 +93,9 @@ typedef struct PerThreadContext {
* Array of frames passed to ff_thread_release_buffer().
* Frames are released after all threads referencing them are finished.
*/
- AVFrame *released_buffers;
- int num_released_buffers;
- int released_buffers_allocated;
+ AVFrame **released_buffers;
+ int num_released_buffers;
+ int released_buffers_allocated;
AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer()
int requested_flags; ///< flags passed to get_buffer() for requested_frame
@@ -370,7 +370,7 @@ static void release_delayed_buffers(PerThreadContext *p)
// fix extended data in case the caller screwed it up
av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO ||
p->avctx->codec_type == AVMEDIA_TYPE_AUDIO);
- f = &p->released_buffers[--p->num_released_buffers];
+ f = p->released_buffers[--p->num_released_buffers];
f->extended_data = f->data;
av_frame_unref(f);
@@ -654,7 +654,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
{
FrameThreadContext *fctx = avctx->internal->thread_ctx;
const AVCodec *codec = avctx->codec;
- int i;
+ int i, j;
park_frame_worker_threads(fctx, thread_count);
@@ -700,6 +700,9 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
pthread_cond_destroy(&p->progress_cond);
pthread_cond_destroy(&p->output_cond);
av_packet_unref(&p->avpkt);
+
+ for (j = 0; j < p->released_buffers_allocated; j++)
+ av_frame_free(&p->released_buffers[j]);
av_freep(&p->released_buffers);
if (p->avctx) {
@@ -988,7 +991,7 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
{
PerThreadContext *p = avctx->internal->thread_ctx;
FrameThreadContext *fctx;
- AVFrame *dst, *tmp;
+ AVFrame *dst;
int ret = 0;
int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) ||
THREAD_SAFE_CALLBACKS(avctx);
@@ -1011,20 +1014,22 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
fctx = p->parent;
pthread_mutex_lock(&fctx->buffer_mutex);
- if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated,
- (p->num_released_buffers + 1) *
- sizeof(*p->released_buffers));
- if (!tmp) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ if (p->num_released_buffers == p->released_buffers_allocated) {
+ AVFrame **tmp = av_realloc_array(p->released_buffers, p->released_buffers_allocated + 1,
+ sizeof(*p->released_buffers));
+ if (tmp) {
+ tmp[p->released_buffers_allocated] = av_frame_alloc();
+ p->released_buffers = tmp;
+ }
+
+ if (!tmp || !tmp[p->released_buffers_allocated]) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ p->released_buffers_allocated++;
}
- p->released_buffers = tmp;
- dst = &p->released_buffers[p->num_released_buffers];
+ dst = p->released_buffers[p->num_released_buffers];
av_frame_move_ref(dst, f->f);
p->num_released_buffers++;