FFmpeg  4.4.6
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 
23 #include "frame_thread_encoder.h"
24 
25 #include "libavutil/avassert.h"
26 #include "libavutil/imgutils.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/thread.h"
29 #include "avcodec.h"
30 #include "internal.h"
31 #include "thread.h"
32 
33 #define MAX_THREADS 64
34 /* There can be as many as MAX_THREADS + 1 outstanding tasks.
35  * An additional + 1 is needed so that one can distinguish
36  * the case of zero and MAX_THREADS + 1 outstanding tasks modulo
37  * the number of buffers. */
38 #define BUFFER_SIZE (MAX_THREADS + 2)
39 
40 typedef struct{
44  int finished;
45 } Task;
46 
47 typedef struct{
50 
51  pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */
53 
54  unsigned max_tasks;
55  Task tasks[BUFFER_SIZE];
56  pthread_mutex_t finished_task_mutex; /* Guards tasks[i].finished */
58 
59  unsigned next_task_index;
60  unsigned task_index;
62 
66 
67 static void * attribute_align_arg worker(void *v){
68  AVCodecContext *avctx = v;
70 
71  while (!atomic_load(&c->exit)) {
72  int got_packet = 0, ret;
73  AVPacket *pkt;
74  AVFrame *frame;
75  Task *task;
76  unsigned task_index;
77 
78  pthread_mutex_lock(&c->task_fifo_mutex);
79  while (c->next_task_index == c->task_index || atomic_load(&c->exit)) {
80  if (atomic_load(&c->exit)) {
81  pthread_mutex_unlock(&c->task_fifo_mutex);
82  goto end;
83  }
84  pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);
85  }
86  task_index = c->next_task_index;
87  c->next_task_index = (c->next_task_index + 1) % c->max_tasks;
88  pthread_mutex_unlock(&c->task_fifo_mutex);
89  /* The main thread ensures that any two outstanding tasks have
90  * different indices, ergo each worker thread owns its element
91  * of c->tasks with the exception of finished, which is shared
92  * with the main thread and guarded by finished_task_mutex. */
93  task = &c->tasks[task_index];
94  frame = task->indata;
95  pkt = task->outdata;
96 
97  ret = avctx->codec->encode2(avctx, pkt, frame, &got_packet);
98  if(got_packet) {
99  int ret2 = av_packet_make_refcounted(pkt);
100  if (ret >= 0 && ret2 < 0)
101  ret = ret2;
102  pkt->pts = pkt->dts = frame->pts;
103  } else {
104  pkt->data = NULL;
105  pkt->size = 0;
106  }
107  pthread_mutex_lock(&c->buffer_mutex);
109  pthread_mutex_unlock(&c->buffer_mutex);
110  pthread_mutex_lock(&c->finished_task_mutex);
111  task->return_code = ret;
112  task->finished = 1;
113  pthread_cond_signal(&c->finished_task_cond);
114  pthread_mutex_unlock(&c->finished_task_mutex);
115  }
116 end:
117  pthread_mutex_lock(&c->buffer_mutex);
118  avcodec_close(avctx);
119  pthread_mutex_unlock(&c->buffer_mutex);
120  av_freep(&avctx);
121  return NULL;
122 }
123 
125  int i=0;
126  ThreadContext *c;
127  AVCodecContext *thread_avctx = NULL;
128 
129  if( !(avctx->thread_type & FF_THREAD_FRAME)
131  return 0;
132 
133  if( !avctx->thread_count
134  && avctx->codec_id == AV_CODEC_ID_MJPEG
135  && !(avctx->flags & AV_CODEC_FLAG_QSCALE)) {
136  av_log(avctx, AV_LOG_DEBUG,
137  "Forcing thread count to 1 for MJPEG encoding, use -thread_type slice "
138  "or a constant quantizer if you want to use multiple cpu cores\n");
139  avctx->thread_count = 1;
140  }
141  if( avctx->thread_count > 1
142  && avctx->codec_id == AV_CODEC_ID_MJPEG
143  && !(avctx->flags & AV_CODEC_FLAG_QSCALE))
144  av_log(avctx, AV_LOG_WARNING,
145  "MJPEG CBR encoding works badly with frame multi-threading, consider "
146  "using -threads 1, -thread_type slice or a constant quantizer.\n");
147 
148  if (avctx->codec_id == AV_CODEC_ID_HUFFYUV ||
149  avctx->codec_id == AV_CODEC_ID_FFVHUFF) {
150  int warn = 0;
151  int context_model = 0;
153 
154  if (con && con->value)
155  context_model = atoi(con->value);
156 
157  if (avctx->flags & AV_CODEC_FLAG_PASS1)
158  warn = 1;
159  else if(context_model > 0) {
160  AVDictionaryEntry *t = av_dict_get(options, "non_deterministic",
162  warn = !t || !t->value || !atoi(t->value) ? 1 : 0;
163  }
164  // huffyuv does not support these with multiple frame threads currently
165  if (warn) {
166  av_log(avctx, AV_LOG_WARNING,
167  "Forcing thread count to 1 for huffyuv encoding with first pass or context 1\n");
168  avctx->thread_count = 1;
169  }
170  }
171 
172  if(!avctx->thread_count) {
173  avctx->thread_count = av_cpu_count();
174  avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
175  }
176 
177  if(avctx->thread_count <= 1)
178  return 0;
179 
180  if(avctx->thread_count > MAX_THREADS)
181  return AVERROR(EINVAL);
182 
185  if(!c)
186  return AVERROR(ENOMEM);
187 
188  c->parent_avctx = avctx;
189 
190  pthread_mutex_init(&c->task_fifo_mutex, NULL);
191  pthread_mutex_init(&c->finished_task_mutex, NULL);
192  pthread_mutex_init(&c->buffer_mutex, NULL);
193  pthread_cond_init(&c->task_fifo_cond, NULL);
194  pthread_cond_init(&c->finished_task_cond, NULL);
195  atomic_init(&c->exit, 0);
196 
197  c->max_tasks = avctx->thread_count + 2;
198  for (unsigned i = 0; i < c->max_tasks; i++) {
199  if (!(c->tasks[i].indata = av_frame_alloc()) ||
200  !(c->tasks[i].outdata = av_packet_alloc()))
201  goto fail;
202  }
203 
204  for(i=0; i<avctx->thread_count ; i++){
205  AVDictionary *tmp = NULL;
206  int ret;
207  void *tmpv;
208  thread_avctx = avcodec_alloc_context3(avctx->codec);
209  if(!thread_avctx)
210  goto fail;
211  tmpv = thread_avctx->priv_data;
212  *thread_avctx = *avctx;
213  thread_avctx->priv_data = tmpv;
214  thread_avctx->internal = NULL;
215  thread_avctx->hw_frames_ctx = NULL;
216  ret = av_opt_copy(thread_avctx, avctx);
217  if (ret < 0)
218  goto fail;
219  if (avctx->codec->priv_class) {
220  int ret = av_opt_copy(thread_avctx->priv_data, avctx->priv_data);
221  if (ret < 0)
222  goto fail;
223  } else if (avctx->codec->priv_data_size) {
224  memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size);
225  }
226  thread_avctx->thread_count = 1;
227  thread_avctx->active_thread_type &= ~FF_THREAD_FRAME;
228 
229  av_dict_copy(&tmp, options, 0);
230  av_dict_set(&tmp, "threads", "1", 0);
231  if(avcodec_open2(thread_avctx, avctx->codec, &tmp) < 0) {
232  av_dict_free(&tmp);
233  goto fail;
234  }
235  av_dict_free(&tmp);
236  av_assert0(!thread_avctx->internal->frame_thread_encoder);
237  thread_avctx->internal->frame_thread_encoder = c;
238  if(pthread_create(&c->worker[i], NULL, worker, thread_avctx)) {
239  goto fail;
240  }
241  }
242 
244 
245  return 0;
246 fail:
247  avcodec_close(thread_avctx);
248  av_freep(&thread_avctx);
249  avctx->thread_count = i;
250  av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n");
252  return -1;
253 }
254 
256  int i;
258 
259  pthread_mutex_lock(&c->task_fifo_mutex);
260  atomic_store(&c->exit, 1);
261  pthread_cond_broadcast(&c->task_fifo_cond);
262  pthread_mutex_unlock(&c->task_fifo_mutex);
263 
264  for (i=0; i<avctx->thread_count; i++) {
265  pthread_join(c->worker[i], NULL);
266  }
267 
268  for (unsigned i = 0; i < c->max_tasks; i++) {
269  av_frame_free(&c->tasks[i].indata);
270  av_packet_free(&c->tasks[i].outdata);
271  }
272 
273  pthread_mutex_destroy(&c->task_fifo_mutex);
274  pthread_mutex_destroy(&c->finished_task_mutex);
275  pthread_mutex_destroy(&c->buffer_mutex);
276  pthread_cond_destroy(&c->task_fifo_cond);
277  pthread_cond_destroy(&c->finished_task_cond);
279 }
280 
282  AVFrame *frame, int *got_packet_ptr)
283 {
285  Task *outtask;
286 
287  av_assert1(!*got_packet_ptr);
288 
289  if(frame){
290  av_frame_move_ref(c->tasks[c->task_index].indata, frame);
291 
292  pthread_mutex_lock(&c->task_fifo_mutex);
293  c->task_index = (c->task_index + 1) % c->max_tasks;
294  pthread_cond_signal(&c->task_fifo_cond);
295  pthread_mutex_unlock(&c->task_fifo_mutex);
296  }
297 
298  outtask = &c->tasks[c->finished_task_index];
299  pthread_mutex_lock(&c->finished_task_mutex);
300  /* The access to task_index in the following code is ok,
301  * because it is only ever changed by the main thread. */
302  if (c->task_index == c->finished_task_index ||
303  (frame && !outtask->finished &&
304  (c->task_index - c->finished_task_index + c->max_tasks) % c->max_tasks <= avctx->thread_count)) {
305  pthread_mutex_unlock(&c->finished_task_mutex);
306  return 0;
307  }
308  while (!outtask->finished) {
309  pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
310  }
311  pthread_mutex_unlock(&c->finished_task_mutex);
312  /* We now own outtask completely: No worker thread touches it any more,
313  * because there is no outstanding task with this index. */
314  outtask->finished = 0;
315  av_packet_move_ref(pkt, outtask->outdata);
316  if(pkt->data)
317  *got_packet_ptr = 1;
318  c->finished_task_index = (c->finished_task_index + 1) % c->max_tasks;
319 
320  return outtask->return_code;
321 }
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:53
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Libavcodec external API header.
#define FF_THREAD_FRAME
Decode more than one frame at once.
Definition: avcodec.h:1788
#define fail()
Definition: checkasm.h:133
#define FFMIN(a, b)
Definition: common.h:105
#define NULL
Definition: coverity.c:32
int av_cpu_count(void)
Definition: cpu.c:275
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
const OptionDef options[]
#define pthread_mutex_lock(a)
Definition: ffprobe.c:63
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:67
int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options)
Initialize frame thread encoder.
int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, AVFrame *frame, int *got_packet_ptr)
#define BUFFER_SIZE
void ff_frame_thread_encoder_free(AVCodecContext *avctx)
#define MAX_THREADS
static void *attribute_align_arg worker(void *v)
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition: opt.c:1789
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
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition: avcodec.h:275
#define AV_CODEC_FLAG_PASS1
Use internal 2pass ratecontrol in first pass mode.
Definition: avcodec.h:296
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: codec.h:108
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:173
av_cold int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
Definition: avcodec.c:570
@ AV_CODEC_ID_FFVHUFF
Definition: codec_id.h:116
@ AV_CODEC_ID_HUFFYUV
Definition: codec_id.h:74
@ AV_CODEC_ID_MJPEG
Definition: codec_id.h:56
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
int av_packet_make_refcounted(AVPacket *pkt)
Ensure the data described by a given packet is reference counted.
Definition: avpacket.c:696
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:690
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:64
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
Definition: dict.h:69
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
#define AVERROR(e)
Definition: error.h:43
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:582
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:190
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
misc image utilities
int i
Definition: input.c:407
common internal API header
#define attribute_align_arg
Definition: internal.h:61
AVOptions.
static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
Definition: os2threads.h:162
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:152
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:94
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
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_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
main external API structure.
Definition: avcodec.h:536
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition: avcodec.h:2222
int active_thread_type
Which multithreading methods are in use by the codec.
Definition: avcodec.h:1796
const struct AVCodec * codec
Definition: avcodec.h:545
int thread_type
Which multithreading methods to use.
Definition: avcodec.h:1787
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1777
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:616
enum AVCodecID codec_id
Definition: avcodec.h:546
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:571
void * priv_data
Definition: avcodec.h:563
void * frame_thread_encoder
Definition: internal.h:168
const AVClass * priv_class
AVClass for the private context.
Definition: codec.h:223
int priv_data_size
Definition: codec.h:245
int(* encode2)(struct AVCodecContext *avctx, struct AVPacket *avpkt, const struct AVFrame *frame, int *got_packet_ptr)
Encode data to an AVPacket.
Definition: codec.h:289
int capabilities
Codec capabilities.
Definition: codec.h:216
char * value
Definition: dict.h:83
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:411
This structure stores compressed data.
Definition: packet.h:346
int size
Definition: packet.h:370
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:362
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:368
uint8_t * data
Definition: packet.h:369
AVPacket * outdata
AVFrame * indata
pthread_mutex_t task_fifo_mutex
pthread_mutex_t finished_task_mutex
pthread_mutex_t buffer_mutex
unsigned finished_task_index
pthread_cond_t finished_task_cond
pthread_cond_t task_fifo_cond
AVCodecContext * parent_avctx
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[11]
Definition: aes_ctr.c:27
AVPacket * pkt
Definition: movenc.c:59
static double c[64]