pthread_slice.c (5000B)
1 /* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 /** 20 * @file 21 * Slice multithreading support functions 22 * @see doc/multithreading.txt 23 */ 24 25 #include "config.h" 26 27 #include "avcodec.h" 28 #include "codec_internal.h" 29 #include "internal.h" 30 #include "pthread_internal.h" 31 #include "thread.h" 32 33 #include "libavutil/avassert.h" 34 #include "libavutil/common.h" 35 #include "libavutil/cpu.h" 36 #include "libavutil/mem.h" 37 #include "libavutil/thread.h" 38 #include "libavutil/slicethread.h" 39 40 typedef int (action_func)(AVCodecContext *c, void *arg); 41 typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); 42 typedef int (main_func)(AVCodecContext *c); 43 44 typedef struct SliceThreadContext { 45 AVSliceThread *thread; 46 action_func *func; 47 action_func2 *func2; 48 main_func *mainfunc; 49 void *args; 50 int *rets; 51 int job_size; 52 } SliceThreadContext; 53 54 static void main_function(void *priv) { 55 AVCodecContext *avctx = priv; 56 SliceThreadContext *c = avctx->internal->thread_ctx; 57 c->mainfunc(avctx); 58 } 59 60 static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads) 61 { 62 AVCodecContext *avctx = priv; 63 SliceThreadContext *c = avctx->internal->thread_ctx; 64 int ret; 65 66 ret = c->func ? c->func(avctx, (char *)c->args + c->job_size * jobnr) 67 : c->func2(avctx, c->args, jobnr, threadnr); 68 if (c->rets) 69 c->rets[jobnr] = ret; 70 } 71 72 void ff_slice_thread_free(AVCodecContext *avctx) 73 { 74 SliceThreadContext *c = avctx->internal->thread_ctx; 75 76 avpriv_slicethread_free(&c->thread); 77 78 av_freep(&avctx->internal->thread_ctx); 79 } 80 81 static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size) 82 { 83 SliceThreadContext *c = avctx->internal->thread_ctx; 84 85 if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1) 86 return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size); 87 88 if (job_count <= 0) 89 return 0; 90 91 c->job_size = job_size; 92 c->args = arg; 93 c->func = func; 94 c->rets = ret; 95 96 avpriv_slicethread_execute(c->thread, job_count, !!c->mainfunc ); 97 return 0; 98 } 99 100 static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count) 101 { 102 SliceThreadContext *c = avctx->internal->thread_ctx; 103 c->func2 = func2; 104 return thread_execute(avctx, NULL, arg, ret, job_count, 0); 105 } 106 107 int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2* func2, main_func *mainfunc, void *arg, int *ret, int job_count) 108 { 109 SliceThreadContext *c = avctx->internal->thread_ctx; 110 c->func2 = func2; 111 c->mainfunc = mainfunc; 112 return thread_execute(avctx, NULL, arg, ret, job_count, 0); 113 } 114 115 int ff_slice_thread_init(AVCodecContext *avctx) 116 { 117 SliceThreadContext *c; 118 int thread_count = avctx->thread_count; 119 void (*mainfunc)(void *); 120 121 // We cannot do this in the encoder init as the threads are created before 122 if (av_codec_is_encoder(avctx->codec) && 123 avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && 124 avctx->height > 2800) 125 thread_count = avctx->thread_count = 1; 126 127 if (!thread_count) { 128 int nb_cpus = av_cpu_count(); 129 if (avctx->height) 130 nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16); 131 // use number of cores + 1 as thread count if there is more than one 132 if (nb_cpus > 1) 133 thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); 134 else 135 thread_count = avctx->thread_count = 1; 136 } 137 138 if (thread_count <= 1) { 139 avctx->active_thread_type = 0; 140 return 0; 141 } 142 143 avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c)); 144 mainfunc = ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL; 145 if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) { 146 if (c) 147 avpriv_slicethread_free(&c->thread); 148 av_freep(&avctx->internal->thread_ctx); 149 avctx->thread_count = 1; 150 avctx->active_thread_type = 0; 151 return 0; 152 } 153 avctx->thread_count = thread_count; 154 155 avctx->execute = thread_execute; 156 avctx->execute2 = thread_execute2; 157 return 0; 158 }