/**
* Array of progress values used by ff_thread_get_buffer().
*/
- int progress[MAX_BUFFERS][2];
- uint8_t progress_used[MAX_BUFFERS];
+ volatile int progress[MAX_BUFFERS][2];
+ volatile uint8_t progress_used[MAX_BUFFERS];
AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer()
} PerThreadContext;
* limit the number of threads to 16 for automatic detection */
#define MAX_AUTO_THREADS 16
-static int get_logical_cpus(AVCodecContext *avctx)
+int ff_get_logical_cpus(AVCodecContext *avctx)
{
int ret, nb_cpus = 1;
#if HAVE_SCHED_GETAFFINITY && defined(CPU_COUNT)
int thread_count = avctx->thread_count;
if (!thread_count) {
- int nb_cpus = get_logical_cpus(avctx);
+ int nb_cpus = ff_get_logical_cpus(avctx);
// use number of cores + 1 as thread count if there is more than one
if (nb_cpus > 1)
thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
AVCodecContext *avctx = p->avctx;
AVCodec *codec = avctx->codec;
+ pthread_mutex_lock(&p->mutex);
while (1) {
int i;
- if (p->state == STATE_INPUT_READY && !fctx->die) {
- pthread_mutex_lock(&p->mutex);
while (p->state == STATE_INPUT_READY && !fctx->die)
pthread_cond_wait(&p->input_cond, &p->mutex);
- pthread_mutex_unlock(&p->mutex);
- }
if (fctx->die) break;
if (!codec->update_thread_context && (avctx->thread_safe_callbacks || avctx->get_buffer == avcodec_default_get_buffer))
ff_thread_finish_setup(avctx);
- pthread_mutex_lock(&p->mutex);
avcodec_get_frame_defaults(&p->frame);
p->got_frame = 0;
p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt);
pthread_cond_broadcast(&p->progress_cond);
pthread_cond_signal(&p->output_cond);
pthread_mutex_unlock(&p->progress_mutex);
-
- pthread_mutex_unlock(&p->mutex);
}
+ pthread_mutex_unlock(&p->mutex);
return NULL;
}
int err = 0;
if (dst != src) {
- dst->sub_id = src->sub_id;
dst->time_base = src->time_base;
dst->width = src->width;
dst->height = src->height;
dst->release_buffer = src->release_buffer;
dst->opaque = src->opaque;
- dst->dsp_mask = src->dsp_mask;
dst->debug = src->debug;
dst->debug_mv = src->debug_mv;
dst->slice_flags = src->slice_flags;
dst->flags2 = src->flags2;
- copy_fields(skip_loop_filter, bidir_refine);
+ copy_fields(skip_loop_filter, subtitle_header);
dst->frame_number = src->frame_number;
dst->reordered_opaque = src->reordered_opaque;
static void free_progress(AVFrame *f)
{
PerThreadContext *p = f->owner->thread_opaque;
- int *progress = f->thread_opaque;
+ volatile int *progress = f->thread_opaque;
p->progress_used[(progress - p->progress[0]) / 2] = 0;
}
* If we're still receiving the initial packets, don't return a frame.
*/
- if (fctx->delaying && avpkt->size) {
+ if (fctx->delaying) {
if (fctx->next_decoding >= (avctx->thread_count-1)) fctx->delaying = 0;
*got_picture_ptr=0;
- return avpkt->size;
+ if (avpkt->size)
+ return avpkt->size;
}
/*
*picture = p->frame;
*got_picture_ptr = p->got_frame;
picture->pkt_dts = p->avpkt.dts;
- picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
- picture->width = avctx->width;
- picture->height = avctx->height;
- picture->format = avctx->pix_fmt;
/*
* A later call with avkpt->size == 0 may loop over all threads,
void ff_thread_report_progress(AVFrame *f, int n, int field)
{
PerThreadContext *p;
- int *progress = f->thread_opaque;
+ volatile int *progress = f->thread_opaque;
if (!progress || progress[field] >= n) return;
void ff_thread_await_progress(AVFrame *f, int n, int field)
{
PerThreadContext *p;
- int *progress = f->thread_opaque;
+ volatile int *progress = f->thread_opaque;
if (!progress || progress[field] >= n) return;
int i, err = 0;
if (!thread_count) {
- int nb_cpus = get_logical_cpus(avctx);
+ int nb_cpus = ff_get_logical_cpus(avctx);
if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv)
nb_cpus = 1;
// use number of cores + 1 as thread count if there is more than one
if (err) goto error;
- p->thread_init= !pthread_create(&p->thread, NULL, frame_worker_thread, p);
+ err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
+ p->thread_init= !err;
if(!p->thread_init)
goto error;
}
void ff_thread_flush(AVCodecContext *avctx)
{
+ int i;
FrameThreadContext *fctx = avctx->thread_opaque;
if (!avctx->thread_opaque) return;
fctx->next_decoding = fctx->next_finished = 0;
fctx->delaying = 1;
fctx->prev_thread = NULL;
+ for (i = 0; i < avctx->thread_count; i++) {
+ PerThreadContext *p = &fctx->threads[i];
+ // Make sure decode flush calls with size=0 won't return old frames
+ p->got_frame = 0;
+
+ release_delayed_buffers(p);
+ }
}
-static int *allocate_progress(PerThreadContext *p)
+static volatile int *allocate_progress(PerThreadContext *p)
{
int i;
return p->progress[i];
}
+int ff_thread_can_start_frame(AVCodecContext *avctx)
+{
+ PerThreadContext *p = avctx->thread_opaque;
+ if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP &&
+ (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
+ avctx->get_buffer != avcodec_default_get_buffer))) {
+ return 0;
+ }
+ return 1;
+}
+
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
{
PerThreadContext *p = avctx->thread_opaque;
- int *progress, err;
+ int err;
+ volatile int *progress;
f->owner = avctx;
}
pthread_mutex_lock(&p->parent->buffer_mutex);
- f->thread_opaque = progress = allocate_progress(p);
+ f->thread_opaque = (int*)(progress = allocate_progress(p));
if (!progress) {
pthread_mutex_unlock(&p->parent->buffer_mutex);
avctx->get_buffer == avcodec_default_get_buffer) {
err = avctx->get_buffer(avctx, f);
} else {
+ pthread_mutex_lock(&p->progress_mutex);
p->requested_frame = f;
p->state = STATE_GET_BUFFER;
- pthread_mutex_lock(&p->progress_mutex);
pthread_cond_broadcast(&p->progress_cond);
while (p->state != STATE_SETTING_UP)
ff_thread_finish_setup(avctx);
}
+ if (err) {
+ free_progress(f);
+ f->thread_opaque = NULL;
+ }
pthread_mutex_unlock(&p->parent->buffer_mutex);
return err;
avctx->thread_count = 1;
avctx->active_thread_type = 0;
}
+
+ if (avctx->thread_count > MAX_AUTO_THREADS)
+ av_log(avctx, AV_LOG_WARNING,
+ "Application has requested %d threads. Using a thread count greater than %d is not recommended.\n",
+ avctx->thread_count, MAX_AUTO_THREADS);
}
int ff_thread_init(AVCodecContext *avctx)