FFmpeg
pthread_slice.c
Go to the documentation of this file.
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);
43 
44 typedef struct SliceThreadContext {
49  void *args;
50  int *rets;
51  int job_size;
52 
53  int *entries;
59 
60 static void main_function(void *priv) {
61  AVCodecContext *avctx = priv;
63  c->mainfunc(avctx);
64 }
65 
66 static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
67 {
68  AVCodecContext *avctx = priv;
70  int ret;
71 
72  ret = c->func ? c->func(avctx, (char *)c->args + c->job_size * jobnr)
73  : c->func2(avctx, c->args, jobnr, threadnr);
74  if (c->rets)
75  c->rets[jobnr] = ret;
76 }
77 
79 {
81  int i;
82 
83  avpriv_slicethread_free(&c->thread);
84 
85  for (i = 0; i < c->thread_count; i++) {
86  pthread_mutex_destroy(&c->progress_mutex[i]);
87  pthread_cond_destroy(&c->progress_cond[i]);
88  }
89 
90  av_freep(&c->entries);
91  av_freep(&c->progress_mutex);
92  av_freep(&c->progress_cond);
93  av_freep(&avctx->internal->thread_ctx);
94 }
95 
96 static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size)
97 {
99 
100  if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1)
101  return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size);
102 
103  if (job_count <= 0)
104  return 0;
105 
106  c->job_size = job_size;
107  c->args = arg;
108  c->func = func;
109  c->rets = ret;
110 
111  avpriv_slicethread_execute(c->thread, job_count, !!c->mainfunc );
112  return 0;
113 }
114 
115 static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count)
116 {
118  c->func2 = func2;
119  return thread_execute(avctx, NULL, arg, ret, job_count, 0);
120 }
121 
122 int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2* func2, main_func *mainfunc, void *arg, int *ret, int job_count)
123 {
125  c->func2 = func2;
126  c->mainfunc = mainfunc;
127  return thread_execute(avctx, NULL, arg, ret, job_count, 0);
128 }
129 
131 {
133  int thread_count = avctx->thread_count;
134  void (*mainfunc)(void *);
135 
136  // We cannot do this in the encoder init as the threads are created before
137  if (av_codec_is_encoder(avctx->codec) &&
138  avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO &&
139  avctx->height > 2800)
140  thread_count = avctx->thread_count = 1;
141 
142  if (!thread_count) {
143  int nb_cpus = av_cpu_count();
144  if (avctx->height)
145  nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
146  // use number of cores + 1 as thread count if there is more than one
147  if (nb_cpus > 1)
148  thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
149  else
150  thread_count = avctx->thread_count = 1;
151  }
152 
153  if (thread_count <= 1) {
154  avctx->active_thread_type = 0;
155  return 0;
156  }
157 
158  avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c));
160  if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) {
161  if (c)
162  avpriv_slicethread_free(&c->thread);
163  av_freep(&avctx->internal->thread_ctx);
164  avctx->thread_count = 1;
165  avctx->active_thread_type = 0;
166  return 0;
167  }
168  avctx->thread_count = thread_count;
169 
170  avctx->execute = thread_execute;
171  avctx->execute2 = thread_execute2;
172  return 0;
173 }
174 
175 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
176 {
178  int *entries = p->entries;
179 
180  pthread_mutex_lock(&p->progress_mutex[thread]);
181  entries[field] +=n;
182  pthread_cond_signal(&p->progress_cond[thread]);
184 }
185 
186 void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
187 {
189  int *entries = p->entries;
190 
191  if (!entries || !field) return;
192 
193  thread = thread ? thread - 1 : p->thread_count - 1;
194 
195  pthread_mutex_lock(&p->progress_mutex[thread]);
196  while ((entries[field - 1] - entries[field]) < shift){
197  pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]);
198  }
200 }
201 
202 int ff_alloc_entries(AVCodecContext *avctx, int count)
203 {
204  int i;
205 
206  if (avctx->active_thread_type & FF_THREAD_SLICE) {
208 
209  if (p->entries) {
210  av_assert0(p->thread_count == avctx->thread_count);
211  av_freep(&p->entries);
212  }
213 
214  p->thread_count = avctx->thread_count;
215  p->entries = av_calloc(count, sizeof(*p->entries));
216 
217  if (!p->progress_mutex) {
220  }
221 
222  if (!p->entries || !p->progress_mutex || !p->progress_cond) {
223  av_freep(&p->entries);
225  av_freep(&p->progress_cond);
226  return AVERROR(ENOMEM);
227  }
228  p->entries_count = count;
229 
230  for (i = 0; i < p->thread_count; i++) {
233  }
234  }
235 
236  return 0;
237 }
238 
240 {
242  memset(p->entries, 0, p->entries_count * sizeof(int));
243 }
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:68
SliceThreadContext::args
void * args
Definition: pthread_slice.c:49
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
FF_CODEC_CAP_SLICE_THREAD_HAS_MF
#define FF_CODEC_CAP_SLICE_THREAD_HAS_MF
Codec initializes slice-based threading with a main function.
Definition: codec_internal.h:61
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
thread.h
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
MAX_AUTO_THREADS
#define MAX_AUTO_THREADS
Definition: pthread_internal.h:26
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:247
SliceThreadContext::mainfunc
main_func * mainfunc
Definition: pthread_slice.c:48
internal.h
ff_slice_thread_free
void ff_slice_thread_free(AVCodecContext *avctx)
Definition: pthread_slice.c:78
SliceThreadContext::entries_count
int entries_count
Definition: pthread_slice.c:54
AVSliceThread
struct AVSliceThread AVSliceThread
Definition: slicethread.h:22
thread.h
main_function
static void main_function(void *priv)
Definition: pthread_slice.c:60
SliceThreadContext::progress_mutex
pthread_mutex_t * progress_mutex
Definition: pthread_slice.c:57
SliceThreadContext::thread_count
int thread_count
Definition: pthread_slice.c:55
AVCodecContext::codec
const struct AVCodec * codec
Definition: avcodec.h:398
avpriv_slicethread_create
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv, void(*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads), void(*main_func)(void *priv), int nb_threads)
Create slice threading context.
Definition: slicethread.c:238
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1463
ff_reset_entries
void ff_reset_entries(AVCodecContext *avctx)
Definition: pthread_slice.c:239
SliceThreadContext::func2
action_func2 * func2
Definition: pthread_slice.c:47
ff_thread_report_progress2
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
Definition: pthread_slice.c:175
avassert.h
func2
static double(*const func2[])(void *, double, double)
Definition: af_afftfilt.c:99
ff_thread_await_progress2
void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
Definition: pthread_slice.c:186
SliceThreadContext::job_size
int job_size
Definition: pthread_slice.c:51
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
field
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
Definition: writing_filters.txt:78
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:399
arg
const char * arg
Definition: jacosubdec.c:67
if
if(ret)
Definition: filter_design.txt:179
SliceThreadContext::progress_cond
pthread_cond_t * progress_cond
Definition: pthread_slice.c:56
NULL
#define NULL
Definition: coverity.c:32
SliceThreadContext::rets
int * rets
Definition: pthread_slice.c:50
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:424
SliceThreadContext::thread
AVSliceThread * thread
Definition: pthread_slice.c:45
pthread_internal.h
SliceThreadContext::entries
int * entries
Definition: pthread_slice.c:53
worker_func
static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
Definition: pthread_slice.c:66
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:77
AV_CODEC_ID_MPEG1VIDEO
@ AV_CODEC_ID_MPEG1VIDEO
Definition: codec_id.h:51
av_cpu_count
int av_cpu_count(void)
Definition: cpu.c:194
SliceThreadContext
Definition: pthread_slice.c:44
thread_execute2
static int thread_execute2(AVCodecContext *avctx, action_func2 *func2, void *arg, int *ret, int job_count)
Definition: pthread_slice.c:115
codec_internal.h
cpu.h
thread_execute
static int thread_execute(AVCodecContext *avctx, action_func *func, void *arg, int *ret, int job_count, int job_size)
Definition: pthread_slice.c:96
SliceThreadContext::func
action_func * func
Definition: pthread_slice.c:46
ffcodec
static const av_always_inline FFCodec * ffcodec(const AVCodec *codec)
Definition: codec_internal.h:273
FF_THREAD_SLICE
#define FF_THREAD_SLICE
Decode more than one part of a single frame at once.
Definition: avcodec.h:1475
avcodec_default_execute
int avcodec_default_execute(AVCodecContext *c, int(*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size)
Definition: avcodec.c:45
pthread_cond_destroy
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
slicethread.h
ff_slice_thread_init
int ff_slice_thread_init(AVCodecContext *avctx)
Definition: pthread_slice.c:130
av_codec_is_encoder
int av_codec_is_encoder(const AVCodec *codec)
Definition: utils.c:74
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
ff_slice_thread_execute_with_mainfunc
int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2 *func2, main_func *mainfunc, void *arg, int *ret, int job_count)
Definition: pthread_slice.c:122
FFCodec::caps_internal
unsigned caps_internal
Internal codec capabilities FF_CODEC_CAP_*.
Definition: codec_internal.h:121
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
main_func
int() main_func(AVCodecContext *c)
Definition: pthread_slice.c:42
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
pthread_cond_t
Definition: os2threads.h:58
AVCodecContext::height
int height
Definition: avcodec.h:562
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
avcodec.h
ret
ret
Definition: filter_design.txt:187
action_func2
int() action_func2(AVCodecContext *c, void *arg, int jobnr, int threadnr)
Definition: pthread_slice.c:41
pthread_cond_signal
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:152
AVCodecContext
main external API structure.
Definition: avcodec.h:389
AVCodecContext::active_thread_type
int active_thread_type
Which multithreading methods are in use by the codec.
Definition: avcodec.h:1482
AVCodecContext::execute
int(* execute)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size)
The codec may call this to execute several independent things.
Definition: avcodec.h:1514
pthread_cond_wait
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
shift
static int shift(int a, int b)
Definition: sonic.c:88
mem.h
action_func
int() action_func(AVCodecContext *c, void *arg)
Definition: pthread_slice.c:40
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecInternal::thread_ctx
void * thread_ctx
Definition: internal.h:63
avpriv_slicethread_free
void avpriv_slicethread_free(AVSliceThread **pctx)
Destroy slice threading context.
Definition: slicethread.c:252
pthread_cond_init
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
int
int
Definition: ffmpeg_filter.c:153
AVCodecContext::execute2
int(* execute2)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count)
The codec may call this to execute several independent things.
Definition: avcodec.h:1534
ff_alloc_entries
int ff_alloc_entries(AVCodecContext *avctx, int count)
Definition: pthread_slice.c:202
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:73