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);
42 typedef int (main_func)(AVCodecContext *c);
43 
44 typedef struct Progress {
47 } Progress;
48 
49 typedef struct SliceThreadContext {
54  void *args;
55  int *rets;
56  int job_size;
57 
58  int *entries;
63 
64 static void main_function(void *priv) {
65  AVCodecContext *avctx = priv;
67  c->mainfunc(avctx);
68 }
69 
70 static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
71 {
72  AVCodecContext *avctx = priv;
74  int ret;
75 
76  ret = c->func ? c->func(avctx, (char *)c->args + c->job_size * jobnr)
77  : c->func2(avctx, c->args, jobnr, threadnr);
78  if (c->rets)
79  c->rets[jobnr] = ret;
80 }
81 
83 {
85  int i;
86 
87  avpriv_slicethread_free(&c->thread);
88 
89  for (i = 0; i < c->thread_count; i++) {
90  Progress *const progress = &c->progress[i];
91  pthread_mutex_destroy(&progress->mutex);
92  pthread_cond_destroy(&progress->cond);
93  }
94 
95  av_freep(&c->entries);
96  av_freep(&c->progress);
97  av_freep(&avctx->internal->thread_ctx);
98 }
99 
100 static int thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size)
101 {
103 
104  if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1)
105  return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size);
106 
107  if (job_count <= 0)
108  return 0;
109 
110  c->job_size = job_size;
111  c->args = arg;
112  c->func = func;
113  c->rets = ret;
114 
115  avpriv_slicethread_execute(c->thread, job_count, !!c->mainfunc );
116  return 0;
117 }
118 
119 static int thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count)
120 {
122  c->func2 = func2;
123  return thread_execute(avctx, NULL, arg, ret, job_count, 0);
124 }
125 
126 int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, action_func2* func2, main_func *mainfunc, void *arg, int *ret, int job_count)
127 {
129  c->func2 = func2;
130  c->mainfunc = mainfunc;
131  return thread_execute(avctx, NULL, arg, ret, job_count, 0);
132 }
133 
135 {
137  int thread_count = avctx->thread_count;
138  void (*mainfunc)(void *);
139 
140  // We cannot do this in the encoder init as the threads are created before
141  if (av_codec_is_encoder(avctx->codec) &&
142  avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO &&
143  avctx->height > 2800)
144  thread_count = avctx->thread_count = 1;
145 
146  if (!thread_count) {
147  int nb_cpus = av_cpu_count();
148  if (avctx->height)
149  nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
150  // use number of cores + 1 as thread count if there is more than one
151  if (nb_cpus > 1)
152  thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
153  else
154  thread_count = avctx->thread_count = 1;
155  }
156 
157  if (thread_count <= 1) {
158  avctx->active_thread_type = 0;
159  return 0;
160  }
161 
162  avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c));
164  if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) {
165  if (c)
166  avpriv_slicethread_free(&c->thread);
167  av_freep(&avctx->internal->thread_ctx);
168  avctx->thread_count = 1;
169  avctx->active_thread_type = 0;
170  return 0;
171  }
172  avctx->thread_count = thread_count;
173 
174  avctx->execute = thread_execute;
175  avctx->execute2 = thread_execute2;
176  return 0;
177 }
178 
180 {
181  SliceThreadContext *const p = avctx->internal->thread_ctx;
182  int err, i = 0, thread_count = avctx->thread_count;
183 
184  p->progress = av_calloc(thread_count, sizeof(*p->progress));
185  if (!p->progress) {
186  err = AVERROR(ENOMEM);
187  goto fail;
188  }
189 
190  for (; i < thread_count; i++) {
191  Progress *const progress = &p->progress[i];
192  err = pthread_mutex_init(&progress->mutex, NULL);
193  if (err) {
194  err = AVERROR(err);
195  goto fail;
196  }
197  err = pthread_cond_init (&progress->cond, NULL);
198  if (err) {
199  err = AVERROR(err);
200  pthread_mutex_destroy(&progress->mutex);
201  goto fail;
202  }
203  }
204  err = 0;
205 fail:
206  p->thread_count = i;
207  return err;
208 }
209 
210 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
211 {
213  Progress *const progress = &p->progress[thread];
214  int *entries = p->entries;
215 
216  pthread_mutex_lock(&progress->mutex);
217  entries[field] +=n;
218  pthread_cond_signal(&progress->cond);
219  pthread_mutex_unlock(&progress->mutex);
220 }
221 
222 void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
223 {
225  Progress *progress;
226  int *entries = p->entries;
227 
228  if (!entries || !field) return;
229 
230  thread = thread ? thread - 1 : p->thread_count - 1;
231  progress = &p->progress[thread];
232 
233  pthread_mutex_lock(&progress->mutex);
234  while ((entries[field - 1] - entries[field]) < shift){
235  pthread_cond_wait(&progress->cond, &progress->mutex);
236  }
237  pthread_mutex_unlock(&progress->mutex);
238 }
239 
241 {
242  if (avctx->active_thread_type & FF_THREAD_SLICE) {
244 
245  if (p->entries_count == count) {
246  memset(p->entries, 0, p->entries_count * sizeof(*p->entries));
247  return 0;
248  }
249  av_freep(&p->entries);
250 
251  p->entries = av_calloc(count, sizeof(*p->entries));
252  if (!p->entries) {
253  p->entries_count = 0;
254  return AVERROR(ENOMEM);
255  }
256  p->entries_count = count;
257  }
258 
259  return 0;
260 }
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:68
SliceThreadContext::args
void * args
Definition: pthread_slice.c:54
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:65
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:271
SliceThreadContext::mainfunc
main_func * mainfunc
Definition: pthread_slice.c:53
internal.h
ff_slice_thread_free
void ff_slice_thread_free(AVCodecContext *avctx)
Definition: pthread_slice.c:82
SliceThreadContext::entries_count
int entries_count
Definition: pthread_slice.c:59
Progress::cond
pthread_cond_t cond
Definition: pthread_slice.c:45
AVSliceThread
struct AVSliceThread AVSliceThread
Definition: slicethread.h:22
thread.h
main_function
static void main_function(void *priv)
Definition: pthread_slice.c:64
SliceThreadContext::thread_count
int thread_count
Definition: pthread_slice.c:60
AVCodecContext::codec
const struct AVCodec * codec
Definition: avcodec.h:460
SliceThreadContext::progress
Progress * progress
Definition: pthread_slice.c:61
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:262
fail
#define fail()
Definition: checkasm.h:188
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1593
SliceThreadContext::func2
action_func2 * func2
Definition: pthread_slice.c:52
ff_thread_report_progress2
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
Definition: pthread_slice.c:210
avassert.h
func2
static double(*const func2[])(void *, double, double)
Definition: af_afftfilt.c:99
av_cold
#define av_cold
Definition: attributes.h:90
ff_thread_await_progress2
void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
Definition: pthread_slice.c:222
SliceThreadContext::job_size
int job_size
Definition: pthread_slice.c:56
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:461
arg
const char * arg
Definition: jacosubdec.c:67
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
SliceThreadContext::rets
int * rets
Definition: pthread_slice.c:55
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:486
Progress
Definition: pthread_slice.c:44
SliceThreadContext::thread
AVSliceThread * thread
Definition: pthread_slice.c:50
pthread_internal.h
SliceThreadContext::entries
int * entries
Definition: pthread_slice.c:58
ff_slice_thread_init_progress
int av_cold ff_slice_thread_init_progress(AVCodecContext *avctx)
Definition: pthread_slice.c:179
worker_func
static void worker_func(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
Definition: pthread_slice.c:70
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:82
AV_CODEC_ID_MPEG1VIDEO
@ AV_CODEC_ID_MPEG1VIDEO
Definition: codec_id.h:53
av_cpu_count
int av_cpu_count(void)
Definition: cpu.c:217
SliceThreadContext
Definition: pthread_slice.c:49
thread_execute2
static int thread_execute2(AVCodecContext *avctx, action_func2 *func2, void *arg, int *ret, int job_count)
Definition: pthread_slice.c:119
codec_internal.h
shift
static int shift(int a, int b)
Definition: bonk.c:261
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:100
SliceThreadContext::func
action_func * func
Definition: pthread_slice.c:51
ffcodec
static const av_always_inline FFCodec * ffcodec(const AVCodec *codec)
Definition: codec_internal.h:330
FF_THREAD_SLICE
#define FF_THREAD_SLICE
Decode more than one part of a single frame at once.
Definition: avcodec.h:1605
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:72
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:134
av_codec_is_encoder
int av_codec_is_encoder(const AVCodec *codec)
Definition: utils.c:78
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:126
FFCodec::caps_internal
unsigned caps_internal
Internal codec capabilities FF_CODEC_CAP_*.
Definition: codec_internal.h:136
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
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:256
pthread_cond_t
Definition: os2threads.h:58
AVCodecContext::height
int height
Definition: avcodec.h:624
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
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
ff_slice_thread_allocz_entries
int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
Definition: pthread_slice.c:240
AVCodecContext
main external API structure.
Definition: avcodec.h:451
AVCodecContext::active_thread_type
int active_thread_type
Which multithreading methods are in use by the codec.
Definition: avcodec.h:1612
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:1623
pthread_cond_wait
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
Progress::mutex
pthread_mutex_t mutex
Definition: pthread_slice.c:46
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:73
avpriv_slicethread_free
void avpriv_slicethread_free(AVSliceThread **pctx)
Destroy slice threading context.
Definition: slicethread.c:276
pthread_cond_init
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
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:1642
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:78