int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){ ThreadContext *c = avctx->internal->frame_thread_encoder; Task task; int ret; av_assert1(!*got_packet_ptr); if(frame){ if(!(avctx->flags & CODEC_FLAG_INPUT_PRESERVED)){ AVFrame *new = avcodec_alloc_frame(); if(!new) return AVERROR(ENOMEM); pthread_mutex_lock(&c->buffer_mutex); ret = c->parent_avctx->get_buffer(c->parent_avctx, new); pthread_mutex_unlock(&c->buffer_mutex); if(ret<0) return ret; new->pts = frame->pts; new->quality = frame->quality; new->pict_type = frame->pict_type; av_image_copy(new->data, new->linesize, (const uint8_t **)frame->data, frame->linesize, avctx->pix_fmt, avctx->width, avctx->height); frame = new; } task.index = c->task_index; task.indata = (void*)frame; pthread_mutex_lock(&c->task_fifo_mutex); av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL); pthread_cond_signal(&c->task_fifo_cond); pthread_mutex_unlock(&c->task_fifo_mutex); c->task_index = (c->task_index+1) % BUFFER_SIZE; if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count) return 0; } if(c->task_index == c->finished_task_index) return 0; pthread_mutex_lock(&c->finished_task_mutex); while (!c->finished_tasks[c->finished_task_index].outdata) { pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex); } task = c->finished_tasks[c->finished_task_index]; *pkt = *(AVPacket*)(task.outdata); av_freep(&c->finished_tasks[c->finished_task_index].outdata); c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE; pthread_mutex_unlock(&c->finished_task_mutex); *got_packet_ptr = 1; return task.return_code; }