|
|
|
@@ -42,7 +42,6 @@ typedef struct{ |
|
|
|
AVFrame *indata; |
|
|
|
AVPacket *outdata; |
|
|
|
int64_t return_code; |
|
|
|
unsigned index; |
|
|
|
int finished; |
|
|
|
} Task; |
|
|
|
|
|
|
|
@@ -74,7 +73,8 @@ static void * attribute_align_arg worker(void *v){ |
|
|
|
int got_packet = 0, ret; |
|
|
|
AVPacket *pkt; |
|
|
|
AVFrame *frame; |
|
|
|
Task task; |
|
|
|
Task *task; |
|
|
|
unsigned task_index; |
|
|
|
|
|
|
|
pthread_mutex_lock(&c->task_fifo_mutex); |
|
|
|
while (av_fifo_size(c->task_fifo) <= 0 || atomic_load(&c->exit)) { |
|
|
|
@@ -84,14 +84,15 @@ static void * attribute_align_arg worker(void *v){ |
|
|
|
} |
|
|
|
pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex); |
|
|
|
} |
|
|
|
av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL); |
|
|
|
av_fifo_generic_read(c->task_fifo, &task_index, sizeof(task_index), NULL); |
|
|
|
pthread_mutex_unlock(&c->task_fifo_mutex); |
|
|
|
/* The main thread ensures that any two outstanding tasks have |
|
|
|
* different indices, ergo each worker thread owns its element |
|
|
|
* of c->tasks with the exception of finished, which is shared |
|
|
|
* with the main thread and guarded by finished_task_mutex. */ |
|
|
|
frame = task.indata; |
|
|
|
pkt = c->tasks[task.index].outdata; |
|
|
|
task = &c->tasks[task_index]; |
|
|
|
frame = task->indata; |
|
|
|
pkt = task->outdata; |
|
|
|
|
|
|
|
ret = avctx->codec->encode2(avctx, pkt, frame, &got_packet); |
|
|
|
if(got_packet) { |
|
|
|
@@ -106,10 +107,9 @@ static void * attribute_align_arg worker(void *v){ |
|
|
|
pthread_mutex_lock(&c->buffer_mutex); |
|
|
|
av_frame_unref(frame); |
|
|
|
pthread_mutex_unlock(&c->buffer_mutex); |
|
|
|
av_frame_free(&frame); |
|
|
|
pthread_mutex_lock(&c->finished_task_mutex); |
|
|
|
c->tasks[task.index].return_code = ret; |
|
|
|
c->tasks[task.index].finished = 1; |
|
|
|
task->return_code = ret; |
|
|
|
task->finished = 1; |
|
|
|
pthread_cond_signal(&c->finished_task_cond); |
|
|
|
pthread_mutex_unlock(&c->finished_task_mutex); |
|
|
|
} |
|
|
|
@@ -187,7 +187,7 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){ |
|
|
|
|
|
|
|
c->parent_avctx = avctx; |
|
|
|
|
|
|
|
c->task_fifo = av_fifo_alloc_array(BUFFER_SIZE, sizeof(Task)); |
|
|
|
c->task_fifo = av_fifo_alloc_array(BUFFER_SIZE, sizeof(unsigned)); |
|
|
|
if (!c->task_fifo) { |
|
|
|
av_freep(&avctx->internal->frame_thread_encoder); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
@@ -202,7 +202,8 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){ |
|
|
|
|
|
|
|
c->max_tasks = avctx->thread_count + 2; |
|
|
|
for (unsigned i = 0; i < c->max_tasks; i++) { |
|
|
|
if (!(c->tasks[i].outdata = av_packet_alloc())) |
|
|
|
if (!(c->tasks[i].indata = av_frame_alloc()) || |
|
|
|
!(c->tasks[i].outdata = av_packet_alloc())) |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -267,13 +268,8 @@ void ff_frame_thread_encoder_free(AVCodecContext *avctx){ |
|
|
|
pthread_join(c->worker[i], NULL); |
|
|
|
} |
|
|
|
|
|
|
|
while (av_fifo_size(c->task_fifo) > 0) { |
|
|
|
Task task; |
|
|
|
av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL); |
|
|
|
av_frame_free(&task.indata); |
|
|
|
} |
|
|
|
|
|
|
|
for (unsigned i = 0; i < c->max_tasks; i++) { |
|
|
|
av_frame_free(&c->tasks[i].indata); |
|
|
|
av_packet_free(&c->tasks[i].outdata); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -290,20 +286,16 @@ int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
AVFrame *frame, int *got_packet_ptr) |
|
|
|
{ |
|
|
|
ThreadContext *c = avctx->internal->frame_thread_encoder; |
|
|
|
Task *outtask, task; |
|
|
|
Task *outtask; |
|
|
|
|
|
|
|
av_assert1(!*got_packet_ptr); |
|
|
|
|
|
|
|
if(frame){ |
|
|
|
AVFrame *new = av_frame_alloc(); |
|
|
|
if(!new) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
av_frame_move_ref(new, frame); |
|
|
|
av_frame_move_ref(c->tasks[c->task_index].indata, frame); |
|
|
|
|
|
|
|
task.index = c->task_index; |
|
|
|
task.indata = (void*)new; |
|
|
|
pthread_mutex_lock(&c->task_fifo_mutex); |
|
|
|
av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL); |
|
|
|
av_fifo_generic_write(c->task_fifo, &c->task_index, |
|
|
|
sizeof(c->task_index), NULL); |
|
|
|
pthread_cond_signal(&c->task_fifo_cond); |
|
|
|
pthread_mutex_unlock(&c->task_fifo_mutex); |
|
|
|
|
|
|
|
|