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