avcodec/frame_thread_encoder: Stop serializing unreferencing AVFrames
Currently, the frame-threaded decoding API still supports thread-unsafe callbacks. If one uses a thread-unsafe get_buffer2() callback, calls to av_frame_unref() by the decoder are serialized, because it is presumed that the underlying deallocator is thread-unsafe. The frame-threaded encoder seems to have been written with this restriction in mind: It always serializes unreferencing its AVFrames, although no documentation forces it to do so. This commit schedules to change this behaviour as soon as thread-unsafe callbacks are removed. For this reason, the FF_API_THREAD_SAFE_CALLBACKS define is reused. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
25ea90b733
commit
65f6851448
@ -190,7 +190,7 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
|
int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
|
||||||
const AVFrame *frame, int *got_packet)
|
AVFrame *frame, int *got_packet)
|
||||||
{
|
{
|
||||||
const FFCodec *const codec = ffcodec(avctx->codec);
|
const FFCodec *const codec = ffcodec(avctx->codec);
|
||||||
int ret;
|
int ret;
|
||||||
@ -227,6 +227,10 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
|
|||||||
unref:
|
unref:
|
||||||
av_packet_unref(avpkt);
|
av_packet_unref(avpkt);
|
||||||
}
|
}
|
||||||
|
#if !FF_API_THREAD_SAFE_CALLBACKS
|
||||||
|
if (frame)
|
||||||
|
av_frame_unref(frame);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -267,8 +271,10 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt)
|
|||||||
ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet);
|
ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet);
|
||||||
else {
|
else {
|
||||||
ret = ff_encode_encode_cb(avctx, avpkt, frame, &got_packet);
|
ret = ff_encode_encode_cb(avctx, avpkt, frame, &got_packet);
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
if (frame)
|
if (frame)
|
||||||
av_frame_unref(frame);
|
av_frame_unref(frame);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avci->draining && !got_packet)
|
if (avci->draining && !got_packet)
|
||||||
|
@ -76,7 +76,7 @@ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size);
|
|||||||
int ff_encode_preinit(AVCodecContext *avctx);
|
int ff_encode_preinit(AVCodecContext *avctx);
|
||||||
|
|
||||||
int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
|
int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
|
||||||
const AVFrame *frame, int *got_packet);
|
AVFrame *frame, int *got_packet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rescale from sample rate to AVCodecContext.time_base.
|
* Rescale from sample rate to AVCodecContext.time_base.
|
||||||
|
@ -48,7 +48,9 @@ typedef struct{
|
|||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
AVCodecContext *parent_avctx;
|
AVCodecContext *parent_avctx;
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
pthread_mutex_t buffer_mutex;
|
pthread_mutex_t buffer_mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */
|
pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */
|
||||||
pthread_cond_t task_fifo_cond;
|
pthread_cond_t task_fifo_cond;
|
||||||
@ -68,9 +70,15 @@ typedef struct{
|
|||||||
} ThreadContext;
|
} ThreadContext;
|
||||||
|
|
||||||
#define OFF(member) offsetof(ThreadContext, member)
|
#define OFF(member) offsetof(ThreadContext, member)
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt,
|
DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt,
|
||||||
(OFF(buffer_mutex), OFF(task_fifo_mutex), OFF(finished_task_mutex)),
|
(OFF(buffer_mutex), OFF(task_fifo_mutex), OFF(finished_task_mutex)),
|
||||||
(OFF(task_fifo_cond), OFF(finished_task_cond)));
|
(OFF(task_fifo_cond), OFF(finished_task_cond)));
|
||||||
|
#else
|
||||||
|
DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt,
|
||||||
|
(OFF(task_fifo_mutex), OFF(finished_task_mutex)),
|
||||||
|
(OFF(task_fifo_cond), OFF(finished_task_cond)));
|
||||||
|
#endif
|
||||||
#undef OFF
|
#undef OFF
|
||||||
|
|
||||||
static void * attribute_align_arg worker(void *v){
|
static void * attribute_align_arg worker(void *v){
|
||||||
@ -104,9 +112,11 @@ static void * attribute_align_arg worker(void *v){
|
|||||||
pkt = task->outdata;
|
pkt = task->outdata;
|
||||||
|
|
||||||
ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet);
|
ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet);
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
pthread_mutex_lock(&c->buffer_mutex);
|
pthread_mutex_lock(&c->buffer_mutex);
|
||||||
av_frame_unref(frame);
|
av_frame_unref(frame);
|
||||||
pthread_mutex_unlock(&c->buffer_mutex);
|
pthread_mutex_unlock(&c->buffer_mutex);
|
||||||
|
#endif
|
||||||
pthread_mutex_lock(&c->finished_task_mutex);
|
pthread_mutex_lock(&c->finished_task_mutex);
|
||||||
task->return_code = ret;
|
task->return_code = ret;
|
||||||
task->finished = 1;
|
task->finished = 1;
|
||||||
@ -114,9 +124,13 @@ static void * attribute_align_arg worker(void *v){
|
|||||||
pthread_mutex_unlock(&c->finished_task_mutex);
|
pthread_mutex_unlock(&c->finished_task_mutex);
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
pthread_mutex_lock(&c->buffer_mutex);
|
pthread_mutex_lock(&c->buffer_mutex);
|
||||||
|
#endif
|
||||||
avcodec_close(avctx);
|
avcodec_close(avctx);
|
||||||
|
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||||
pthread_mutex_unlock(&c->buffer_mutex);
|
pthread_mutex_unlock(&c->buffer_mutex);
|
||||||
|
#endif
|
||||||
av_freep(&avctx);
|
av_freep(&avctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user