OpenShot Library | libopenshot  0.2.6
FFmpegWriter.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for FFmpegWriter class
4  * @author Jonathan Thomas <jonathan@openshot.org>, Fabrice Bellard
5  *
6  * @ref License
7  */
8 
9 /* LICENSE
10  *
11  * Copyright (c) 2008-2019 OpenShot Studios, LLC, Fabrice Bellard
12  * (http://www.openshotstudios.com). This file is part of
13  * OpenShot Library (http://www.openshot.org), an open-source project
14  * dedicated to delivering high quality video editing and animation solutions
15  * to the world.
16  *
17  * This file is originally based on the Libavformat API example, and then modified
18  * by the libopenshot project.
19  *
20  * OpenShot Library (libopenshot) is free software: you can redistribute it
21  * and/or modify it under the terms of the GNU Lesser General Public License
22  * as published by the Free Software Foundation, either version 3 of the
23  * License, or (at your option) any later version.
24  *
25  * OpenShot Library (libopenshot) is distributed in the hope that it will be
26  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public License
31  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
32  */
33 
34 #include "FFmpegWriter.h"
35 #include "Exceptions.h"
36 
37 #include <iostream>
38 
39 using namespace openshot;
40 
41 // Multiplexer parameters temporary storage
42 AVDictionary *mux_dict = NULL;
43 
44 #if USE_HW_ACCEL
45 int hw_en_on = 1; // Is set in UI
46 int hw_en_supported = 0; // Is set by FFmpegWriter
47 AVPixelFormat hw_en_av_pix_fmt = AV_PIX_FMT_NONE;
48 AVHWDeviceType hw_en_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
49 static AVBufferRef *hw_device_ctx = NULL;
50 AVFrame *hw_frame = NULL;
51 
52 static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
53 {
54  AVBufferRef *hw_frames_ref;
55  AVHWFramesContext *frames_ctx = NULL;
56  int err = 0;
57 
58  if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
59  std::clog << "Failed to create HW frame context.\n";
60  return -1;
61  }
62  frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
63  frames_ctx->format = hw_en_av_pix_fmt;
64  frames_ctx->sw_format = AV_PIX_FMT_NV12;
65  frames_ctx->width = width;
66  frames_ctx->height = height;
67  frames_ctx->initial_pool_size = 20;
68  if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
69  std::clog << "Failed to initialize HW frame context. " <<
70  "Error code: " << av_err2string(err) << "\n";
71  av_buffer_unref(&hw_frames_ref);
72  return err;
73  }
74  ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
75  if (!ctx->hw_frames_ctx)
76  err = AVERROR(ENOMEM);
77 
78  av_buffer_unref(&hw_frames_ref);
79  return err;
80 }
81 #endif // USE_HW_ACCEL
82 
83 FFmpegWriter::FFmpegWriter(const std::string& path) :
84  path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
85  audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
86  initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32),
87  rescaler_position(0), video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
88  original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
89  write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
90 
91  // Disable audio & video (so they can be independently enabled)
92  info.has_audio = false;
93  info.has_video = false;
94 
95  // Initialize FFMpeg, and register all formats and codecs
97 
98  // auto detect format
99  auto_detect_format();
100 }
101 
102 // Open the writer
104  if (!is_open) {
105  // Open the writer
106  is_open = true;
107 
108  // Prepare streams (if needed)
109  if (!prepare_streams)
110  PrepareStreams();
111 
112  // Now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers
113  if (info.has_video && video_st)
114  open_video(oc, video_st);
115  if (info.has_audio && audio_st)
116  open_audio(oc, audio_st);
117 
118  // Write header (if needed)
119  if (!write_header)
120  WriteHeader();
121  }
122 }
123 
124 // auto detect format (from path)
125 void FFmpegWriter::auto_detect_format() {
126  // Auto detect the output format from the name. default is mpeg.
127  fmt = av_guess_format(NULL, path.c_str(), NULL);
128  if (!fmt)
129  throw InvalidFormat("Could not deduce output format from file extension.", path);
130 
131  // Allocate the output media context
132  AV_OUTPUT_CONTEXT(&oc, path.c_str());
133  if (!oc)
134  throw OutOfMemory("Could not allocate memory for AVFormatContext.", path);
135 
136  // Set the AVOutputFormat for the current AVFormatContext
137  oc->oformat = fmt;
138 
139  // Update codec names
140  if (fmt->video_codec != AV_CODEC_ID_NONE && info.has_video)
141  // Update video codec name
142  info.vcodec = avcodec_find_encoder(fmt->video_codec)->name;
143 
144  if (fmt->audio_codec != AV_CODEC_ID_NONE && info.has_audio)
145  // Update audio codec name
146  info.acodec = avcodec_find_encoder(fmt->audio_codec)->name;
147 }
148 
149 // initialize streams
150 void FFmpegWriter::initialize_streams() {
151  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::initialize_streams", "fmt->video_codec", fmt->video_codec, "fmt->audio_codec", fmt->audio_codec, "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
152 
153  // Add the audio and video streams using the default format codecs and initialize the codecs
154  video_st = NULL;
155  audio_st = NULL;
156  if (fmt->video_codec != AV_CODEC_ID_NONE && info.has_video)
157  // Add video stream
158  video_st = add_video_stream();
159 
160  if (fmt->audio_codec != AV_CODEC_ID_NONE && info.has_audio)
161  // Add audio stream
162  audio_st = add_audio_stream();
163 }
164 
165 // Set video export options
166 void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction fps, int width, int height, Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate) {
167  // Set the video options
168  if (codec.length() > 0) {
169  AVCodec *new_codec;
170  // Check if the codec selected is a hardware accelerated codec
171 #if USE_HW_ACCEL
172 #if defined(__linux__)
173  if (strstr(codec.c_str(), "_vaapi") != NULL) {
174  new_codec = avcodec_find_encoder_by_name(codec.c_str());
175  hw_en_on = 1;
176  hw_en_supported = 1;
177  hw_en_av_pix_fmt = AV_PIX_FMT_VAAPI;
178  hw_en_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
179  } else if (strstr(codec.c_str(), "_nvenc") != NULL) {
180  new_codec = avcodec_find_encoder_by_name(codec.c_str());
181  hw_en_on = 1;
182  hw_en_supported = 1;
183  hw_en_av_pix_fmt = AV_PIX_FMT_CUDA;
184  hw_en_av_device_type = AV_HWDEVICE_TYPE_CUDA;
185  } else {
186  new_codec = avcodec_find_encoder_by_name(codec.c_str());
187  hw_en_on = 0;
188  hw_en_supported = 0;
189  }
190 #elif defined(_WIN32)
191  if (strstr(codec.c_str(), "_dxva2") != NULL) {
192  new_codec = avcodec_find_encoder_by_name(codec.c_str());
193  hw_en_on = 1;
194  hw_en_supported = 1;
195  hw_en_av_pix_fmt = AV_PIX_FMT_DXVA2_VLD;
196  hw_en_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
197  } else if (strstr(codec.c_str(), "_nvenc") != NULL) {
198  new_codec = avcodec_find_encoder_by_name(codec.c_str());
199  hw_en_on = 1;
200  hw_en_supported = 1;
201  hw_en_av_pix_fmt = AV_PIX_FMT_CUDA;
202  hw_en_av_device_type = AV_HWDEVICE_TYPE_CUDA;
203  } else {
204  new_codec = avcodec_find_encoder_by_name(codec.c_str());
205  hw_en_on = 0;
206  hw_en_supported = 0;
207  }
208 #elif defined(__APPLE__)
209  if (strstr(codec.c_str(), "_videotoolbox") != NULL) {
210  new_codec = avcodec_find_encoder_by_name(codec.c_str());
211  hw_en_on = 1;
212  hw_en_supported = 1;
213  hw_en_av_pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX;
214  hw_en_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
215  } else {
216  new_codec = avcodec_find_encoder_by_name(codec.c_str());
217  hw_en_on = 0;
218  hw_en_supported = 0;
219  }
220 #else // unknown OS
221  new_codec = avcodec_find_encoder_by_name(codec.c_str());
222 #endif //__linux__/_WIN32/__APPLE__
223 #else // USE_HW_ACCEL
224  new_codec = avcodec_find_encoder_by_name(codec.c_str());
225 #endif // USE_HW_ACCEL
226  if (new_codec == NULL)
227  throw InvalidCodec("A valid video codec could not be found for this file.", path);
228  else {
229  // Set video codec
230  info.vcodec = new_codec->name;
231 
232  // Update video codec in fmt
233  fmt->video_codec = new_codec->id;
234  }
235  }
236  if (fps.num > 0) {
237  // Set frames per second (if provided)
238  info.fps.num = fps.num;
239  info.fps.den = fps.den;
240 
241  // Set the timebase (inverse of fps)
244  }
245  if (width >= 1)
246  info.width = width;
247  if (height >= 1)
248  info.height = height;
249  if (pixel_ratio.num > 0) {
250  info.pixel_ratio.num = pixel_ratio.num;
251  info.pixel_ratio.den = pixel_ratio.den;
252  }
253  if (bit_rate >= 1000) // bit_rate is the bitrate in b/s
254  info.video_bit_rate = bit_rate;
255  if ((bit_rate >= 0) && (bit_rate < 256)) // bit_rate is the bitrate in crf
256  info.video_bit_rate = bit_rate;
257 
258  info.interlaced_frame = interlaced;
259  info.top_field_first = top_field_first;
260 
261  // Calculate the DAR (display aspect ratio)
263 
264  // Reduce size fraction
265  size.Reduce();
266 
267  // Set the ratio based on the reduced fraction
268  info.display_ratio.num = size.num;
269  info.display_ratio.den = size.den;
270 
271  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetVideoOptions (" + codec + ")", "width", width, "height", height, "size.num", size.num, "size.den", size.den, "fps.num", fps.num, "fps.den", fps.den);
272 
273  // Enable / Disable video
274  info.has_video = has_video;
275 }
276 
277 // Set video export options (overloaded function)
278 void FFmpegWriter::SetVideoOptions(std::string codec, int width, int height, Fraction fps, int bit_rate) {
279  // Call full signature with some default parameters
281  true, codec, fps, width, height,
282  openshot::Fraction(1, 1), false, true, bit_rate
283  );
284 }
285 
286 
287 // Set audio export options
288 void FFmpegWriter::SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate) {
289  // Set audio options
290  if (codec.length() > 0) {
291  AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
292  if (new_codec == NULL)
293  throw InvalidCodec("A valid audio codec could not be found for this file.", path);
294  else {
295  // Set audio codec
296  info.acodec = new_codec->name;
297 
298  // Update audio codec in fmt
299  fmt->audio_codec = new_codec->id;
300  }
301  }
302  if (sample_rate > 7999)
303  info.sample_rate = sample_rate;
304  if (channels > 0)
305  info.channels = channels;
306  if (bit_rate > 999)
307  info.audio_bit_rate = bit_rate;
308  info.channel_layout = channel_layout;
309 
310  // init resample options (if zero)
311  if (original_sample_rate == 0)
312  original_sample_rate = info.sample_rate;
313  if (original_channels == 0)
314  original_channels = info.channels;
315 
317  "FFmpegWriter::SetAudioOptions (" + codec + ")",
318  "sample_rate", sample_rate,
319  "channels", channels,
320  "bit_rate", bit_rate);
321 
322  // Enable / Disable audio
323  info.has_audio = has_audio;
324 }
325 
326 
327 // Set audio export options (overloaded function)
328 void FFmpegWriter::SetAudioOptions(std::string codec, int sample_rate, int bit_rate) {
329  // Call full signature with some default parameters
331  true, codec, sample_rate, 2,
332  openshot::LAYOUT_STEREO, bit_rate
333  );
334 }
335 
336 
337 // Set custom options (some codecs accept additional params)
338 void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string value) {
339  // Declare codec context
340  AVCodecContext *c = NULL;
341  AVStream *st = NULL;
342  std::stringstream convert(value);
343 
344  if (info.has_video && stream == VIDEO_STREAM && video_st) {
345  st = video_st;
346  // Get codec context
347  c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec_ctx);
348  // Was a codec / stream found?
349  if (c) {
350  if (info.interlaced_frame) {
351  c->field_order = info.top_field_first ? AV_FIELD_TT : AV_FIELD_BB;
352  // We only use these two version and ignore AV_FIELD_TB and AV_FIELD_BT
353  // Otherwise we would need to change the whole export window
354  }
355  }
356  } else if (info.has_audio && stream == AUDIO_STREAM && audio_st) {
357  st = audio_st;
358  // Get codec context
359  c = AV_GET_CODEC_PAR_CONTEXT(st, audio_codec_ctx);
360  } else
361  throw NoStreamsFound("The stream was not found. Be sure to call PrepareStreams() first.", path);
362 
363  // Init AVOption
364  const AVOption *option = NULL;
365 
366  // Was a codec / stream found?
367  if (c)
368  // Find AVOption (if it exists)
369  option = AV_OPTION_FIND(c->priv_data, name.c_str());
370 
371  // Was option found?
372  if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
373  name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" ||
374  name == "rc_buffer_size" || name == "crf" || name == "cqp" || name == "qp")) {
375  // Check for specific named options
376  if (name == "g")
377  // Set gop_size
378  convert >> c->gop_size;
379 
380  else if (name == "qmin")
381  // Minimum quantizer
382  convert >> c->qmin;
383 
384  else if (name == "qmax")
385  // Maximum quantizer
386  convert >> c->qmax;
387 
388  else if (name == "max_b_frames")
389  // Maximum number of B-frames between non-B-frames
390  convert >> c->max_b_frames;
391 
392  else if (name == "mb_decision")
393  // Macroblock decision mode
394  convert >> c->mb_decision;
395 
396  else if (name == "level")
397  // Set codec level
398  convert >> c->level;
399 
400  else if (name == "profile")
401  // Set codec profile
402  convert >> c->profile;
403 
404  else if (name == "slices")
405  // Indicates number of picture subdivisions
406  convert >> c->slices;
407 
408  else if (name == "rc_min_rate")
409  // Minimum bitrate
410  convert >> c->rc_min_rate;
411 
412  else if (name == "rc_max_rate")
413  // Maximum bitrate
414  convert >> c->rc_max_rate;
415 
416  else if (name == "rc_buffer_size")
417  // Buffer size
418  convert >> c->rc_buffer_size;
419 
420  else if (name == "cqp") {
421  // encode quality and special settings like lossless
422  // This might be better in an extra methods as more options
423  // and way to set quality are possible
424 #if USE_HW_ACCEL
425  if (hw_en_on) {
426  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63
427  } else
428 #endif // USE_HW_ACCEL
429  {
430  switch (c->codec_id) {
431 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
432  // FFmpeg 4.0+
433  case AV_CODEC_ID_AV1 :
434  c->bit_rate = 0;
435  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63
436  break;
437 #endif
438  case AV_CODEC_ID_VP8 :
439  c->bit_rate = 10000000;
440  av_opt_set_int(c->priv_data, "qp", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63
441  break;
442  case AV_CODEC_ID_VP9 :
443  c->bit_rate = 0; // Must be zero!
444  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63
445  if (std::stoi(value) == 0) {
446  av_opt_set(c->priv_data, "preset", "veryslow", 0);
447  av_opt_set_int(c->priv_data, "lossless", 1, 0);
448  }
449  break;
450  case AV_CODEC_ID_H264 :
451  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51
452  if (std::stoi(value) == 0) {
453  av_opt_set(c->priv_data, "preset", "veryslow", 0);
454  c->pix_fmt = PIX_FMT_YUV444P; // no chroma subsampling
455  }
456  break;
457  case AV_CODEC_ID_HEVC :
458  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51
459  if (std::stoi(value) == 0) {
460  av_opt_set(c->priv_data, "preset", "veryslow", 0);
461  av_opt_set_int(c->priv_data, "lossless", 1, 0);
462  }
463  break;
464  default:
465  // For all other codecs assume a range of 0-63
466  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63
467  c->bit_rate = 0;
468  }
469  }
470  } else if (name == "crf") {
471  // encode quality and special settings like lossless
472  // This might be better in an extra methods as more options
473  // and way to set quality are possible
474 #if USE_HW_ACCEL
475  if (hw_en_on) {
476  double mbs = 15000000.0;
477  if (info.video_bit_rate > 0) {
478  if (info.video_bit_rate > 42) {
479  mbs = 380000.0;
480  }
481  else {
482  mbs *= std::pow(0.912,info.video_bit_rate);
483  }
484  }
485  c->bit_rate = (int)(mbs);
486  } else
487 #endif // USE_HW_ACCEL
488  {
489  switch (c->codec_id) {
490 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
491  // FFmpeg 4.0+
492  case AV_CODEC_ID_AV1 :
493  c->bit_rate = 0;
494  // AV1 only supports "crf" quality values
495  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
496  break;
497 #endif
498  case AV_CODEC_ID_VP8 :
499  c->bit_rate = 10000000;
500  av_opt_set_int(c->priv_data, "crf", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63
501  break;
502  case AV_CODEC_ID_VP9 :
503  c->bit_rate = 0; // Must be zero!
504  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 63), 0); // 0-63
505  if (std::stoi(value) == 0) {
506  av_opt_set(c->priv_data, "preset", "veryslow", 0);
507  av_opt_set_int(c->priv_data, "lossless", 1, 0);
508  }
509  break;
510  case AV_CODEC_ID_H264 :
511  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51
512  if (std::stoi(value) == 0) {
513  av_opt_set(c->priv_data, "preset", "veryslow", 0);
514  c->pix_fmt = PIX_FMT_YUV444P; // no chroma subsampling
515  }
516  break;
517  case AV_CODEC_ID_HEVC :
518  if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) {
519  av_opt_set_int(c->priv_data, "preset", 7, 0);
520  av_opt_set_int(c->priv_data, "forced-idr",1,0);
521  av_opt_set_int(c->priv_data, "qp",std::min(std::stoi(value), 51),0);
522  }
523  else {
524  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51
525  }
526  if (std::stoi(value) == 0) {
527  av_opt_set(c->priv_data, "preset", "veryslow", 0);
528  av_opt_set_int(c->priv_data, "lossless", 1, 0);
529  }
530  break;
531  default:
532  // If this codec doesn't support crf calculate a bitrate
533  // TODO: find better formula
534  double mbs = 15000000.0;
535  if (info.video_bit_rate > 0) {
536  if (info.video_bit_rate > 42) {
537  mbs = 380000.0;
538  } else {
539  mbs *= std::pow(0.912, info.video_bit_rate);
540  }
541  }
542  c->bit_rate = (int) (mbs);
543  }
544  }
545  } else if (name == "qp") {
546  // encode quality and special settings like lossless
547  // This might be better in an extra methods as more options
548  // and way to set quality are possible
549 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
550  // FFmpeg 4.0+
551  switch (c->codec_id) {
552  case AV_CODEC_ID_AV1 :
553  c->bit_rate = 0;
554  if (strstr(info.vcodec.c_str(), "svtav1") != NULL) {
555  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0);
556  }
557  else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) {
558  // Set number of tiles to a fixed value
559  // TODO Let user choose number of tiles
560  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0);
561  }
562  else if (strstr(info.vcodec.c_str(), "aom") != NULL) {
563  // Set number of tiles to a fixed value
564  // TODO Let user choose number of tiles
565  // libaom doesn't have qp only crf
566  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
567  }
568  else {
569  av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
570  }
571  case AV_CODEC_ID_HEVC :
572  c->bit_rate = 0;
573  if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) {
574  av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),51), 0);
575  av_opt_set_int(c->priv_data, "preset", 7, 0);
576  av_opt_set_int(c->priv_data, "forced-idr",1,0);
577  }
578  break;
579  }
580 #endif // FFmpeg 4.0+
581  } else {
582  // Set AVOption
583  AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
584  }
585 
586  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::SetOption (" + (std::string)name + ")", "stream == VIDEO_STREAM", stream == VIDEO_STREAM);
587 
588  // Muxing dictionary is not part of the codec context.
589  // Just reusing SetOption function to set popular multiplexing presets.
590  } else if (name == "muxing_preset") {
591  if (value == "mp4_faststart") {
592  // 'moov' box to the beginning; only for MOV, MP4
593  av_dict_set(&mux_dict, "movflags", "faststart", 0);
594  } else if (value == "mp4_fragmented") {
595  // write selfcontained fragmented file, minimum length of the fragment 8 sec; only for MOV, MP4
596  av_dict_set(&mux_dict, "movflags", "frag_keyframe", 0);
597  av_dict_set(&mux_dict, "min_frag_duration", "8000000", 0);
598  }
599  } else {
600  throw InvalidOptions("The option is not valid for this codec.", path);
601  }
602 
603 }
604 
605 /// Determine if codec name is valid
606 bool FFmpegWriter::IsValidCodec(std::string codec_name) {
607  // Initialize FFMpeg, and register all formats and codecs
609 
610  // Find the codec (if any)
611  if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
612  return false;
613  else
614  return true;
615 }
616 
617 // Prepare & initialize streams and open codecs
619  if (!info.has_audio && !info.has_video)
620  throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
621 
622  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::PrepareStreams [" + path + "]", "info.has_audio", info.has_audio, "info.has_video", info.has_video);
623 
624  // Initialize the streams (i.e. add the streams)
625  initialize_streams();
626 
627  // Mark as 'prepared'
628  prepare_streams = true;
629 }
630 
631 // Write the file header (after the options are set)
633  if (!info.has_audio && !info.has_video)
634  throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
635 
636  // Open the output file, if needed
637  if (!(fmt->flags & AVFMT_NOFILE)) {
638  if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
639  throw InvalidFile("Could not open or write file.", path);
640  }
641 
642  // Force the output filename (which doesn't always happen for some reason)
643  AV_SET_FILENAME(oc, path.c_str());
644 
645  // Add general metadata (if any)
646  for (std::map<std::string, std::string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
647  av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
648  }
649 
650  // Set multiplexing parameters
651  AVDictionary *dict = NULL;
652 
653  bool is_mp4 = strcmp(oc->oformat->name, "mp4");
654  bool is_mov = strcmp(oc->oformat->name, "mov");
655  // Set dictionary preset only for MP4 and MOV files
656  if (is_mp4 || is_mov)
657  av_dict_copy(&dict, mux_dict, 0);
658 
659  // Write the stream header
660  if (avformat_write_header(oc, &dict) != 0) {
661  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteHeader (avformat_write_header)");
662  throw InvalidFile("Could not write header to file.", path);
663  };
664 
665  // Free multiplexing dictionaries sets
666  if (dict) av_dict_free(&dict);
667  if (mux_dict) av_dict_free(&mux_dict);
668 
669  // Mark as 'written'
670  write_header = true;
671 
672  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteHeader");
673 }
674 
675 // Add a frame to the queue waiting to be encoded.
676 void FFmpegWriter::WriteFrame(std::shared_ptr<Frame> frame) {
677  // Check for open reader (or throw exception)
678  if (!is_open)
679  throw WriterClosed("The FFmpegWriter is closed. Call Open() before calling this method.", path);
680 
681  // Add frame pointer to "queue", waiting to be processed the next
682  // time the WriteFrames() method is called.
683  if (info.has_video && video_st)
684  spooled_video_frames.push_back(frame);
685 
686  if (info.has_audio && audio_st)
687  spooled_audio_frames.push_back(frame);
688 
689  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteFrame", "frame->number", frame->number, "spooled_video_frames.size()", spooled_video_frames.size(), "spooled_audio_frames.size()", spooled_audio_frames.size(), "cache_size", cache_size, "is_writing", is_writing);
690 
691  // Write the frames once it reaches the correct cache size
692  if ((int)spooled_video_frames.size() == cache_size || (int)spooled_audio_frames.size() == cache_size) {
693  // Write frames to video file
694  write_queued_frames();
695  }
696 
697  // Keep track of the last frame added
698  last_frame = frame;
699 }
700 
701 // Write all frames in the queue to the video file.
702 void FFmpegWriter::write_queued_frames() {
703  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_queued_frames", "spooled_video_frames.size()", spooled_video_frames.size(), "spooled_audio_frames.size()", spooled_audio_frames.size());
704 
705  // Flip writing flag
706  is_writing = true;
707 
708  // Transfer spool to queue
709  queued_video_frames = spooled_video_frames;
710  queued_audio_frames = spooled_audio_frames;
711 
712  // Empty spool
713  spooled_video_frames.clear();
714  spooled_audio_frames.clear();
715 
716  // Create blank exception
717  bool has_error_encoding_video = false;
718 
719  // Process all audio frames (in a separate thread)
720  if (info.has_audio && audio_st && !queued_audio_frames.empty())
721  write_audio_packets(false);
722 
723  // Loop through each queued image frame
724  while (!queued_video_frames.empty()) {
725  // Get front frame (from the queue)
726  std::shared_ptr<Frame> frame = queued_video_frames.front();
727 
728  // Add to processed queue
729  processed_frames.push_back(frame);
730 
731  // Encode and add the frame to the output file
732  if (info.has_video && video_st)
733  process_video_packet(frame);
734 
735  // Remove front item
736  queued_video_frames.pop_front();
737 
738  } // end while
739 
740 
741  // Loop back through the frames (in order), and write them to the video file
742  while (!processed_frames.empty()) {
743  // Get front frame (from the queue)
744  std::shared_ptr<Frame> frame = processed_frames.front();
745 
746  if (info.has_video && video_st) {
747  // Add to deallocate queue (so we can remove the AVFrames when we are done)
748  deallocate_frames.push_back(frame);
749 
750  // Does this frame's AVFrame still exist
751  if (av_frames.count(frame)) {
752  // Get AVFrame
753  AVFrame *frame_final = av_frames[frame];
754 
755  // Write frame to video file
756  bool success = write_video_packet(frame, frame_final);
757  if (!success)
758  has_error_encoding_video = true;
759  }
760  }
761 
762  // Remove front item
763  processed_frames.pop_front();
764  }
765 
766  // Loop through, and deallocate AVFrames
767  while (!deallocate_frames.empty()) {
768  // Get front frame (from the queue)
769  std::shared_ptr<Frame> frame = deallocate_frames.front();
770 
771  // Does this frame's AVFrame still exist
772  if (av_frames.count(frame)) {
773  // Get AVFrame
774  AVFrame *av_frame = av_frames[frame];
775 
776  // Deallocate AVPicture and AVFrame
777  av_freep(&(av_frame->data[0]));
778  AV_FREE_FRAME(&av_frame);
779  av_frames.erase(frame);
780  }
781 
782  // Remove front item
783  deallocate_frames.pop_front();
784  }
785 
786  // Done writing
787  is_writing = false;
788 
789  // Raise exception from main thread
790  if (has_error_encoding_video)
791  throw ErrorEncodingVideo("Error while writing raw video frame", -1);
792 }
793 
794 // Write a block of frames from a reader
795 void FFmpegWriter::WriteFrame(ReaderBase *reader, int64_t start, int64_t length) {
796  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteFrame (from Reader)", "start", start, "length", length);
797 
798  // Loop through each frame (and encoded it)
799  for (int64_t number = start; number <= length; number++) {
800  // Get the frame
801  std::shared_ptr<Frame> f = reader->GetFrame(number);
802 
803  // Encode frame
804  WriteFrame(f);
805  }
806 }
807 
808 // Write the file trailer (after all frames are written)
810  // Write any remaining queued frames to video file
811  write_queued_frames();
812 
813  // Process final audio frame (if any)
814  if (info.has_audio && audio_st)
815  write_audio_packets(true);
816 
817  // Flush encoders (who sometimes hold on to frames)
818  flush_encoders();
819 
820  /* write the trailer, if any. The trailer must be written
821  * before you close the CodecContexts open when you wrote the
822  * header; otherwise write_trailer may try to use memory that
823  * was freed on av_codec_close() */
824  av_write_trailer(oc);
825 
826  // Mark as 'written'
827  write_trailer = true;
828 
829  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::WriteTrailer");
830 }
831 
832 // Flush encoders
833 void FFmpegWriter::flush_encoders() {
834  if (info.has_audio && audio_codec_ctx && AV_GET_CODEC_TYPE(audio_st) == AVMEDIA_TYPE_AUDIO && AV_GET_CODEC_ATTRIBUTES(audio_st, audio_codec_ctx)->frame_size <= 1)
835  return;
836 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
837  // FFmpeg < 4.0
838  if (info.has_video && video_codec_ctx && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO)
839  return;
840 #else
841  if (info.has_video && video_codec_ctx && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO)
842  return;
843 #endif
844 
845  // FLUSH VIDEO ENCODER
846  if (info.has_video)
847  for (;;) {
848 
849  // Increment PTS (in frames and scaled to the codec's timebase)
850  video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
851 
852  AVPacket pkt;
853  av_init_packet(&pkt);
854  pkt.data = NULL;
855  pkt.size = 0;
856 
857  /* encode the image */
858  int got_packet = 0;
859  int error_code = 0;
860 
861 #if IS_FFMPEG_3_2
862  // Encode video packet (latest version of FFmpeg)
863  error_code = avcodec_send_frame(video_codec_ctx, NULL);
864  got_packet = 0;
865  while (error_code >= 0) {
866  error_code = avcodec_receive_packet(video_codec_ctx, &pkt);
867  if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
868  got_packet = 0;
869  // Write packet
870  avcodec_flush_buffers(video_codec_ctx);
871  break;
872  }
873  av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
874  pkt.stream_index = video_st->index;
875  error_code = av_interleaved_write_frame(oc, &pkt);
876  }
877 #else // IS_FFMPEG_3_2
878 
879  // Encode video packet (older than FFmpeg 3.2)
880  error_code = avcodec_encode_video2(video_codec_ctx, &pkt, NULL, &got_packet);
881 
882 #endif // IS_FFMPEG_3_2
883 
884  if (error_code < 0) {
885  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
886  }
887  if (!got_packet) {
888  break;
889  }
890 
891  // set the timestamp
892  av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
893  pkt.stream_index = video_st->index;
894 
895  // Write packet
896  error_code = av_interleaved_write_frame(oc, &pkt);
897  if (error_code < 0) {
898  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
899  }
900  }
901 
902  // FLUSH AUDIO ENCODER
903  if (info.has_audio) {
904  for (;;) {
905  AVPacket pkt;
906  av_init_packet(&pkt);
907  pkt.data = NULL;
908  pkt.size = 0;
909  pkt.pts = pkt.dts = audio_timestamp;
910 
911  /* encode the image */
912  int error_code = 0;
913  int got_packet = 0;
914 #if IS_FFMPEG_3_2
915  error_code = avcodec_send_frame(audio_codec_ctx, NULL);
916 #else
917  error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, NULL, &got_packet);
918 #endif
919  if (error_code < 0) {
921  "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) + "]",
922  "error_code", error_code);
923  }
924  if (!got_packet) {
925  break;
926  }
927 
928  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
929  // but it fixes lots of PTS related issues when I do this.
930  pkt.pts = pkt.dts = audio_timestamp;
931 
932  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
933  av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
934 
935  // set stream
936  pkt.stream_index = audio_st->index;
937  pkt.flags |= AV_PKT_FLAG_KEY;
938 
939  // Write packet
940  error_code = av_interleaved_write_frame(oc, &pkt);
941  if (error_code < 0) {
943  "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) + "]",
944  "error_code", error_code);
945  }
946 
947  // Increment PTS by duration of packet
948  audio_timestamp += pkt.duration;
949 
950  // deallocate memory for packet
951  AV_FREE_PACKET(&pkt);
952  }
953  }
954 
955 }
956 
957 // Close the video codec
958 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
959 {
960 #if USE_HW_ACCEL
961  if (hw_en_on && hw_en_supported) {
962  if (hw_device_ctx) {
963  av_buffer_unref(&hw_device_ctx);
964  hw_device_ctx = NULL;
965  }
966  }
967 #endif // USE_HW_ACCEL
968 }
969 
970 // Close the audio codec
971 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
972 {
973  // Clear buffers
974  delete[] samples;
975  delete[] audio_outbuf;
976  delete[] audio_encoder_buffer;
977  samples = NULL;
978  audio_outbuf = NULL;
979  audio_encoder_buffer = NULL;
980 
981  // Deallocate resample buffer
982  if (avr) {
983  SWR_CLOSE(avr);
984  SWR_FREE(&avr);
985  avr = NULL;
986  }
987 
988  if (avr_planar) {
989  SWR_CLOSE(avr_planar);
990  SWR_FREE(&avr_planar);
991  avr_planar = NULL;
992  }
993 }
994 
995 // Close the writer
997  // Write trailer (if needed)
998  if (!write_trailer)
999  WriteTrailer();
1000 
1001  // Close each codec
1002  if (video_st)
1003  close_video(oc, video_st);
1004  if (audio_st)
1005  close_audio(oc, audio_st);
1006 
1007  // Deallocate image scalers
1008  if (image_rescalers.size() > 0)
1009  RemoveScalers();
1010 
1011  if (!(fmt->flags & AVFMT_NOFILE)) {
1012  /* close the output file */
1013  avio_close(oc->pb);
1014  }
1015 
1016  // Reset frame counters
1017  video_timestamp = 0;
1018  audio_timestamp = 0;
1019 
1020  // Free the context which frees the streams too
1021  avformat_free_context(oc);
1022  oc = NULL;
1023 
1024  // Close writer
1025  is_open = false;
1026  prepare_streams = false;
1027  write_header = false;
1028  write_trailer = false;
1029 
1030  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::Close");
1031 }
1032 
1033 // Add an AVFrame to the cache
1034 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1035  // Add AVFrame to map (if it does not already exist)
1036  if (!av_frames.count(frame)) {
1037  // Add av_frame
1038  av_frames[frame] = av_frame;
1039  } else {
1040  // Do not add, and deallocate this AVFrame
1041  AV_FREE_FRAME(&av_frame);
1042  }
1043 }
1044 
1045 // Add an audio output stream
1046 AVStream *FFmpegWriter::add_audio_stream() {
1047  AVCodecContext *c;
1048  AVStream *st;
1049 
1050  // Find the audio codec
1051  AVCodec *codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1052  if (codec == NULL)
1053  throw InvalidCodec("A valid audio codec could not be found for this file.", path);
1054 
1055  // Free any previous memory allocations
1056  if (audio_codec_ctx != NULL) {
1057  AV_FREE_CONTEXT(audio_codec_ctx);
1058  }
1059 
1060  // Create a new audio stream
1061  AV_FORMAT_NEW_STREAM(oc, audio_codec_ctx, codec, st)
1062 
1063  c->codec_id = codec->id;
1064  c->codec_type = AVMEDIA_TYPE_AUDIO;
1065 
1066  // Set the sample parameters
1067  c->bit_rate = info.audio_bit_rate;
1068  c->channels = info.channels;
1069 
1070  // Set valid sample rate (or throw error)
1071  if (codec->supported_samplerates) {
1072  int i;
1073  for (i = 0; codec->supported_samplerates[i] != 0; i++)
1074  if (info.sample_rate == codec->supported_samplerates[i]) {
1075  // Set the valid sample rate
1076  c->sample_rate = info.sample_rate;
1077  break;
1078  }
1079  if (codec->supported_samplerates[i] == 0)
1080  throw InvalidSampleRate("An invalid sample rate was detected for this codec.", path);
1081  } else
1082  // Set sample rate
1083  c->sample_rate = info.sample_rate;
1084 
1085 
1086  // Set a valid number of channels (or throw error)
1087  const uint64_t channel_layout = info.channel_layout;
1088  if (codec->channel_layouts) {
1089  int i;
1090  for (i = 0; codec->channel_layouts[i] != 0; i++)
1091  if (channel_layout == codec->channel_layouts[i]) {
1092  // Set valid channel layout
1093  c->channel_layout = channel_layout;
1094  break;
1095  }
1096  if (codec->channel_layouts[i] == 0)
1097  throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1098  } else
1099  // Set valid channel layout
1100  c->channel_layout = channel_layout;
1101 
1102  // Choose a valid sample_fmt
1103  if (codec->sample_fmts) {
1104  for (int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1105  // Set sample format to 1st valid format (and then exit loop)
1106  c->sample_fmt = codec->sample_fmts[i];
1107  break;
1108  }
1109  }
1110  if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1111  // Default if no sample formats found
1112  c->sample_fmt = AV_SAMPLE_FMT_S16;
1113  }
1114 
1115  // some formats want stream headers to be separate
1116  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1117 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1118  // FFmpeg 3.0+
1119  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1120 #else
1121  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1122 #endif
1123 
1125  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_audio_stream", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->channels", c->channels, "c->sample_fmt", c->sample_fmt, "c->channel_layout", c->channel_layout, "c->sample_rate", c->sample_rate);
1126 
1127  return st;
1128 }
1129 
1130 // Add a video output stream
1131 AVStream *FFmpegWriter::add_video_stream() {
1132  AVCodecContext *c;
1133  AVStream *st;
1134 
1135  // Find the video codec
1136  AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1137  if (codec == NULL)
1138  throw InvalidCodec("A valid video codec could not be found for this file.", path);
1139 
1140  // Create a new video stream
1141  AV_FORMAT_NEW_STREAM(oc, video_codec_ctx, codec, st)
1142 
1143  c->codec_id = codec->id;
1144  c->codec_type = AVMEDIA_TYPE_VIDEO;
1145 
1146  /* Init video encoder options */
1147  if (info.video_bit_rate >= 1000
1148 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
1149  && c->codec_id != AV_CODEC_ID_AV1
1150 #endif
1151  ) {
1152  c->bit_rate = info.video_bit_rate;
1153  if (info.video_bit_rate >= 1500000) {
1154  if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1155  c->qmin = 2;
1156  c->qmax = 30;
1157  }
1158  }
1159  // Here should be the setting for low fixed bitrate
1160  // Defaults are used because mpeg2 otherwise had problems
1161  } else {
1162  // Check if codec supports crf or qp
1163  switch (c->codec_id) {
1164 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
1165  // FFmpeg 4.0+
1166  case AV_CODEC_ID_AV1 :
1167  // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet.
1168  if (info.video_bit_rate >= 1000) {
1169  c->bit_rate = 0;
1170  if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1171  int calculated_quality = 35;
1172  if (info.video_bit_rate < 500000) calculated_quality = 50;
1173  if (info.video_bit_rate > 5000000) calculated_quality = 10;
1174  av_opt_set_int(c->priv_data, "crf", calculated_quality, 0);
1175  info.video_bit_rate = calculated_quality;
1176  } else {
1177  int calculated_quality = 50;
1178  if (info.video_bit_rate < 500000) calculated_quality = 60;
1179  if (info.video_bit_rate > 5000000) calculated_quality = 15;
1180  av_opt_set_int(c->priv_data, "qp", calculated_quality, 0);
1181  info.video_bit_rate = calculated_quality;
1182  } // medium
1183  }
1184  if (strstr(info.vcodec.c_str(), "svtav1") != NULL) {
1185  av_opt_set_int(c->priv_data, "preset", 6, 0);
1186  av_opt_set_int(c->priv_data, "forced-idr",1,0);
1187  }
1188  else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) {
1189  av_opt_set_int(c->priv_data, "speed", 7, 0);
1190  av_opt_set_int(c->priv_data, "tile-rows", 2, 0);
1191  av_opt_set_int(c->priv_data, "tile-columns", 4, 0);
1192  }
1193  else if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1194  // Set number of tiles to a fixed value
1195  // TODO: Allow user to chose their own number of tiles
1196  av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows
1197  av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns
1198  av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores
1199  av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4
1200  }
1201  //break;
1202 #endif
1203  case AV_CODEC_ID_VP9 :
1204  case AV_CODEC_ID_HEVC :
1205  case AV_CODEC_ID_VP8 :
1206  case AV_CODEC_ID_H264 :
1207  if (info.video_bit_rate < 40) {
1208  c->qmin = 0;
1209  c->qmax = 63;
1210  } else {
1211  c->qmin = info.video_bit_rate - 5;
1212  c->qmax = 63;
1213  }
1214  break;
1215  default:
1216  // Here should be the setting for codecs that don't support crf
1217  // For now defaults are used
1218  break;
1219  }
1220  }
1221 
1222 //TODO: Implement variable bitrate feature (which actually works). This implementation throws
1223  //invalid bitrate errors and rc buffer underflow errors, etc...
1224  //c->rc_min_rate = info.video_bit_rate;
1225  //c->rc_max_rate = info.video_bit_rate;
1226  //c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
1227  //if ( !c->rc_initial_buffer_occupancy )
1228  // c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
1229 
1230  /* resolution must be a multiple of two */
1231  // TODO: require /2 height and width
1232  c->width = info.width;
1233  c->height = info.height;
1234 
1235  /* time base: this is the fundamental unit of time (in seconds) in terms
1236  of which frame timestamps are represented. for fixed-fps content,
1237  timebase should be 1/framerate and timestamp increments should be
1238  identically 1. */
1239  c->time_base.num = info.video_timebase.num;
1240  c->time_base.den = info.video_timebase.den;
1241 // AVCodecContext->framerate was added in FFmpeg 2.6
1242 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1243  c->framerate = av_inv_q(c->time_base);
1244 #endif
1245  st->avg_frame_rate = av_inv_q(c->time_base);
1246  st->time_base.num = info.video_timebase.num;
1247  st->time_base.den = info.video_timebase.den;
1248 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1249  #pragma GCC diagnostic push
1250  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1251  st->codec->time_base.num = info.video_timebase.num;
1252  st->codec->time_base.den = info.video_timebase.den;
1253  #pragma GCC diagnostic pop
1254 #endif
1255 
1256  c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
1257  c->max_b_frames = 10;
1258  if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1259  /* just for testing, we also add B frames */
1260  c->max_b_frames = 2;
1261  if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1262  /* Needed to avoid using macroblocks in which some coeffs overflow.
1263  This does not happen with normal video, it just happens here as
1264  the motion of the chroma plane does not match the luma plane. */
1265  c->mb_decision = 2;
1266  // some formats want stream headers to be separate
1267  if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1268 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1269  // FFmpeg 3.0+
1270  c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1271 #else
1272  c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1273 #endif
1274 
1275  // Find all supported pixel formats for this codec
1276  const PixelFormat *supported_pixel_formats = codec->pix_fmts;
1277  while (supported_pixel_formats != NULL && *supported_pixel_formats != PIX_FMT_NONE) {
1278  // Assign the 1st valid pixel format (if one is missing)
1279  if (c->pix_fmt == PIX_FMT_NONE)
1280  c->pix_fmt = *supported_pixel_formats;
1281  ++supported_pixel_formats;
1282  }
1283 
1284  // Codec doesn't have any pix formats?
1285  if (c->pix_fmt == PIX_FMT_NONE) {
1286  if (fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
1287  // Raw video should use RGB24
1288  c->pix_fmt = PIX_FMT_RGB24;
1289 
1290 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1291  // FFmpeg < 4.0
1292  if (strcmp(fmt->name, "gif") != 0)
1293  // If not GIF format, skip the encoding process
1294  // Set raw picture flag (so we don't encode this video)
1295  oc->oformat->flags |= AVFMT_RAWPICTURE;
1296 #endif
1297  } else {
1298  // Set the default codec
1299  c->pix_fmt = PIX_FMT_YUV420P;
1300  }
1301  }
1302 
1304 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1305  // FFmpeg < 4.0
1306  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (std::string)fmt->name + " : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "AVFMT_RAWPICTURE", AVFMT_RAWPICTURE);
1307 #else
1308  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (std::string)fmt->name + " : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags);
1309 #endif
1310 
1311  return st;
1312 }
1313 
1314 // open audio codec
1315 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1316  AVCodec *codec;
1317  AV_GET_CODEC_FROM_STREAM(st, audio_codec_ctx)
1318 
1319  // Set number of threads equal to number of processors (not to exceed 16)
1320  audio_codec_ctx->thread_count = std::min(FF_NUM_PROCESSORS, 16);
1321 
1322  // Find the audio encoder
1323  codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1324  if (!codec)
1325  codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1326  if (!codec)
1327  throw InvalidCodec("Could not find codec", path);
1328 
1329  // Init options
1330  AVDictionary *opts = NULL;
1331  av_dict_set(&opts, "strict", "experimental", 0);
1332 
1333  // Open the codec
1334  if (avcodec_open2(audio_codec_ctx, codec, &opts) < 0)
1335  throw InvalidCodec("Could not open audio codec", path);
1336  AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec_ctx);
1337 
1338  // Free options
1339  av_dict_free(&opts);
1340 
1341  // Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
1342  // TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
1343  if (audio_codec_ctx->frame_size <= 1) {
1344  // No frame size found... so calculate
1345  audio_input_frame_size = 50000 / info.channels;
1346 
1347  int s = AV_FIND_DECODER_CODEC_ID(st);
1348  switch (s) {
1349  case AV_CODEC_ID_PCM_S16LE:
1350  case AV_CODEC_ID_PCM_S16BE:
1351  case AV_CODEC_ID_PCM_U16LE:
1352  case AV_CODEC_ID_PCM_U16BE:
1353  audio_input_frame_size >>= 1;
1354  break;
1355  default:
1356  break;
1357  }
1358  } else {
1359  // Set frame size based on the codec
1360  audio_input_frame_size = audio_codec_ctx->frame_size;
1361  }
1362 
1363  // Set the initial frame size (since it might change during resampling)
1364  initial_audio_input_frame_size = audio_input_frame_size;
1365 
1366  // Allocate array for samples
1367  samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
1368 
1369  // Set audio output buffer (used to store the encoded audio)
1370  audio_outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
1371  audio_outbuf = new uint8_t[audio_outbuf_size];
1372 
1373  // Set audio packet encoding buffer
1374  audio_encoder_buffer_size = AUDIO_PACKET_ENCODING_SIZE;
1375  audio_encoder_buffer = new uint8_t[audio_encoder_buffer_size];
1376 
1377  // Add audio metadata (if any)
1378  for (std::map<std::string, std::string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1379  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1380  }
1381 
1382  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_audio", "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count, "audio_input_frame_size", audio_input_frame_size, "buffer_size", AVCODEC_MAX_AUDIO_FRAME_SIZE + MY_INPUT_BUFFER_PADDING_SIZE);
1383 }
1384 
1385 // open video codec
1386 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1387  AVCodec *codec;
1388  AV_GET_CODEC_FROM_STREAM(st, video_codec_ctx)
1389 
1390  // Set number of threads equal to number of processors (not to exceed 16)
1391  video_codec_ctx->thread_count = std::min(FF_NUM_PROCESSORS, 16);
1392 
1393 #if USE_HW_ACCEL
1394  if (hw_en_on && hw_en_supported) {
1395  //char *dev_hw = NULL;
1396  char adapter[256];
1397  char *adapter_ptr = NULL;
1398  int adapter_num;
1399  // Use the hw device given in the environment variable HW_EN_DEVICE_SET or the default if not set
1401  std::clog << "Encoding Device Nr: " << adapter_num << "\n";
1402  if (adapter_num < 3 && adapter_num >=0) {
1403 #if defined(__linux__)
1404  snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128);
1405  // Maybe 127 is better because the first card would be 1?!
1406  adapter_ptr = adapter;
1407 #elif defined(_WIN32) || defined(__APPLE__)
1408  adapter_ptr = NULL;
1409 #endif
1410  }
1411  else {
1412  adapter_ptr = NULL; // Just to be sure
1413  }
1414 // Check if it is there and writable
1415 #if defined(__linux__)
1416  if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1417 #elif defined(_WIN32) || defined(__APPLE__)
1418  if( adapter_ptr != NULL ) {
1419 #endif
1420  ZmqLogger::Instance()->AppendDebugMethod("Encode Device present using device", "adapter", adapter_num);
1421  }
1422  else {
1423  adapter_ptr = NULL; // use default
1424  ZmqLogger::Instance()->AppendDebugMethod("Encode Device not present, using default");
1425  }
1426  if (av_hwdevice_ctx_create(&hw_device_ctx, hw_en_av_device_type,
1427  adapter_ptr, NULL, 0) < 0) {
1428  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video ERROR creating hwdevice, Codec name:", info.vcodec.c_str(), -1);
1429  throw InvalidCodec("Could not create hwdevice", path);
1430  }
1431  }
1432 #endif // USE_HW_ACCEL
1433 
1434  /* find the video encoder */
1435  codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1436  if (!codec)
1437  codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
1438  if (!codec)
1439  throw InvalidCodec("Could not find codec", path);
1440 
1441  /* Force max_b_frames to 0 in some cases (i.e. for mjpeg image sequences */
1442  if (video_codec_ctx->max_b_frames && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1443  video_codec_ctx->max_b_frames = 0;
1444 
1445  // Init options
1446  AVDictionary *opts = NULL;
1447  av_dict_set(&opts, "strict", "experimental", 0);
1448 
1449 #if USE_HW_ACCEL
1451  video_codec_ctx->pix_fmt = hw_en_av_pix_fmt;
1452 
1453  // for the list of possible options, see the list of codec-specific options:
1454  // e.g. ffmpeg -h encoder=h264_vaapi or ffmpeg -h encoder=hevc_vaapi
1455  // and "man ffmpeg-codecs"
1456 
1457  // For VAAPI, it is safer to explicitly set rc_mode instead of relying on auto-selection
1458  // which is ffmpeg version-specific.
1459  if (hw_en_av_pix_fmt == AV_PIX_FMT_VAAPI) {
1460  int64_t qp;
1461  if (av_opt_get_int(video_codec_ctx->priv_data, "qp", 0, &qp) != 0 || qp == 0) {
1462  // unless "qp" was set for CQP, switch to VBR RC mode
1463  av_opt_set(video_codec_ctx->priv_data, "rc_mode", "VBR", 0);
1464 
1465  // In the current state (ffmpeg-4.2-4 libva-mesa-driver-19.1.5-1) to use VBR,
1466  // one has to specify both bit_rate and maxrate, otherwise a small low quality file is generated on Intel iGPU).
1467  video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1468  }
1469  }
1470 
1471  switch (video_codec_ctx->codec_id) {
1472  case AV_CODEC_ID_H264:
1473  video_codec_ctx->max_b_frames = 0; // At least this GPU doesn't support b-frames
1474  video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1475  av_opt_set(video_codec_ctx->priv_data, "preset", "slow", 0);
1476  av_opt_set(video_codec_ctx->priv_data, "tune", "zerolatency", 0);
1477  av_opt_set(video_codec_ctx->priv_data, "vprofile", "baseline", AV_OPT_SEARCH_CHILDREN);
1478  break;
1479  case AV_CODEC_ID_HEVC:
1480  // tested to work with defaults
1481  break;
1482  case AV_CODEC_ID_VP9:
1483  // tested to work with defaults
1484  break;
1485  default:
1486  ZmqLogger::Instance()->AppendDebugMethod("No codec-specific options defined for this codec. HW encoding may fail",
1487  "codec_id", video_codec_ctx->codec_id);
1488  break;
1489  }
1490 
1491  // set hw_frames_ctx for encoder's AVCodecContext
1492  int err;
1493  if ((err = set_hwframe_ctx(video_codec_ctx, hw_device_ctx, info.width, info.height)) < 0) {
1494  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1495  "width", info.width, "height", info.height, av_err2string(err), -1);
1496  }
1497  }
1498 #endif // USE_HW_ACCEL
1499 
1500  /* open the codec */
1501  if (avcodec_open2(video_codec_ctx, codec, &opts) < 0)
1502  throw InvalidCodec("Could not open video codec", path);
1503  AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx);
1504 
1505  // Free options
1506  av_dict_free(&opts);
1507 
1508  // Add video metadata (if any)
1509  for (std::map<std::string, std::string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1510  av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1511  }
1512 
1513  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video", "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1514 
1515 }
1516 
1517 // write all queued frames' audio to the video file
1518 void FFmpegWriter::write_audio_packets(bool is_final) {
1519  // Init audio buffers / variables
1520  int total_frame_samples = 0;
1521  int frame_position = 0;
1522  int channels_in_frame = 0;
1523  int sample_rate_in_frame = 0;
1524  int samples_in_frame = 0;
1525  ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
1526 
1527  // Create a new array (to hold all S16 audio samples, for the current queued frames
1528  unsigned int all_queued_samples_size = sizeof(int16_t) * (queued_audio_frames.size() * AVCODEC_MAX_AUDIO_FRAME_SIZE);
1529  int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1530  int16_t *all_resampled_samples = NULL;
1531  int16_t *final_samples_planar = NULL;
1532  int16_t *final_samples = NULL;
1533 
1534  // Loop through each queued audio frame
1535  while (!queued_audio_frames.empty()) {
1536  // Get front frame (from the queue)
1537  std::shared_ptr<Frame> frame = queued_audio_frames.front();
1538 
1539  // Get the audio details from this frame
1540  sample_rate_in_frame = frame->SampleRate();
1541  samples_in_frame = frame->GetAudioSamplesCount();
1542  channels_in_frame = frame->GetAudioChannelsCount();
1543  channel_layout_in_frame = frame->ChannelsLayout();
1544 
1545  // Get audio sample array
1546  float *frame_samples_float = NULL;
1547  // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
1548  frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1549 
1550  // Calculate total samples
1551  total_frame_samples = samples_in_frame * channels_in_frame;
1552 
1553  // Translate audio sample values back to 16 bit integers with saturation
1554  const int16_t max16 = 32767;
1555  const int16_t min16 = -32768;
1556  for (int s = 0; s < total_frame_samples; s++, frame_position++) {
1557  float valF = frame_samples_float[s] * (1 << 15);
1558  int16_t conv;
1559  if (valF > max16) {
1560  conv = max16;
1561  } else if (valF < min16) {
1562  conv = min16;
1563  } else {
1564  conv = int(valF + 32768.5) - 32768; // +0.5 is for rounding
1565  }
1566 
1567  // Copy into buffer
1568  all_queued_samples[frame_position] = conv;
1569  }
1570 
1571  // Deallocate float array
1572  delete[] frame_samples_float;
1573 
1574  // Remove front item
1575  queued_audio_frames.pop_front();
1576 
1577  } // end while
1578 
1579 
1580  // Update total samples (since we've combined all queued frames)
1581  total_frame_samples = frame_position;
1582  int remaining_frame_samples = total_frame_samples;
1583  int samples_position = 0;
1584 
1585 
1586  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets", "is_final", is_final, "total_frame_samples", total_frame_samples, "channel_layout_in_frame", channel_layout_in_frame, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "LAYOUT_MONO", LAYOUT_MONO);
1587 
1588  // Keep track of the original sample format
1589  AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1590 
1591  AVFrame *audio_frame = NULL;
1592  if (!is_final) {
1593  // Create input frame (and allocate arrays)
1594  audio_frame = AV_ALLOCATE_FRAME();
1595  AV_RESET_FRAME(audio_frame);
1596  audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1597 
1598  // Fill input frame with sample data
1599  int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) all_queued_samples, all_queued_samples_size, 0);
1600  if (error_code < 0) {
1601  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
1602  }
1603 
1604  // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
1605  switch (audio_codec_ctx->sample_fmt) {
1606  case AV_SAMPLE_FMT_FLTP: {
1607  output_sample_fmt = AV_SAMPLE_FMT_FLT;
1608  break;
1609  }
1610  case AV_SAMPLE_FMT_S32P: {
1611  output_sample_fmt = AV_SAMPLE_FMT_S32;
1612  break;
1613  }
1614  case AV_SAMPLE_FMT_S16P: {
1615  output_sample_fmt = AV_SAMPLE_FMT_S16;
1616  break;
1617  }
1618  case AV_SAMPLE_FMT_U8P: {
1619  output_sample_fmt = AV_SAMPLE_FMT_U8;
1620  break;
1621  }
1622  default: {
1623  // This is only here to silence unused-enum warnings
1624  break;
1625  }
1626  }
1627 
1628  // Update total samples & input frame size (due to bigger or smaller data types)
1629  total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
1630  total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
1631 
1632  // Create output frame (and allocate arrays)
1633  AVFrame *audio_converted = AV_ALLOCATE_FRAME();
1634  AV_RESET_FRAME(audio_converted);
1635  audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1636  av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
1637 
1638  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (1st resampling)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", output_sample_fmt, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
1639 
1640  // setup resample context
1641  if (!avr) {
1642  avr = SWR_ALLOC();
1643  av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
1644  av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
1645  av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1646  av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
1647  av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
1648  av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1649  av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1650  av_opt_set_int(avr, "out_channels", info.channels, 0);
1651  SWR_INIT(avr);
1652  }
1653  // Convert audio samples
1654  int nb_samples = SWR_CONVERT(
1655  avr, // audio resample context
1656  audio_converted->data, // output data pointers
1657  audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
1658  audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
1659  audio_frame->data, // input data pointers
1660  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1661  audio_frame->nb_samples // number of input samples to convert
1662  );
1663 
1664  // Set remaining samples
1665  remaining_frame_samples = total_frame_samples;
1666 
1667  // Create a new array (to hold all resampled S16 audio samples)
1668  all_resampled_samples = (int16_t *) av_malloc(
1669  sizeof(int16_t) * nb_samples * info.channels
1670  * (av_get_bytes_per_sample(output_sample_fmt) /
1671  av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1672  );
1673 
1674  // Copy audio samples over original samples
1675  memcpy(all_resampled_samples, audio_converted->data[0], nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1676 
1677  // Remove converted audio
1678  av_freep(&(audio_frame->data[0]));
1679  AV_FREE_FRAME(&audio_frame);
1680  av_freep(&audio_converted->data[0]);
1681  AV_FREE_FRAME(&audio_converted);
1682  all_queued_samples = NULL; // this array cleared with above call
1683 
1684  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)", "nb_samples", nb_samples, "remaining_frame_samples", remaining_frame_samples);
1685  }
1686 
1687  // Loop until no more samples
1688  while (remaining_frame_samples > 0 || is_final) {
1689  // Get remaining samples needed for this packet
1690  int remaining_packet_samples = (audio_input_frame_size * info.channels) - audio_input_position;
1691 
1692  // Determine how many samples we need
1693  int diff = 0;
1694  if (remaining_frame_samples >= remaining_packet_samples) {
1695  diff = remaining_packet_samples;
1696  } else {
1697  diff = remaining_frame_samples;
1698  }
1699 
1700  // Copy frame samples into the packet samples array
1701  if (!is_final)
1702  //TODO: Make this more sane
1703  memcpy(
1704  samples + (audio_input_position
1705  * (av_get_bytes_per_sample(output_sample_fmt) /
1706  av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1707  ),
1708  all_resampled_samples + samples_position,
1709  diff * av_get_bytes_per_sample(output_sample_fmt)
1710  );
1711 
1712  // Increment counters
1713  audio_input_position += diff;
1714  samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1715  remaining_frame_samples -= diff;
1716 
1717  // Do we have enough samples to proceed?
1718  if (audio_input_position < (audio_input_frame_size * info.channels) && !is_final)
1719  // Not enough samples to encode... so wait until the next frame
1720  break;
1721 
1722  // Convert to planar (if needed by audio codec)
1723  AVFrame *frame_final = AV_ALLOCATE_FRAME();
1724  AV_RESET_FRAME(frame_final);
1725  if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1727  "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1728  "in_sample_fmt", output_sample_fmt,
1729  "out_sample_fmt", audio_codec_ctx->sample_fmt,
1730  "in_sample_rate", info.sample_rate,
1731  "out_sample_rate", info.sample_rate,
1732  "in_channels", info.channels,
1733  "out_channels", info.channels
1734  );
1735 
1736  // setup resample context
1737  if (!avr_planar) {
1738  avr_planar = SWR_ALLOC();
1739  av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
1740  av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
1741  av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
1742  av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec_ctx->sample_fmt, 0); // planar not allowed here
1743  av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
1744  av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
1745  av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1746  av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
1747  SWR_INIT(avr_planar);
1748  }
1749 
1750  // Create input frame (and allocate arrays)
1751  audio_frame = AV_ALLOCATE_FRAME();
1752  AV_RESET_FRAME(audio_frame);
1753  audio_frame->nb_samples = audio_input_position / info.channels;
1754 
1755  // Create a new array
1756  final_samples_planar = (int16_t *) av_malloc(
1757  sizeof(int16_t) * audio_frame->nb_samples * info.channels
1758  * (av_get_bytes_per_sample(output_sample_fmt) /
1759  av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1760  );
1761 
1762  // Copy audio into buffer for frame
1763  memcpy(final_samples_planar, samples, audio_frame->nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt));
1764 
1765  // Fill input frame with sample data
1766  avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt,
1767  (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1768 
1769  // Create output frame (and allocate arrays)
1770  frame_final->nb_samples = audio_input_frame_size;
1771  frame_final->channels = info.channels;
1772  frame_final->format = audio_codec_ctx->sample_fmt;
1773  frame_final->channel_layout = info.channel_layout;
1774  av_samples_alloc(frame_final->data, frame_final->linesize, info.channels,
1775  frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1776 
1777  // Convert audio samples
1778  int nb_samples = SWR_CONVERT(
1779  avr_planar, // audio resample context
1780  frame_final->data, // output data pointers
1781  frame_final->linesize[0], // output plane size, in bytes. (0 if unknown)
1782  frame_final->nb_samples, // maximum number of samples that the output buffer can hold
1783  audio_frame->data, // input data pointers
1784  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1785  audio_frame->nb_samples // number of input samples to convert
1786  );
1787 
1788  // Copy audio samples over original samples
1789  if (nb_samples > 0) {
1790  memcpy(samples, frame_final->data[0],
1791  nb_samples * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) * info.channels);
1792  }
1793 
1794  // deallocate AVFrame
1795  av_freep(&(audio_frame->data[0]));
1796  AV_FREE_FRAME(&audio_frame);
1797  all_queued_samples = NULL; // this array cleared with above call
1798 
1799  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)", "nb_samples", nb_samples);
1800 
1801  } else {
1802  // Create a new array
1803  final_samples = (int16_t *) av_malloc(
1804  sizeof(int16_t) * audio_input_position
1805  * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1806  av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1807  );
1808 
1809  // Copy audio into buffer for frame
1810  memcpy(final_samples, samples,
1811  audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1812 
1813  // Init the nb_samples property
1814  frame_final->nb_samples = audio_input_frame_size;
1815 
1816  // Fill the final_frame AVFrame with audio (non planar)
1817  avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1818  audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1819  audio_encoder_buffer_size, 0);
1820  }
1821 
1822  // Set the AVFrame's PTS
1823  frame_final->pts = audio_timestamp;
1824 
1825  // Init the packet
1826  AVPacket pkt;
1827  av_init_packet(&pkt);
1828  pkt.data = audio_encoder_buffer;
1829  pkt.size = audio_encoder_buffer_size;
1830 
1831  // Set the packet's PTS prior to encoding
1832  pkt.pts = pkt.dts = audio_timestamp;
1833 
1834  /* encode the audio samples */
1835  int got_packet_ptr = 0;
1836 
1837 #if IS_FFMPEG_3_2
1838  // Encode audio (latest version of FFmpeg)
1839  int error_code;
1840  int ret = 0;
1841  int frame_finished = 0;
1842  error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1843  if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1844  avcodec_send_frame(audio_codec_ctx, NULL);
1845  }
1846  else {
1847  if (ret >= 0)
1848  pkt.size = 0;
1849  ret = avcodec_receive_packet(audio_codec_ctx, &pkt);
1850  if (ret >= 0)
1851  frame_finished = 1;
1852  if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1853  avcodec_flush_buffers(audio_codec_ctx);
1854  ret = 0;
1855  }
1856  if (ret >= 0) {
1857  ret = frame_finished;
1858  }
1859  }
1860  if (!pkt.data && !frame_finished)
1861  {
1862  ret = -1;
1863  }
1864  got_packet_ptr = ret;
1865 #else
1866  // Encode audio (older versions of FFmpeg)
1867  int error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, frame_final, &got_packet_ptr);
1868 #endif
1869  /* if zero size, it means the image was buffered */
1870  if (error_code == 0 && got_packet_ptr) {
1871 
1872  // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1873  // but it fixes lots of PTS related issues when I do this.
1874  pkt.pts = pkt.dts = audio_timestamp;
1875 
1876  // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
1877  av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
1878 
1879  // set stream
1880  pkt.stream_index = audio_st->index;
1881  pkt.flags |= AV_PKT_FLAG_KEY;
1882 
1883  /* write the compressed frame in the media file */
1884  error_code = av_interleaved_write_frame(oc, &pkt);
1885  }
1886 
1887  if (error_code < 0) {
1888  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
1889  }
1890 
1891  // Increment PTS (no pkt.duration, so calculate with maths)
1892  audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
1893 
1894  // deallocate AVFrame
1895  av_freep(&(frame_final->data[0]));
1896  AV_FREE_FRAME(&frame_final);
1897 
1898  // deallocate memory for packet
1899  AV_FREE_PACKET(&pkt);
1900 
1901  // Reset position
1902  audio_input_position = 0;
1903  is_final = false;
1904  }
1905 
1906  // Delete arrays (if needed)
1907  if (all_resampled_samples) {
1908  av_freep(&all_resampled_samples);
1909  all_resampled_samples = NULL;
1910  }
1911  if (all_queued_samples) {
1912  av_freep(&all_queued_samples);
1913  all_queued_samples = NULL;
1914  }
1915 }
1916 
1917 // Allocate an AVFrame object
1918 AVFrame *FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer) {
1919  // Create an RGB AVFrame
1920  AVFrame *new_av_frame = NULL;
1921 
1922  // Allocate an AVFrame structure
1923  new_av_frame = AV_ALLOCATE_FRAME();
1924  if (new_av_frame == NULL)
1925  throw OutOfMemory("Could not allocate AVFrame", path);
1926 
1927  // Determine required buffer size and allocate buffer
1928  *buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
1929 
1930  // Create buffer (if not provided)
1931  if (!new_buffer) {
1932  // New Buffer
1933  new_buffer = (uint8_t *) av_malloc(*buffer_size * sizeof(uint8_t));
1934  // Attach buffer to AVFrame
1935  AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
1936  new_av_frame->width = width;
1937  new_av_frame->height = height;
1938  new_av_frame->format = pix_fmt;
1939  }
1940 
1941  // return AVFrame
1942  return new_av_frame;
1943 }
1944 
1945 // process video frame
1946 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
1947  // Determine the height & width of the source image
1948  int source_image_width = frame->GetWidth();
1949  int source_image_height = frame->GetHeight();
1950 
1951  // Do nothing if size is 1x1 (i.e. no image in this frame)
1952  if (source_image_height == 1 && source_image_width == 1)
1953  return;
1954 
1955  // Init rescalers (if not initialized yet)
1956  if (image_rescalers.size() == 0)
1957  InitScalers(source_image_width, source_image_height);
1958 
1959  // Get a unique rescaler (for this thread)
1960  SwsContext *scaler = image_rescalers[rescaler_position];
1961  rescaler_position++;
1962  if (rescaler_position == num_of_rescalers)
1963  rescaler_position = 0;
1964 
1965  // Allocate an RGB frame & final output frame
1966  int bytes_source = 0;
1967  int bytes_final = 0;
1968  AVFrame *frame_source = NULL;
1969  const uchar *pixels = NULL;
1970 
1971  // Get a list of pixels from source image
1972  pixels = frame->GetPixels();
1973 
1974  // Init AVFrame for source image & final (converted image)
1975  frame_source = allocate_avframe(PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
1976 #if IS_FFMPEG_3_2
1977  AVFrame *frame_final;
1978 #if USE_HW_ACCEL
1979  if (hw_en_on && hw_en_supported) {
1980  frame_final = allocate_avframe(AV_PIX_FMT_NV12, info.width, info.height, &bytes_final, NULL);
1981  } else
1982 #endif // USE_HW_ACCEL
1983  {
1984  frame_final = allocate_avframe(
1985  (AVPixelFormat)(video_st->codecpar->format),
1986  info.width, info.height, &bytes_final, NULL
1987  );
1988  }
1989 #else
1990  AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt, info.width, info.height, &bytes_final, NULL);
1991 #endif // IS_FFMPEG_3_2
1992 
1993  // Fill with data
1994  AV_COPY_PICTURE_DATA(frame_source, (uint8_t *) pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
1995  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::process_video_packet", "frame->number", frame->number, "bytes_source", bytes_source, "bytes_final", bytes_final);
1996 
1997  // Resize & convert pixel format
1998  sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1999  source_image_height, frame_final->data, frame_final->linesize);
2000 
2001  // Add resized AVFrame to av_frames map
2002  add_avframe(frame, frame_final);
2003 
2004  // Deallocate memory
2005  AV_FREE_FRAME(&frame_source);
2006 }
2007 
2008 // write video frame
2009 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2010 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2011  // FFmpeg 4.0+
2012  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet",
2013  "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags);
2014 
2015  if (AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) {
2016 #else
2017  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet",
2018  "frame->number", frame->number,
2019  "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2020 
2021  if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2022 #endif
2023  // Raw video case.
2024  AVPacket pkt;
2025  av_init_packet(&pkt);
2026 
2027  pkt.flags |= AV_PKT_FLAG_KEY;
2028  pkt.stream_index = video_st->index;
2029  pkt.data = (uint8_t *) frame_final->data;
2030  pkt.size = sizeof(AVPicture);
2031 
2032  // Set PTS (in frames and scaled to the codec's timebase)
2033  pkt.pts = video_timestamp;
2034 
2035  /* write the compressed frame in the media file */
2036  int error_code = av_interleaved_write_frame(oc, &pkt);
2037  if (error_code < 0) {
2038  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
2039  return false;
2040  }
2041 
2042  // Deallocate packet
2043  AV_FREE_PACKET(&pkt);
2044 
2045  } else
2046  {
2047 
2048  AVPacket pkt;
2049  av_init_packet(&pkt);
2050  pkt.data = NULL;
2051  pkt.size = 0;
2052  pkt.pts = pkt.dts = AV_NOPTS_VALUE;
2053 
2054  // Assign the initial AVFrame PTS from the frame counter
2055  frame_final->pts = video_timestamp;
2056 #if USE_HW_ACCEL
2057  if (hw_en_on && hw_en_supported) {
2058  if (!(hw_frame = av_frame_alloc())) {
2059  std::clog << "Error code: av_hwframe_alloc\n";
2060  }
2061  if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx, hw_frame, 0) < 0) {
2062  std::clog << "Error code: av_hwframe_get_buffer\n";
2063  }
2064  if (!hw_frame->hw_frames_ctx) {
2065  std::clog << "Error hw_frames_ctx.\n";
2066  }
2067  hw_frame->format = AV_PIX_FMT_NV12;
2068  if ( av_hwframe_transfer_data(hw_frame, frame_final, 0) < 0) {
2069  std::clog << "Error while transferring frame data to surface.\n";
2070  }
2071  av_frame_copy_props(hw_frame, frame_final);
2072  }
2073 #endif // USE_HW_ACCEL
2074  /* encode the image */
2075  int got_packet_ptr = 0;
2076  int error_code = 0;
2077 #if IS_FFMPEG_3_2
2078  // Write video packet (latest version of FFmpeg)
2079  int ret;
2080 
2081  #if USE_HW_ACCEL
2082  if (hw_en_on && hw_en_supported) {
2083  ret = avcodec_send_frame(video_codec_ctx, hw_frame); //hw_frame!!!
2084  } else
2085  #endif // USE_HW_ACCEL
2086  {
2087  ret = avcodec_send_frame(video_codec_ctx, frame_final);
2088  }
2089  error_code = ret;
2090  if (ret < 0 ) {
2091  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent)");
2092  if (ret == AVERROR(EAGAIN) ) {
2093  std::clog << "Frame EAGAIN\n";
2094  }
2095  if (ret == AVERROR_EOF ) {
2096  std::clog << "Frame AVERROR_EOF\n";
2097  }
2098  avcodec_send_frame(video_codec_ctx, NULL);
2099  }
2100  else {
2101  while (ret >= 0) {
2102  ret = avcodec_receive_packet(video_codec_ctx, &pkt);
2103 
2104  if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2105  avcodec_flush_buffers(video_codec_ctx);
2106  got_packet_ptr = 0;
2107  break;
2108  }
2109  if (ret == 0) {
2110  got_packet_ptr = 1;
2111  break;
2112  }
2113  }
2114  }
2115 #else
2116  // Write video packet (older than FFmpeg 3.2)
2117  error_code = avcodec_encode_video2(video_codec_ctx, &pkt, frame_final, &got_packet_ptr);
2118  if (error_code != 0) {
2119  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + av_err2string(error_code) + "]", "error_code", error_code);
2120  }
2121  if (got_packet_ptr == 0) {
2122  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame gotpacket error)");
2123  }
2124 #endif // IS_FFMPEG_3_2
2125 
2126  /* if zero size, it means the image was buffered */
2127  if (error_code == 0 && got_packet_ptr) {
2128  // set the timestamp
2129  av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
2130  pkt.stream_index = video_st->index;
2131 
2132  /* write the compressed frame in the media file */
2133  int result = av_interleaved_write_frame(oc, &pkt);
2134  if (result < 0) {
2135  ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + av_err2string(result) + "]", "result", result);
2136  return false;
2137  }
2138  }
2139 
2140  // Deallocate packet
2141  AV_FREE_PACKET(&pkt);
2142 #if USE_HW_ACCEL
2143  if (hw_en_on && hw_en_supported) {
2144  if (hw_frame) {
2145  av_frame_free(&hw_frame);
2146  hw_frame = NULL;
2147  }
2148  }
2149 #endif // USE_HW_ACCEL
2150  }
2151 
2152  // Increment PTS (in frames and scaled to the codec's timebase)
2153  video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
2154 
2155  // Success
2156  return true;
2157 }
2158 
2159 // Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
2161  // output debug info
2162  av_dump_format(oc, 0, path.c_str(), 1);
2163 }
2164 
2165 // Init a collection of software rescalers (thread safe)
2166 void FFmpegWriter::InitScalers(int source_width, int source_height) {
2167  int scale_mode = SWS_FAST_BILINEAR;
2168  if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) {
2169  scale_mode = SWS_BICUBIC;
2170  }
2171 
2172  // Init software rescalers vector (many of them, one for each thread)
2173  for (int x = 0; x < num_of_rescalers; x++) {
2174  // Init the software scaler from FFMpeg
2175 #if USE_HW_ACCEL
2176  if (hw_en_on && hw_en_supported) {
2177  img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA,
2178  info.width, info.height, AV_PIX_FMT_NV12, scale_mode, NULL, NULL, NULL);
2179  } else
2180 #endif // USE_HW_ACCEL
2181  {
2182  img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA,
2183  info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec),
2184  scale_mode, NULL, NULL, NULL);
2185  }
2186 
2187  // Add rescaler to vector
2188  image_rescalers.push_back(img_convert_ctx);
2189  }
2190 }
2191 
2192 // Set audio resample options
2193 void FFmpegWriter::ResampleAudio(int sample_rate, int channels) {
2194  original_sample_rate = sample_rate;
2195  original_channels = channels;
2196 }
2197 
2198 // Remove & deallocate all software scalers
2200  // Close all rescalers
2201  for (int x = 0; x < num_of_rescalers; x++)
2202  sws_freeContext(image_rescalers[x]);
2203 
2204  // Clear vector
2205  image_rescalers.clear();
2206 }
#define AV_RESET_FRAME(av_frame)
int channels
The number of audio channels used in the audio stream.
Definition: WriterBase.h:73
A video stream (used to determine which type of stream)
Definition: FFmpegWriter.h:61
#define AV_FREE_FRAME(av_frame)
int num
Numerator for the fraction.
Definition: Fraction.h:50
WriterInfo info
Information about the current media file.
Definition: WriterBase.h:94
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
An audio stream (used to determine which type of stream)
Definition: FFmpegWriter.h:62
#define SWR_INIT(ctx)
int video_bit_rate
The bit rate of the video stream (in bytes)
Definition: WriterBase.h:61
Exception when an invalid # of audio channels are detected.
Definition: Exceptions.h:141
#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height)
#define AV_REGISTER_ALL
#define PIX_FMT_RGB24
#define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
openshot::Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3) ...
Definition: WriterBase.h:63
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
Definition: Fraction.cpp:84
static bool IsValidCodec(std::string codec_name)
Determine if codec name is valid.
AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx)
#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in)
#define AV_OPTION_FIND(priv_data, name)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
#define SWR_CLOSE(ctx)
#define SWR_FREE(ctx)
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:97
int width
The width of the video (in pixels)
Definition: WriterBase.h:58
int audio_bit_rate
The bit rate of the audio stream (in bytes)
Definition: WriterBase.h:71
Header file for FFmpegWriter class.
openshot::Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition: WriterBase.h:67
std::string acodec
The name of the audio codec used to encode / decode the video stream.
Definition: WriterBase.h:70
openshot::ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition: WriterBase.h:74
openshot::Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square) ...
Definition: WriterBase.h:62
AVPixelFormat hw_en_av_pix_fmt
AVDictionary * mux_dict
Exception when encoding audio packet.
Definition: Exceptions.h:125
Exception when invalid sample rate is detected during encoding.
Definition: Exceptions.h:237
void WriteFrame(std::shared_ptr< openshot::Frame > frame)
Add a frame to the stack waiting to be encoded.
void AppendDebugMethod(std::string method_name, std::string arg1_name="", float arg1_value=-1.0, std::string arg2_name="", float arg2_value=-1.0, std::string arg3_name="", float arg3_value=-1.0, std::string arg4_name="", float arg4_value=-1.0, std::string arg5_name="", float arg5_value=-1.0, std::string arg6_name="", float arg6_value=-1.0)
Append debug information.
Definition: ZmqLogger.cpp:190
void Open()
Open writer.
AVHWDeviceType hw_en_av_device_type
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
Header file for all Exception classes.
#define AV_FREE_CONTEXT(av_context)
void SetVideoOptions(bool has_video, std::string codec, openshot::Fraction fps, int width, int height, openshot::Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
Exception when no valid codec is found for a file.
Definition: Exceptions.h:157
Exception when memory could not be allocated.
Definition: Exceptions.h:321
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
Exception when invalid encoding options are used.
Definition: Exceptions.h:221
#define FF_NUM_PROCESSORS
void SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, openshot::ChannelLayout channel_layout, int bit_rate)
Set audio export options.
#define AV_FREE_PACKET(av_packet)
Exception when no streams are found in the file.
Definition: Exceptions.h:269
void RemoveScalers()
Remove & deallocate all software scalers.
#define AV_ALLOCATE_FRAME()
bool top_field_first
Which interlaced field should be displayed first.
Definition: WriterBase.h:69
Exception for files that can not be found or opened.
Definition: Exceptions.h:173
This class represents a fraction.
Definition: Fraction.h:48
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
#define PIX_FMT_YUV420P
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
#define PixelFormat
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
void Close()
Close the writer.
bool interlaced_frame
Are the contents of this frame interlaced.
Definition: WriterBase.h:68
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: WriterBase.h:72
#define MY_INPUT_BUFFER_PADDING_SIZE
#define AV_GET_IMAGE_SIZE(pix_fmt, width, height)
#define AV_OUTPUT_CONTEXT(output_context, path)
bool has_video
Determines if this file has a video stream.
Definition: WriterBase.h:52
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
Definition: ZmqLogger.cpp:52
int hw_en_on
std::map< std::string, std::string > metadata
An optional map/dictionary of video & audio metadata.
Definition: WriterBase.h:77
if(!codec) codec
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:46
#define PIX_FMT_YUV444P
#define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count)
AVDictionary * opts
#define AV_GET_CODEC_TYPE(av_stream)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
Definition: Settings.cpp:41
int HW_EN_DEVICE_SET
Which GPU to use to encode (0 is the first)
Definition: Settings.h:101
#define SWR_ALLOC()
bool has_audio
Determines if this file has an audio stream.
Definition: WriterBase.h:53
#define PIX_FMT_RGBA
#define AV_SET_FILENAME(oc, f)
std::string vcodec
The name of the video codec used to encode / decode the video stream.
Definition: WriterBase.h:64
int hw_en_supported
Exception when too many seek attempts happen.
Definition: Exceptions.h:390
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
int height
The height of the video (in pixels)
Definition: WriterBase.h:57
#define PIX_FMT_NONE
int den
Denominator for the fraction.
Definition: Fraction.h:51
FFmpegWriter(const std::string &path)
Constructor for FFmpegWriter. Throws an exception on failure to open path.
#define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st)
AVFrame * hw_frame
Exception when no valid format is found for a file.
Definition: Exceptions.h:189
openshot::Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: WriterBase.h:60
void SetOption(openshot::StreamType stream, std::string name, std::string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
#define AUDIO_PACKET_ENCODING_SIZE
StreamType
This enumeration designates the type of stream when encoding (video or audio)
Definition: FFmpegWriter.h:60
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)