1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2004 Roman Shaposhnik 3cabdff1aSopenharmony_ci * Copyright (c) 2008 Alexander Strange (astrange@ithinksw.com) 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * Many thanks to Steven M. Schultz for providing clever ideas and 6cabdff1aSopenharmony_ci * to Michael Niedermayer <michaelni@gmx.at> for writing initial 7cabdff1aSopenharmony_ci * implementation. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * This file is part of FFmpeg. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 12cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 13cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 14cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 17cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 18cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19cabdff1aSopenharmony_ci * Lesser General Public License for more details. 20cabdff1aSopenharmony_ci * 21cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 22cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 23cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci/** 27cabdff1aSopenharmony_ci * @file 28cabdff1aSopenharmony_ci * Multithreading support functions 29cabdff1aSopenharmony_ci * @see doc/multithreading.txt 30cabdff1aSopenharmony_ci */ 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "libavutil/thread.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#include "avcodec.h" 35cabdff1aSopenharmony_ci#include "codec_internal.h" 36cabdff1aSopenharmony_ci#include "pthread_internal.h" 37cabdff1aSopenharmony_ci#include "thread.h" 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci/** 40cabdff1aSopenharmony_ci * Set the threading algorithms used. 41cabdff1aSopenharmony_ci * 42cabdff1aSopenharmony_ci * Threading requires more than one thread. 43cabdff1aSopenharmony_ci * Frame threading requires entire frames to be passed to the codec, 44cabdff1aSopenharmony_ci * and introduces extra decoding delay, so is incompatible with low_delay. 45cabdff1aSopenharmony_ci * 46cabdff1aSopenharmony_ci * @param avctx The context. 47cabdff1aSopenharmony_ci */ 48cabdff1aSopenharmony_cistatic void validate_thread_parameters(AVCodecContext *avctx) 49cabdff1aSopenharmony_ci{ 50cabdff1aSopenharmony_ci int frame_threading_supported = (avctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) 51cabdff1aSopenharmony_ci#if FF_API_FLAG_TRUNCATED 52cabdff1aSopenharmony_ci && !(avctx->flags & AV_CODEC_FLAG_TRUNCATED) 53cabdff1aSopenharmony_ci#endif 54cabdff1aSopenharmony_ci && !(avctx->flags & AV_CODEC_FLAG_LOW_DELAY) 55cabdff1aSopenharmony_ci && !(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS); 56cabdff1aSopenharmony_ci if (avctx->thread_count == 1) { 57cabdff1aSopenharmony_ci avctx->active_thread_type = 0; 58cabdff1aSopenharmony_ci } else if (frame_threading_supported && (avctx->thread_type & FF_THREAD_FRAME)) { 59cabdff1aSopenharmony_ci avctx->active_thread_type = FF_THREAD_FRAME; 60cabdff1aSopenharmony_ci } else if (avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS && 61cabdff1aSopenharmony_ci avctx->thread_type & FF_THREAD_SLICE) { 62cabdff1aSopenharmony_ci avctx->active_thread_type = FF_THREAD_SLICE; 63cabdff1aSopenharmony_ci } else if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) { 64cabdff1aSopenharmony_ci avctx->thread_count = 1; 65cabdff1aSopenharmony_ci avctx->active_thread_type = 0; 66cabdff1aSopenharmony_ci } 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci if (avctx->thread_count > MAX_AUTO_THREADS) 69cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 70cabdff1aSopenharmony_ci "Application has requested %d threads. Using a thread count greater than %d is not recommended.\n", 71cabdff1aSopenharmony_ci avctx->thread_count, MAX_AUTO_THREADS); 72cabdff1aSopenharmony_ci} 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ciint ff_thread_init(AVCodecContext *avctx) 75cabdff1aSopenharmony_ci{ 76cabdff1aSopenharmony_ci validate_thread_parameters(avctx); 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci if (avctx->active_thread_type&FF_THREAD_SLICE) 79cabdff1aSopenharmony_ci return ff_slice_thread_init(avctx); 80cabdff1aSopenharmony_ci else if (avctx->active_thread_type&FF_THREAD_FRAME) 81cabdff1aSopenharmony_ci return ff_frame_thread_init(avctx); 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci return 0; 84cabdff1aSopenharmony_ci} 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_civoid ff_thread_free(AVCodecContext *avctx) 87cabdff1aSopenharmony_ci{ 88cabdff1aSopenharmony_ci if (avctx->active_thread_type&FF_THREAD_FRAME) 89cabdff1aSopenharmony_ci ff_frame_thread_free(avctx, avctx->thread_count); 90cabdff1aSopenharmony_ci else 91cabdff1aSopenharmony_ci ff_slice_thread_free(avctx); 92cabdff1aSopenharmony_ci} 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ciav_cold void ff_pthread_free(void *obj, const unsigned offsets[]) 95cabdff1aSopenharmony_ci{ 96cabdff1aSopenharmony_ci unsigned cnt = *(unsigned*)((char*)obj + offsets[0]); 97cabdff1aSopenharmony_ci const unsigned *cur_offset = offsets; 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci *(unsigned*)((char*)obj + offsets[0]) = 0; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci for (; *(++cur_offset) != THREAD_SENTINEL && cnt; cnt--) 102cabdff1aSopenharmony_ci pthread_mutex_destroy((pthread_mutex_t*)((char*)obj + *cur_offset)); 103cabdff1aSopenharmony_ci for (; *(++cur_offset) != THREAD_SENTINEL && cnt; cnt--) 104cabdff1aSopenharmony_ci pthread_cond_destroy ((pthread_cond_t *)((char*)obj + *cur_offset)); 105cabdff1aSopenharmony_ci} 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ciav_cold int ff_pthread_init(void *obj, const unsigned offsets[]) 108cabdff1aSopenharmony_ci{ 109cabdff1aSopenharmony_ci const unsigned *cur_offset = offsets; 110cabdff1aSopenharmony_ci unsigned cnt = 0; 111cabdff1aSopenharmony_ci int err; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci#define PTHREAD_INIT_LOOP(type) \ 114cabdff1aSopenharmony_ci for (; *(++cur_offset) != THREAD_SENTINEL; cnt++) { \ 115cabdff1aSopenharmony_ci pthread_ ## type ## _t *dst = (void*)((char*)obj + *cur_offset); \ 116cabdff1aSopenharmony_ci err = pthread_ ## type ## _init(dst, NULL); \ 117cabdff1aSopenharmony_ci if (err) { \ 118cabdff1aSopenharmony_ci err = AVERROR(err); \ 119cabdff1aSopenharmony_ci goto fail; \ 120cabdff1aSopenharmony_ci } \ 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci PTHREAD_INIT_LOOP(mutex) 123cabdff1aSopenharmony_ci PTHREAD_INIT_LOOP(cond) 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_cifail: 126cabdff1aSopenharmony_ci *(unsigned*)((char*)obj + offsets[0]) = cnt; 127cabdff1aSopenharmony_ci return err; 128cabdff1aSopenharmony_ci} 129