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