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