FFmpeg
Loading...
Searching...
No Matches
frame_thread_encoder.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdatomic.h>
22
24
25#include "libavutil/avassert.h"
26#include "libavutil/cpu.h"
27#include "libavutil/mem.h"
28#include "libavutil/opt.h"
29#include "libavutil/thread.h"
30#include "avcodec.h"
31#include "avcodec_internal.h"
32#include "codec_par.h"
33#include "encode.h"
34#include "internal.h"
35#include "pthread_internal.h"
36
37#define MAX_THREADS 64
38/* There can be as many as MAX_THREADS + 1 outstanding tasks.
39 * An additional + 1 is needed so that one can distinguish
40 * the case of zero and MAX_THREADS + 1 outstanding tasks modulo
41 * the number of buffers. */
42#define BUFFER_SIZE (MAX_THREADS + 2)
43
51
71
72#define OFF(member) offsetof(ThreadContext, member)
73DEFINE_OFFSET_ARRAY(ThreadContext, thread_ctx, pthread_init_cnt,
74 (OFF(task_fifo_mutex), OFF(finished_task_mutex)),
75 (OFF(task_fifo_cond), OFF(finished_task_cond)));
76#undef OFF
77
78static void * attribute_align_arg worker(void *v){
79 AVCodecContext *avctx = v;
81
82 while (!atomic_load(&c->exit)) {
83 int ret;
86 Task *task;
87 unsigned task_index;
88
89 pthread_mutex_lock(&c->task_fifo_mutex);
90 while (c->next_task_index == c->task_index || atomic_load(&c->exit)) {
91 if (atomic_load(&c->exit)) {
92 pthread_mutex_unlock(&c->task_fifo_mutex);
93 goto end;
94 }
95 pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);
96 }
97 task_index = c->next_task_index;
98 c->next_task_index = (c->next_task_index + 1) % c->max_tasks;
99 pthread_mutex_unlock(&c->task_fifo_mutex);
100 /* The main thread ensures that any two outstanding tasks have
101 * different indices, ergo each worker thread owns its element
102 * of c->tasks with the exception of finished, which is shared
103 * with the main thread and guarded by finished_task_mutex. */
104 task = &c->tasks[task_index];
105 frame = task->indata;
106 pkt = task->outdata;
107
108 ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet);
109 pthread_mutex_lock(&c->finished_task_mutex);
110 task->return_code = ret;
111 task->finished = 1;
112 pthread_cond_signal(&c->finished_task_cond);
113 pthread_mutex_unlock(&c->finished_task_mutex);
114 }
115end:
116 avcodec_free_context(&avctx);
117 return NULL;
118}
119
121{
122 int i=0;
124 AVCodecContext *thread_avctx = NULL;
125 AVCodecParameters *par = NULL;
126 int ret;
127
128 if( !(avctx->thread_type & FF_THREAD_FRAME)
130 return 0;
131
132 if( !avctx->thread_count
133 && avctx->codec_id == AV_CODEC_ID_MJPEG
134 && !(avctx->flags & AV_CODEC_FLAG_QSCALE)) {
135 av_log(avctx, AV_LOG_DEBUG,
136 "Forcing thread count to 1 for MJPEG encoding, use -thread_type slice "
137 "or a constant quantizer if you want to use multiple cpu cores\n");
138 avctx->thread_count = 1;
139 }
140 if( avctx->thread_count > 1
141 && avctx->codec_id == AV_CODEC_ID_MJPEG
142 && !(avctx->flags & AV_CODEC_FLAG_QSCALE))
143 av_log(avctx, AV_LOG_WARNING,
144 "MJPEG CBR encoding works badly with frame multi-threading, consider "
145 "using -threads 1, -thread_type slice or a constant quantizer.\n");
146
147 if (avctx->codec_id == AV_CODEC_ID_HUFFYUV ||
148 avctx->codec_id == AV_CODEC_ID_FFVHUFF) {
149 int warn = 0;
150 int64_t tmp;
151
152 if (avctx->flags & AV_CODEC_FLAG_PASS1)
153 warn = 1;
154 else if (av_opt_get_int(avctx->priv_data, "context", 0, &tmp) >= 0 &&
155 tmp > 0) {
156 warn = av_opt_get_int(avctx->priv_data, "non_deterministic", 0, &tmp) < 0
157 || !tmp;
158 }
159 // huffyuv does not support these with multiple frame threads currently
160 if (warn) {
161 av_log(avctx, AV_LOG_WARNING,
162 "Forcing thread count to 1 for huffyuv encoding with first pass or context 1\n");
163 avctx->thread_count = 1;
164 }
165 }
166
167 if(!avctx->thread_count) {
168 avctx->thread_count = av_cpu_count();
169 avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
170 }
171
172 if(avctx->thread_count <= 1)
173 return 0;
174
175 if(avctx->thread_count > MAX_THREADS)
176 return AVERROR(EINVAL);
177
180 if(!c)
181 return AVERROR(ENOMEM);
182
183 c->parent_avctx = avctx;
184
185 ret = ff_pthread_init(c, thread_ctx_offsets);
186 if (ret < 0)
187 goto fail;
188 atomic_init(&c->exit, 0);
189
190 c->max_tasks = avctx->thread_count + 2;
191 for (unsigned j = 0; j < c->max_tasks; j++) {
192 if (!(c->tasks[j].indata = av_frame_alloc()) ||
193 !(c->tasks[j].outdata = av_packet_alloc())) {
194 ret = AVERROR(ENOMEM);
195 goto fail;
196 }
197 }
198
200 if (!par) {
201 ret = AVERROR(ENOMEM);
202 goto fail;
203 }
204
205 ret = avcodec_parameters_from_context(par, avctx);
206 if (ret < 0)
207 goto fail;
208
209 for(i=0; i<avctx->thread_count ; i++){
210 thread_avctx = avcodec_alloc_context3(avctx->codec);
211 if (!thread_avctx) {
212 ret = AVERROR(ENOMEM);
213 goto fail;
214 }
215
216 ret = avcodec_parameters_to_context(thread_avctx, par);
217 if (ret < 0)
218 goto fail;
219
220 ret = av_opt_copy(thread_avctx, avctx);
221 if (ret < 0)
222 goto fail;
223 if (avctx->codec->priv_class) {
224 ret = av_opt_copy(thread_avctx->priv_data, avctx->priv_data);
225 if (ret < 0)
226 goto fail;
227 }
228 thread_avctx->thread_count = 1;
229 thread_avctx->active_thread_type &= ~FF_THREAD_FRAME;
230
231#define DUP_MATRIX(m) \
232 if (avctx->m) { \
233 thread_avctx->m = av_memdup(avctx->m, 64 * sizeof(*avctx->m)); \
234 if (!thread_avctx->m) { \
235 ret = AVERROR(ENOMEM); \
236 goto fail; \
237 } \
238 }
239 DUP_MATRIX(intra_matrix);
240 DUP_MATRIX(chroma_intra_matrix);
241 DUP_MATRIX(inter_matrix);
242
243#undef DUP_MATRIX
244
245 thread_avctx->opaque = avctx->opaque;
246 thread_avctx->get_encode_buffer = avctx->get_encode_buffer;
247 thread_avctx->execute = avctx->execute;
248 thread_avctx->execute2 = avctx->execute2;
249 thread_avctx->stats_in = avctx->stats_in;
250
251 if ((ret = avcodec_open2(thread_avctx, avctx->codec, NULL)) < 0)
252 goto fail;
254 thread_avctx->internal->frame_thread_encoder = c;
255 if ((ret = pthread_create(&c->worker[i], NULL, worker, thread_avctx))) {
256 ret = AVERROR(ret);
257 goto fail;
258 }
259 }
260
262
264
265 return 0;
266fail:
268 avcodec_free_context(&thread_avctx);
269 avctx->thread_count = i;
270 av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n");
272 return ret;
273}
274
276{
278
279 /* In case initializing the mutexes/condition variables failed,
280 * they must not be used. In this case the thread_count is zero
281 * as no thread has been initialized yet. */
282 if (avctx->thread_count > 0) {
283 pthread_mutex_lock(&c->task_fifo_mutex);
284 atomic_store(&c->exit, 1);
285 pthread_cond_broadcast(&c->task_fifo_cond);
286 pthread_mutex_unlock(&c->task_fifo_mutex);
287
288 for (int i = 0; i < avctx->thread_count; i++)
289 pthread_join(c->worker[i], NULL);
290 }
291
292 for (unsigned i = 0; i < c->max_tasks; i++) {
293 av_frame_free(&c->tasks[i].indata);
294 av_packet_free(&c->tasks[i].outdata);
295 }
296
297 ff_pthread_free(c, thread_ctx_offsets);
299}
300
302 AVFrame *frame, int *got_packet_ptr)
303{
305 Task *outtask;
306
307 av_assert1(!*got_packet_ptr);
308
309 if(frame){
310 av_frame_move_ref(c->tasks[c->task_index].indata, frame);
311
312 pthread_mutex_lock(&c->task_fifo_mutex);
313 c->task_index = (c->task_index + 1) % c->max_tasks;
314 pthread_cond_signal(&c->task_fifo_cond);
315 pthread_mutex_unlock(&c->task_fifo_mutex);
316 }
317
318 outtask = &c->tasks[c->finished_task_index];
319 pthread_mutex_lock(&c->finished_task_mutex);
320 /* The access to task_index in the following code is ok,
321 * because it is only ever changed by the main thread. */
322 if (c->task_index == c->finished_task_index ||
323 (frame && !outtask->finished &&
324 (c->task_index - c->finished_task_index + c->max_tasks) % c->max_tasks <= avctx->thread_count)) {
325 pthread_mutex_unlock(&c->finished_task_mutex);
326 return 0;
327 }
328 while (!outtask->finished) {
329 pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
330 }
331 pthread_mutex_unlock(&c->finished_task_mutex);
332 /* We now own outtask completely: No worker thread touches it any more,
333 * because there is no outstanding task with this index. */
334 outtask->finished = 0;
335 av_packet_move_ref(pkt, outtask->outdata);
336 *got_packet_ptr = outtask->got_packet;
337 c->finished_task_index = (c->finished_task_index + 1) % c->max_tasks;
338
339 return outtask->return_code;
340}
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define FF_THREAD_FRAME
Decode more than one frame at once.
Definition avcodec.h:1591
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Definition codec_par.c:138
AVCodecParameters * avcodec_parameters_alloc(void)
Definition codec_par.c:57
void avcodec_parameters_free(AVCodecParameters **ppar)
Definition codec_par.c:67
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Definition codec_par.c:206
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
static AVFrame * frame
#define atomic_store(object, desired)
Definition stdatomic.h:85
intptr_t atomic_int
Definition stdatomic.h:55
#define atomic_load(object)
Definition stdatomic.h:93
#define atomic_init(obj, value)
Definition stdatomic.h:33
int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt, AVFrame *frame, int *got_packet)
Definition encode.c:293
static void *attribute_align_arg worker(void *v)
av_cold int ff_frame_thread_encoder_init(AVCodecContext *avctx)
Initialize frame thread encoder.
int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, AVFrame *frame, int *got_packet_ptr)
#define BUFFER_SIZE
#define MAX_THREADS
av_cold void ff_frame_thread_encoder_free(AVCodecContext *avctx)
#define OFF(member)
#define DUP_MATRIX(m)
#define fail
Definition test.h:479
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition avcodec.c:144
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition options.c:149
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition avcodec.h:213
#define AV_CODEC_FLAG_PASS1
Use internal 2pass ratecontrol in first pass mode.
Definition avcodec.h:290
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition codec.h:98
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition options.c:164
@ AV_CODEC_ID_FFVHUFF
Definition codec_id.h:117
@ AV_CODEC_ID_HUFFYUV
Definition codec_id.h:75
@ AV_CODEC_ID_MJPEG
Definition codec_id.h:57
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:491
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
#define AVERROR(e)
Definition error.h:45
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition frame.c:523
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
Definition opt.c:1347
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition opt.c:2217
common internal api header.
av_cold void ff_pthread_free(void *obj, const unsigned offsets[])
Definition pthread.c:92
av_cold int ff_pthread_init(void *obj, const unsigned offsets[])
Initialize/destroy a list of mutexes/conditions contained in a structure.
Definition pthread.c:105
#define av_cold
Definition attributes.h:117
int av_cpu_count(void)
Definition cpu.c:228
#define attribute_align_arg
Definition internal.h:50
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
AVOptions.
static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
Definition os2threads.h:168
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition os2threads.h:158
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition os2threads.h:119
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition os2threads.h:94
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition os2threads.h:80
_fmutex pthread_mutex_t
Definition os2threads.h:53
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition os2threads.h:132
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition os2threads.h:198
#define DEFINE_OFFSET_ARRAY(type, name, cnt_variable, mutexes, conds)
main external API structure.
Definition avcodec.h:443
char * stats_in
pass2 encoding statistics input buffer Concatenated stuff from stats_out of pass1 should be placed he...
Definition avcodec.h:1338
int active_thread_type
Which multithreading methods are in use by the codec.
Definition avcodec.h:1599
int(* get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags)
This callback is called at the beginning of each packet to get a data buffer for it.
Definition avcodec.h:1873
const struct AVCodec * codec
Definition avcodec.h:452
int thread_type
Which multithreading methods to use.
Definition avcodec.h:1590
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:1610
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition avcodec.h:1580
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition avcodec.h:485
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
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:1629
enum AVCodecID codec_id
Definition avcodec.h:453
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * frame_thread_encoder
Definition internal.h:98
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
const AVClass * priv_class
AVClass for the private context.
Definition codec.h:197
int capabilities
Codec capabilities.
Definition codec.h:194
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
AVPacket * outdata
AVFrame * indata
pthread_mutex_t task_fifo_mutex
pthread_mutex_t finished_task_mutex
pthread_t worker[MAX_THREADS]
Task tasks[BUFFER_SIZE]
pthread_cond_t finished_task_cond
pthread_cond_t task_fifo_cond
AVCodecContext * parent_avctx
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
static double c[64]