2 * This file is part of FFmpeg.
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.
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.
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
21 * Slice multithreading support functions
22 * @see doc/multithreading.txt
28 #include "codec_internal.h"
30 #include "pthread_internal.h"
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"
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
);
44 typedef struct SliceThreadContext
{
45 AVSliceThread
*thread
;
54 static void main_function(void *priv
) {
55 AVCodecContext
*avctx
= priv
;
56 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
60 static void worker_func(void *priv
, int jobnr
, int threadnr
, int nb_jobs
, int nb_threads
)
62 AVCodecContext
*avctx
= priv
;
63 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
66 ret
= c
->func
? c
->func(avctx
, (char *)c
->args
+ c
->job_size
* jobnr
)
67 : c
->func2(avctx
, c
->args
, jobnr
, threadnr
);
72 void ff_slice_thread_free(AVCodecContext
*avctx
)
74 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
76 avpriv_slicethread_free(&c
->thread
);
78 av_freep(&avctx
->internal
->thread_ctx
);
81 static int thread_execute(AVCodecContext
*avctx
, action_func
* func
, void *arg
, int *ret
, int job_count
, int job_size
)
83 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
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
);
91 c
->job_size
= job_size
;
96 avpriv_slicethread_execute(c
->thread
, job_count
, !!c
->mainfunc
);
100 static int thread_execute2(AVCodecContext
*avctx
, action_func2
* func2
, void *arg
, int *ret
, int job_count
)
102 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
104 return thread_execute(avctx
, NULL
, arg
, ret
, job_count
, 0);
107 int ff_slice_thread_execute_with_mainfunc(AVCodecContext
*avctx
, action_func2
* func2
, main_func
*mainfunc
, void *arg
, int *ret
, int job_count
)
109 SliceThreadContext
*c
= avctx
->internal
->thread_ctx
;
111 c
->mainfunc
= mainfunc
;
112 return thread_execute(avctx
, NULL
, arg
, ret
, job_count
, 0);
115 int ff_slice_thread_init(AVCodecContext
*avctx
)
117 SliceThreadContext
*c
;
118 int thread_count
= avctx
->thread_count
;
119 void (*mainfunc
)(void *);
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;
128 int nb_cpus
= av_cpu_count();
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
133 thread_count
= avctx
->thread_count
= FFMIN(nb_cpus
+ 1, MAX_AUTO_THREADS
);
135 thread_count
= avctx
->thread_count
= 1;
138 if (thread_count
<= 1) {
139 avctx
->active_thread_type
= 0;
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) {
147 avpriv_slicethread_free(&c
->thread
);
148 av_freep(&avctx
->internal
->thread_ctx
);
149 avctx
->thread_count
= 1;
150 avctx
->active_thread_type
= 0;
153 avctx
->thread_count
= thread_count
;
155 avctx
->execute
= thread_execute
;
156 avctx
->execute2
= thread_execute2
;