X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fpthread.c;h=6ae763da8045e839b3859ad65f8cb5117b6bd871;hb=006508032057824a371bec4e629b66f8cbb26c47;hp=1800f291d738aa97c8f1684399bbf58b8a184938;hpb=ea4d5f48373ab856e01a3cf05426db6e823e01d1;p=ffmpeg diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 1800f291d73..6ae763da804 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -6,20 +6,20 @@ * to Michael Niedermayer for writing initial * implementation. * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,6 +35,20 @@ #define _GNU_SOURCE #include #endif +#if HAVE_GETPROCESSAFFINITYMASK +#include +#endif +#if HAVE_SYSCTL +#if HAVE_SYS_PARAM_H +#include +#endif +#include +#include +#include +#endif +#if HAVE_SYSCONF +#include +#endif #include "avcodec.h" #include "internal.h" @@ -44,6 +58,8 @@ #include #elif HAVE_W32THREADS #include "w32pthreads.h" +#elif HAVE_OS2THREADS +#include "os2threads.h" #endif typedef int (action_func)(AVCodecContext *c, void *arg); @@ -147,7 +163,7 @@ typedef struct FrameThreadContext { static int get_logical_cpus(AVCodecContext *avctx) { int ret, nb_cpus = 1; -#if HAVE_SCHED_GETAFFINITY +#if HAVE_SCHED_GETAFFINITY && defined(CPU_COUNT) cpu_set_t cpuset; CPU_ZERO(&cpuset); @@ -156,9 +172,29 @@ static int get_logical_cpus(AVCodecContext *avctx) if (!ret) { nb_cpus = CPU_COUNT(&cpuset); } +#elif HAVE_GETPROCESSAFFINITYMASK + DWORD_PTR proc_aff, sys_aff; + ret = GetProcessAffinityMask(GetCurrentProcess(), &proc_aff, &sys_aff); + if (ret) + nb_cpus = av_popcount64(proc_aff); +#elif HAVE_SYSCTL && defined(HW_NCPU) + int mib[2] = { CTL_HW, HW_NCPU }; + size_t len = sizeof(nb_cpus); + + ret = sysctl(mib, 2, &nb_cpus, &len, NULL, 0); + if (ret == -1) + nb_cpus = 0; +#elif HAVE_SYSCONF && defined(_SC_NPROC_ONLN) + nb_cpus = sysconf(_SC_NPROC_ONLN); +#elif HAVE_SYSCONF && defined(_SC_NPROCESSORS_ONLN) + nb_cpus = sysconf(_SC_NPROCESSORS_ONLN); #endif av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); - return FFMIN(nb_cpus, MAX_AUTO_THREADS); + + if (avctx->height) + nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16); + + return nb_cpus; } @@ -268,9 +304,11 @@ static int thread_init(AVCodecContext *avctx) if (!thread_count) { int nb_cpus = get_logical_cpus(avctx); - // use number of cores + 1 as thread count if there is motre than one + // use number of cores + 1 as thread count if there is more than one if (nb_cpus > 1) - thread_count = avctx->thread_count = nb_cpus + 1; + thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); + else + thread_count = avctx->thread_count = 1; } if (thread_count <= 1) { @@ -328,6 +366,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg) AVCodec *codec = avctx->codec; 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) @@ -337,7 +376,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg) if (fctx->die) break; - if (!codec->update_thread_context && avctx->thread_safe_callbacks) + 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); @@ -350,6 +389,12 @@ static attribute_align_arg void *frame_worker_thread(void *arg) p->state = STATE_INPUT_READY; pthread_mutex_lock(&p->progress_mutex); + for (i = 0; i < MAX_BUFFERS; i++) + if (p->progress_used[i]) { + p->progress[i][0] = INT_MAX; + p->progress[i][1] = INT_MAX; + } + pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); @@ -382,7 +427,6 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->has_b_frames = src->has_b_frames; dst->idct_algo = src->idct_algo; - dst->slice_count = src->slice_count; dst->bits_per_coded_sample = src->bits_per_coded_sample; dst->sample_aspect_ratio = src->sample_aspect_ratio; @@ -402,6 +446,7 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, } if (for_user) { + dst->delay = src->thread_count - 1; dst->coded_frame = src->coded_frame; } else { if (dst->codec->update_thread_context) @@ -416,8 +461,9 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, * * @param dst The destination context. * @param src The source context. + * @return 0 on success, negative error code on failure */ -static void update_context_from_user(AVCodecContext *dst, AVCodecContext *src) +static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) { #define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); dst->flags = src->flags; @@ -438,6 +484,23 @@ static void update_context_from_user(AVCodecContext *dst, AVCodecContext *src) dst->frame_number = src->frame_number; dst->reordered_opaque = src->reordered_opaque; + dst->thread_safe_callbacks = src->thread_safe_callbacks; + + if (src->slice_count && src->slice_offset) { + if (dst->slice_count < src->slice_count) { + int *tmp = av_realloc(dst->slice_offset, src->slice_count * + sizeof(*dst->slice_offset)); + if (!tmp) { + av_free(dst->slice_offset); + return AVERROR(ENOMEM); + } + dst->slice_offset = tmp; + } + memcpy(dst->slice_offset, src->slice_offset, + src->slice_count * sizeof(*dst->slice_offset)); + } + dst->slice_count = src->slice_count; + return 0; #undef copy_fields } @@ -548,7 +611,8 @@ int ff_thread_decode_frame(AVCodecContext *avctx, */ p = &fctx->threads[fctx->next_decoding]; - update_context_from_user(p->avctx, avctx); + err = update_context_from_user(p->avctx, avctx); + if (err) return err; err = submit_packet(p, avpkt); if (err) return err; @@ -583,6 +647,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx, *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, @@ -646,6 +714,10 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; + if(p->state == STATE_SETUP_FINISHED){ + av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); + } + pthread_mutex_lock(&p->progress_mutex); p->state = STATE_SETUP_FINISHED; pthread_cond_broadcast(&p->progress_cond); @@ -666,6 +738,7 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count pthread_cond_wait(&p->output_cond, &p->progress_mutex); pthread_mutex_unlock(&p->progress_mutex); } + p->got_frame = 0; } } @@ -691,6 +764,7 @@ static void frame_thread_free(AVCodecContext *avctx, int thread_count) if (p->thread_init) pthread_join(p->thread, NULL); + p->thread_init=0; if (codec->close) codec->close(p->avctx); @@ -715,6 +789,7 @@ static void frame_thread_free(AVCodecContext *avctx, int thread_count) if (i) { av_freep(&p->avctx->priv_data); av_freep(&p->avctx->internal); + av_freep(&p->avctx->slice_offset); } av_freep(&p->avctx); @@ -735,9 +810,13 @@ static int frame_thread_init(AVCodecContext *avctx) if (!thread_count) { int nb_cpus = get_logical_cpus(avctx); - // use number of cores + 1 as thread count if there is motre than one + 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 (nb_cpus > 1) - thread_count = avctx->thread_count = nb_cpus + 1; + thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); + else + thread_count = avctx->thread_count = 1; } if (thread_count <= 1) { @@ -792,7 +871,7 @@ static int frame_thread_init(AVCodecContext *avctx) err = AVERROR(ENOMEM); goto error; } - *(copy->internal) = *(src->internal); + *copy->internal = *src->internal; copy->internal->is_copy = 1; if (codec->init_thread_copy) @@ -801,8 +880,9 @@ static int frame_thread_init(AVCodecContext *avctx) if (err) goto error; - if (!pthread_create(&p->thread, NULL, frame_worker_thread, p)) - p->thread_init = 1; + p->thread_init= !pthread_create(&p->thread, NULL, frame_worker_thread, p); + if(!p->thread_init) + goto error; } return 0; @@ -856,13 +936,16 @@ int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f) f->owner = avctx; + ff_init_buffer_info(avctx, f); + if (!(avctx->active_thread_type&FF_THREAD_FRAME)) { f->thread_opaque = NULL; return avctx->get_buffer(avctx, f); } if (p->state != STATE_SETTING_UP && - (avctx->codec->update_thread_context || !avctx->thread_safe_callbacks)) { + (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks && + avctx->get_buffer != avcodec_default_get_buffer))) { av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; } @@ -885,7 +968,7 @@ int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f) p->requested_frame = f; p->state = STATE_GET_BUFFER; pthread_mutex_lock(&p->progress_mutex); - pthread_cond_signal(&p->progress_cond); + pthread_cond_broadcast(&p->progress_cond); while (p->state != STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); @@ -950,6 +1033,9 @@ static void validate_thread_parameters(AVCodecContext *avctx) } else if (avctx->codec->capabilities & CODEC_CAP_SLICE_THREADS && avctx->thread_type & FF_THREAD_SLICE) { avctx->active_thread_type = FF_THREAD_SLICE; + } else if (!(avctx->codec->capabilities & CODEC_CAP_AUTO_THREADS)) { + avctx->thread_count = 1; + avctx->active_thread_type = 0; } }