OpenShot Library | libopenshot 0.6.0
Loading...
Searching...
No Matches
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
32using namespace openshot;
33
34// Multiplexer parameters temporary storage
35AVDictionary *mux_dict = NULL;
36
37#if USE_HW_ACCEL
38int hw_en_on = 1; // Is set in UI
39int hw_en_supported = 0; // Is set by FFmpegWriter
40AVPixelFormat hw_en_av_pix_fmt = AV_PIX_FMT_NONE;
41AVHWDeviceType hw_en_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
42static AVBufferRef *hw_device_ctx = NULL;
43AVFrame *hw_frame = NULL;
44
45static 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
76FFmpegWriter::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)
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)
118void 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
145void 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
165void 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)
278void 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
288void 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)
325void 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,
330 );
331}
332
333
334// Set custom options (some codecs accept additional params)
335void 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) {
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
604bool 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.
672void 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.
690void 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
732void 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
770void 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 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
815 pkt->stream_index = video_st->index;
816 error_code = av_interleaved_write_frame(oc, pkt);
817 }
818#else // IS_FFMPEG_3_2
819
820 // Encode video packet (older than FFmpeg 3.2)
821 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
822
823#endif // IS_FFMPEG_3_2
824
825 if (error_code < 0) {
827 "FFmpegWriter::flush_encoders ERROR ["
828 + av_err2string(error_code) + "]",
829 "error_code", error_code);
830 }
831 if (!got_packet) {
832 break;
833 }
834
835 // set the timestamp
836 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
837 pkt->stream_index = video_st->index;
838
839 // Write packet
840 error_code = av_interleaved_write_frame(oc, pkt);
841 if (error_code < 0) {
843 "FFmpegWriter::flush_encoders ERROR ["
844 + av_err2string(error_code) + "]",
845 "error_code", error_code);
846 }
847 }
848 }
849
850 // FLUSH AUDIO ENCODER
851 if (info.has_audio) {
852 for (;;) {
853#if IS_FFMPEG_3_2
854 AVPacket* pkt = av_packet_alloc();
855#else
856 AVPacket* pkt;
857 av_init_packet(pkt);
858#endif
859 pkt->data = NULL;
860 pkt->size = 0;
861 pkt->pts = pkt->dts = audio_timestamp;
862
863 /* encode the image */
864 int error_code = 0;
865 int got_packet = 0;
866#if IS_FFMPEG_3_2
867 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
868#else
869 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
870#endif
871 if (error_code < 0) {
873 "FFmpegWriter::flush_encoders ERROR ["
874 + av_err2string(error_code) + "]",
875 "error_code", error_code);
876 }
877 if (!got_packet) {
878 break;
879 }
880
881 // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
882 // but it fixes lots of PTS related issues when I do this.
883 pkt->pts = pkt->dts = audio_timestamp;
884
885 // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
886 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
887
888 // set stream
889 pkt->stream_index = audio_st->index;
890 pkt->flags |= AV_PKT_FLAG_KEY;
891
892 // Write packet
893 error_code = av_interleaved_write_frame(oc, pkt);
894 if (error_code < 0) {
896 "FFmpegWriter::flush_encoders ERROR ["
897 + av_err2string(error_code) + "]",
898 "error_code", error_code);
899 }
900
901 // Increment PTS by duration of packet
902 audio_timestamp += pkt->duration;
903
904 // deallocate memory for packet
905 AV_FREE_PACKET(pkt);
906 }
907 }
908
909}
910
911// Close the video codec
912void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
913{
914#if USE_HW_ACCEL
915 if (hw_en_on && hw_en_supported) {
916 if (hw_device_ctx) {
917 av_buffer_unref(&hw_device_ctx);
918 hw_device_ctx = NULL;
919 }
920 }
921#endif // USE_HW_ACCEL
922
923 // Free any previous memory allocations
924 if (video_codec_ctx != nullptr) {
925 AV_FREE_CONTEXT(video_codec_ctx);
926 av_free(video_codec_ctx);
927 }
928}
929
930// Close the audio codec
931void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
932{
933 // Clear buffers
934 delete[] samples;
935 delete[] audio_outbuf;
936 delete[] audio_encoder_buffer;
937 samples = NULL;
938 audio_outbuf = NULL;
939 audio_encoder_buffer = NULL;
940
941 // Deallocate resample buffer
942 if (avr) {
943 SWR_CLOSE(avr);
944 SWR_FREE(&avr);
945 avr = NULL;
946 }
947
948 if (avr_planar) {
949 SWR_CLOSE(avr_planar);
950 SWR_FREE(&avr_planar);
951 avr_planar = NULL;
952 }
953
954 // Free any previous memory allocations
955 if (audio_codec_ctx != nullptr) {
956 AV_FREE_CONTEXT(audio_codec_ctx);
957 av_free(audio_codec_ctx);
958 }
959}
960
961// Close the writer
963 // Write trailer (if needed)
964 if (!write_trailer)
965 WriteTrailer();
966
967 // Close each codec
968 if (video_st)
969 close_video(oc, video_st);
970 if (audio_st)
971 close_audio(oc, audio_st);
972
973 // Remove single software scaler
974 if (img_convert_ctx)
975 sws_freeContext(img_convert_ctx);
976
977 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
978 /* close the output file */
979 avio_close(oc->pb);
980 }
981
982 // Reset frame counters
983 video_timestamp = 0;
984 audio_timestamp = 0;
985
986 // Free the context which frees the streams too
987 avformat_free_context(oc);
988 oc = NULL;
989
990 // Close writer
991 is_open = false;
992 prepare_streams = false;
993 write_header = false;
994 write_trailer = false;
995
996 ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::Close");
997}
998
999// Add an AVFrame to the cache
1000void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1001 // Add AVFrame to map (if it does not already exist)
1002 if (!av_frames.count(frame)) {
1003 // Add av_frame
1004 av_frames[frame] = av_frame;
1005 } else {
1006 // Do not add, and deallocate this AVFrame
1007 AV_FREE_FRAME(&av_frame);
1008 }
1009}
1010
1011// Add an audio output stream
1012AVStream *FFmpegWriter::add_audio_stream() {
1013 // Find the audio codec
1014 const AVCodec *codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1015 if (codec == NULL)
1016 throw InvalidCodec("A valid audio codec could not be found for this file.", path);
1017
1018 // Free any previous memory allocations
1019 if (audio_codec_ctx != nullptr) {
1020 AV_FREE_CONTEXT(audio_codec_ctx);
1021 }
1022
1023 // Create a new audio stream
1024 AVStream* st = avformat_new_stream(oc, codec);
1025 if (!st)
1026 throw OutOfMemory("Could not allocate memory for the audio stream.", path);
1027
1028 // Allocate a new codec context for the stream
1029 ALLOC_CODEC_CTX(audio_codec_ctx, codec, st)
1030#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1031 st->codecpar->codec_id = codec->id;
1032#endif
1033 AVCodecContext* c = audio_codec_ctx;
1034
1035 c->codec_id = codec->id;
1036 c->codec_type = AVMEDIA_TYPE_AUDIO;
1037
1038 // Set the sample parameters
1039 c->bit_rate = info.audio_bit_rate;
1040#if !HAVE_CH_LAYOUT
1041 c->channels = info.channels;
1042#endif
1043
1044 // Set valid sample rate (or throw error)
1045 if (codec->supported_samplerates) {
1046 int i;
1047 for (i = 0; codec->supported_samplerates[i] != 0; i++)
1048 if (info.sample_rate == codec->supported_samplerates[i]) {
1049 // Set the valid sample rate
1050 c->sample_rate = info.sample_rate;
1051 break;
1052 }
1053 if (codec->supported_samplerates[i] == 0)
1054 throw InvalidSampleRate("An invalid sample rate was detected for this codec.", path);
1055 } else
1056 // Set sample rate
1057 c->sample_rate = info.sample_rate;
1058
1059 uint64_t channel_layout = info.channel_layout;
1060#if HAVE_CH_LAYOUT
1061 // Set a valid number of channels (or throw error)
1062 AVChannelLayout ch_layout;
1063 av_channel_layout_from_mask(&ch_layout, info.channel_layout);
1064 if (codec->ch_layouts) {
1065 int i;
1066 for (i = 0; av_channel_layout_check(&codec->ch_layouts[i]); i++)
1067 if (av_channel_layout_compare(&ch_layout, &codec->ch_layouts[i])) {
1068 // Set valid channel layout
1069 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1070 break;
1071 }
1072 if (!av_channel_layout_check(&codec->ch_layouts[i]))
1073 throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1074 } else
1075 // Set valid channel layout
1076 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1077#else
1078 // Set a valid number of channels (or throw error)
1079 if (codec->channel_layouts) {
1080 int i;
1081 for (i = 0; codec->channel_layouts[i] != 0; i++)
1082 if (channel_layout == codec->channel_layouts[i]) {
1083 // Set valid channel layout
1084 c->channel_layout = channel_layout;
1085 break;
1086 }
1087 if (codec->channel_layouts[i] == 0)
1088 throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1089 } else
1090 // Set valid channel layout
1091 c->channel_layout = channel_layout;
1092#endif
1093
1094 // Choose a valid sample_fmt
1095 if (codec->sample_fmts) {
1096 for (int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1097 // Set sample format to 1st valid format (and then exit loop)
1098 c->sample_fmt = codec->sample_fmts[i];
1099 break;
1100 }
1101 }
1102 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1103 // Default if no sample formats found
1104 c->sample_fmt = AV_SAMPLE_FMT_S16;
1105 }
1106
1107 // some formats want stream headers to be separate
1108 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1109#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1110 // FFmpeg 3.0+
1111 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1112#else
1113 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1114#endif
1115
1117
1118 int nb_channels;
1119 const char* nb_channels_label;
1120 const char* channel_layout_label;
1121
1122#if HAVE_CH_LAYOUT
1123 nb_channels = c->ch_layout.nb_channels;
1124 channel_layout = c->ch_layout.u.mask;
1125 nb_channels_label = "c->ch_layout.nb_channels";
1126 channel_layout_label = "c->ch_layout.u.mask";
1127#else
1128 nb_channels = c->channels;
1129 nb_channels_label = "c->channels";
1130 channel_layout_label = "c->channel_layout";
1131#endif
1132
1134 "FFmpegWriter::add_audio_stream",
1135 "c->codec_id", c->codec_id,
1136 "c->bit_rate", c->bit_rate,
1137 nb_channels_label, nb_channels,
1138 "c->sample_fmt", c->sample_fmt,
1139 channel_layout_label, channel_layout,
1140 "c->sample_rate", c->sample_rate);
1141
1142 return st;
1143}
1144
1145// Add a video output stream
1146AVStream *FFmpegWriter::add_video_stream() {
1147 // Find the video codec
1148 const AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1149 if (codec == NULL)
1150 throw InvalidCodec("A valid video codec could not be found for this file.", path);
1151
1152 // Free any previous memory allocations
1153 if (video_codec_ctx != nullptr) {
1154 AV_FREE_CONTEXT(video_codec_ctx);
1155 }
1156
1157 // Create a new video stream
1158 AVStream* st = avformat_new_stream(oc, codec);
1159 if (!st)
1160 throw OutOfMemory("Could not allocate memory for the video stream.", path);
1161
1162 // Allocate a new codec context for the stream
1163 ALLOC_CODEC_CTX(video_codec_ctx, codec, st)
1164#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1165 st->codecpar->codec_id = codec->id;
1166#endif
1167
1168 AVCodecContext* c = video_codec_ctx;
1169
1170 c->codec_id = codec->id;
1171 c->codec_type = AVMEDIA_TYPE_VIDEO;
1172
1173 // Set sample aspect ratio
1174 c->sample_aspect_ratio.num = info.pixel_ratio.num;
1175 c->sample_aspect_ratio.den = info.pixel_ratio.den;
1176
1177 /* Init video encoder options */
1178 if (info.video_bit_rate >= 1000
1179#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1180 && c->codec_id != AV_CODEC_ID_AV1
1181#endif
1182 ) {
1183 c->bit_rate = info.video_bit_rate;
1184 if (info.video_bit_rate >= 1500000) {
1185 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1186 c->qmin = 2;
1187 c->qmax = 30;
1188 }
1189 }
1190 // Here should be the setting for low fixed bitrate
1191 // Defaults are used because mpeg2 otherwise had problems
1192 } else {
1193 // Check if codec supports crf or qp
1194 switch (c->codec_id) {
1195#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1196 // FFmpeg 4.0+
1197 case AV_CODEC_ID_AV1 :
1198 // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet.
1199 if (info.video_bit_rate >= 1000) {
1200 c->bit_rate = 0;
1201 if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1202 int calculated_quality = 35;
1203 if (info.video_bit_rate < 500000) calculated_quality = 50;
1204 if (info.video_bit_rate > 5000000) calculated_quality = 10;
1205 av_opt_set_int(c->priv_data, "crf", calculated_quality, 0);
1206 info.video_bit_rate = calculated_quality;
1207 } else {
1208 int calculated_quality = 50;
1209 if (info.video_bit_rate < 500000) calculated_quality = 60;
1210 if (info.video_bit_rate > 5000000) calculated_quality = 15;
1211 av_opt_set_int(c->priv_data, "qp", calculated_quality, 0);
1212 info.video_bit_rate = calculated_quality;
1213 } // medium
1214 }
1215 if (strstr(info.vcodec.c_str(), "svtav1") != NULL) {
1216 av_opt_set_int(c->priv_data, "preset", 6, 0);
1217 av_opt_set_int(c->priv_data, "forced-idr",1,0);
1218 }
1219 else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) {
1220 av_opt_set_int(c->priv_data, "speed", 7, 0);
1221 av_opt_set_int(c->priv_data, "tile-rows", 2, 0);
1222 av_opt_set_int(c->priv_data, "tile-columns", 4, 0);
1223 }
1224 else if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1225 // Set number of tiles to a fixed value
1226 // TODO: Allow user to chose their own number of tiles
1227 av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows
1228 av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns
1229 av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores
1230 av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4
1231 }
1232 //break;
1233#endif
1234 case AV_CODEC_ID_VP9 :
1235 case AV_CODEC_ID_HEVC :
1236 case AV_CODEC_ID_VP8 :
1237 case AV_CODEC_ID_H264 :
1238 if (info.video_bit_rate < 40) {
1239 c->qmin = 0;
1240 c->qmax = 63;
1241 } else {
1242 c->qmin = info.video_bit_rate - 5;
1243 c->qmax = 63;
1244 }
1245 break;
1246 default:
1247 // Here should be the setting for codecs that don't support crf
1248 // For now defaults are used
1249 break;
1250 }
1251 }
1252
1253 //TODO: Implement variable bitrate feature (which actually works). This implementation throws
1254 //invalid bitrate errors and rc buffer underflow errors, etc...
1255 //c->rc_min_rate = info.video_bit_rate;
1256 //c->rc_max_rate = info.video_bit_rate;
1257 //c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
1258 //if ( !c->rc_initial_buffer_occupancy )
1259 // c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
1260
1261 /* resolution must be a multiple of two */
1262 // TODO: require /2 height and width
1263 c->width = info.width;
1264 c->height = info.height;
1265
1266 /* time base: this is the fundamental unit of time (in seconds) in terms
1267 of which frame timestamps are represented. for fixed-fps content,
1268 timebase should be 1/framerate and timestamp increments should be
1269 identically 1. */
1270 c->time_base.num = info.video_timebase.num;
1271 c->time_base.den = info.video_timebase.den;
1272// AVCodecContext->framerate was added in FFmpeg 2.6
1273#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1274 c->framerate = av_inv_q(c->time_base);
1275#endif
1276 st->avg_frame_rate = av_inv_q(c->time_base);
1277 st->time_base.num = info.video_timebase.num;
1278 st->time_base.den = info.video_timebase.den;
1279
1280 c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
1281 c->max_b_frames = 10;
1282 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1283 /* just for testing, we also add B frames */
1284 c->max_b_frames = 2;
1285 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1286 /* Needed to avoid using macroblocks in which some coeffs overflow.
1287 This does not happen with normal video, it just happens here as
1288 the motion of the chroma plane does not match the luma plane. */
1289 c->mb_decision = 2;
1290 // some formats want stream headers to be separate
1291 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1292#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1293 // FFmpeg 3.0+
1294 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1295#else
1296 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1297#endif
1298
1299 // Find all supported pixel formats for this codec
1300 const PixelFormat *supported_pixel_formats = codec->pix_fmts;
1301 while (supported_pixel_formats != NULL && *supported_pixel_formats != PIX_FMT_NONE) {
1302 // Assign the 1st valid pixel format (if one is missing)
1303 if (c->pix_fmt == PIX_FMT_NONE)
1304 c->pix_fmt = *supported_pixel_formats;
1305 ++supported_pixel_formats;
1306 }
1307
1308 // Codec doesn't have any pix formats?
1309 if (c->pix_fmt == PIX_FMT_NONE) {
1310 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1311 // Raw video should use RGB24
1312 c->pix_fmt = PIX_FMT_RGB24;
1313
1314#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1315 // FFmpeg < 4.0
1316 if (strcmp(oc->oformat->name, "gif") != 0)
1317 // If not GIF format, skip the encoding process
1318 // Set raw picture flag (so we don't encode this video)
1319 oc->oformat->flags |= AVFMT_RAWPICTURE;
1320#endif
1321 } else {
1322 // Set the default codec
1323 c->pix_fmt = PIX_FMT_YUV420P;
1324 }
1325 }
1326
1329 "FFmpegWriter::add_video_stream ("
1330 + (std::string)oc->oformat->name + " : "
1331 + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")",
1332 "c->codec_id", c->codec_id,
1333 "c->bit_rate", c->bit_rate,
1334 "c->pix_fmt", c->pix_fmt,
1335 "oc->oformat->flags", oc->oformat->flags);
1336 return st;
1337}
1338
1339// open audio codec
1340void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1341 const AVCodec *codec;
1342 AV_GET_CODEC_FROM_STREAM(st, audio_codec_ctx)
1343
1344 // Audio encoding does not typically use more than 2 threads (most codecs use 1 thread)
1345 audio_codec_ctx->thread_count = std::min(FF_AUDIO_NUM_PROCESSORS, 2);
1346
1347 // Find the audio encoder
1348 codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1349 if (!codec)
1350 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1351 if (!codec)
1352 throw InvalidCodec("Could not find codec", path);
1353
1354 // Init options
1355 AVDictionary *opts = NULL;
1356 av_dict_set(&opts, "strict", "experimental", 0);
1357
1358 // Open the codec
1359 if (avcodec_open2(audio_codec_ctx, codec, &opts) < 0)
1360 throw InvalidCodec("Could not open audio codec", path);
1361 AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec_ctx);
1362
1363 // Free options
1364 av_dict_free(&opts);
1365
1366 // Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
1367 // TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
1368 if (audio_codec_ctx->frame_size <= 1) {
1369 // No frame size found... so calculate
1370 audio_input_frame_size = 50000 / info.channels;
1371
1372 int s = AV_FIND_DECODER_CODEC_ID(st);
1373 switch (s) {
1374 case AV_CODEC_ID_PCM_S16LE:
1375 case AV_CODEC_ID_PCM_S16BE:
1376 case AV_CODEC_ID_PCM_U16LE:
1377 case AV_CODEC_ID_PCM_U16BE:
1378 audio_input_frame_size >>= 1;
1379 break;
1380 default:
1381 break;
1382 }
1383 } else {
1384 // Set frame size based on the codec
1385 audio_input_frame_size = audio_codec_ctx->frame_size;
1386 }
1387
1388 // Set the initial frame size (since it might change during resampling)
1389 initial_audio_input_frame_size = audio_input_frame_size;
1390
1391 // Allocate array for samples
1392 samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
1393
1394 // Set audio output buffer (used to store the encoded audio)
1395 audio_outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
1396 audio_outbuf = new uint8_t[audio_outbuf_size];
1397
1398 // Set audio packet encoding buffer
1399 audio_encoder_buffer_size = AUDIO_PACKET_ENCODING_SIZE;
1400 audio_encoder_buffer = new uint8_t[audio_encoder_buffer_size];
1401
1402 // Add audio metadata (if any)
1403 for (std::map<std::string, std::string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1404 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1405 }
1406
1408 "FFmpegWriter::open_audio",
1409 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1410 "audio_input_frame_size", audio_input_frame_size,
1412}
1413
1414// open video codec
1415void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1416 const AVCodec *codec;
1417 AV_GET_CODEC_FROM_STREAM(st, video_codec_ctx)
1418
1419 // Set number of threads equal to number of processors (not to exceed 16, FFmpeg doesn't recommend more than 16)
1420 video_codec_ctx->thread_count = std::min(FF_VIDEO_NUM_PROCESSORS, 16);
1421
1422#if USE_HW_ACCEL
1423 if (hw_en_on && hw_en_supported) {
1424 //char *dev_hw = NULL;
1425 char adapter[256];
1426 char *adapter_ptr = NULL;
1427 int adapter_num;
1428 // Use the hw device given in the environment variable HW_EN_DEVICE_SET or the default if not set
1430 std::clog << "Encoding Device Nr: " << adapter_num << "\n";
1431 if (adapter_num < 3 && adapter_num >=0) {
1432#if defined(__linux__)
1433 snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128);
1434 // Maybe 127 is better because the first card would be 1?!
1435 adapter_ptr = adapter;
1436#elif defined(_WIN32) || defined(__APPLE__)
1437 adapter_ptr = NULL;
1438#endif
1439 }
1440 else {
1441 adapter_ptr = NULL; // Just to be sure
1442 }
1443// Check if it is there and writable
1444#if defined(__linux__)
1445 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1446#elif defined(_WIN32) || defined(__APPLE__)
1447 if( adapter_ptr != NULL ) {
1448#endif
1450 "Encode Device present using device",
1451 "adapter", adapter_num);
1452 }
1453 else {
1454 adapter_ptr = NULL; // use default
1456 "Encode Device not present, using default");
1457 }
1458 if (av_hwdevice_ctx_create(&hw_device_ctx,
1459 hw_en_av_device_type, adapter_ptr, NULL, 0) < 0)
1460 {
1462 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1463 info.vcodec.c_str(), -1);
1464 throw InvalidCodec("Could not create hwdevice", path);
1465 }
1466 }
1467#endif // USE_HW_ACCEL
1468
1469 /* find the video encoder */
1470 codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1471 if (!codec)
1472 codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
1473 if (!codec)
1474 throw InvalidCodec("Could not find codec", path);
1475
1476 /* Legacy behavior: force max_b_frames to 0 for many codecs.
1477 * This can be disabled via SetOption(VIDEO_STREAM, "allow_b_frames", "1"). */
1478 if (!allow_b_frames && video_codec_ctx->max_b_frames &&
1479 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 &&
1480 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO &&
1481 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1482 video_codec_ctx->max_b_frames = 0;
1483
1484 // Init options
1485 AVDictionary *opts = NULL;
1486 av_dict_set(&opts, "strict", "experimental", 0);
1487
1488#if USE_HW_ACCEL
1490 video_codec_ctx->pix_fmt = hw_en_av_pix_fmt;
1491
1492 // for the list of possible options, see the list of codec-specific options:
1493 // e.g. ffmpeg -h encoder=h264_vaapi or ffmpeg -h encoder=hevc_vaapi
1494 // and "man ffmpeg-codecs"
1495
1496 // For VAAPI, it is safer to explicitly set rc_mode instead of relying on auto-selection
1497 // which is ffmpeg version-specific.
1498 if (hw_en_av_pix_fmt == AV_PIX_FMT_VAAPI) {
1499 int64_t qp;
1500 if (av_opt_get_int(video_codec_ctx->priv_data, "qp", 0, &qp) != 0 || qp == 0) {
1501 // unless "qp" was set for CQP, switch to VBR RC mode
1502 av_opt_set(video_codec_ctx->priv_data, "rc_mode", "VBR", 0);
1503
1504 // In the current state (ffmpeg-4.2-4 libva-mesa-driver-19.1.5-1) to use VBR,
1505 // one has to specify both bit_rate and maxrate, otherwise a small low quality file is generated on Intel iGPU).
1506 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1507 }
1508 }
1509
1510 switch (video_codec_ctx->codec_id) {
1511 case AV_CODEC_ID_H264:
1512 video_codec_ctx->max_b_frames = 0; // At least this GPU doesn't support b-frames
1513 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1514 av_opt_set(video_codec_ctx->priv_data, "preset", "slow", 0);
1515 av_opt_set(video_codec_ctx->priv_data, "tune", "zerolatency", 0);
1516 av_opt_set(video_codec_ctx->priv_data, "vprofile", "baseline", AV_OPT_SEARCH_CHILDREN);
1517 break;
1518 case AV_CODEC_ID_HEVC:
1519 // tested to work with defaults
1520 break;
1521 case AV_CODEC_ID_VP9:
1522 // tested to work with defaults
1523 break;
1524 default:
1526 "No codec-specific options defined for this codec. HW encoding may fail",
1527 "codec_id", video_codec_ctx->codec_id);
1528 break;
1529 }
1530
1531 // set hw_frames_ctx for encoder's AVCodecContext
1532 int err;
1533 if ((err = set_hwframe_ctx(video_codec_ctx, hw_device_ctx, info.width, info.height)) < 0)
1534 {
1536 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1537 "width", info.width,
1538 "height", info.height,
1539 av_err2string(err), -1);
1540 }
1541 }
1542#endif // USE_HW_ACCEL
1543
1544// Set libx265 hvc1 tag (for Apple playback compatibility).
1545#if USE_HW_ACCEL
1546 if (!(hw_en_on && hw_en_supported) && video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
1547 video_codec_ctx->codec_tag = MKTAG('h', 'v', 'c', '1');
1548 }
1549#else
1550 if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
1551 video_codec_ctx->codec_tag = MKTAG('h', 'v', 'c', '1');
1552 }
1553#endif
1554
1555 /* open the codec */
1556 if (avcodec_open2(video_codec_ctx, codec, &opts) < 0)
1557 throw InvalidCodec("Could not open video codec", path);
1558 AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx);
1559
1560 // Free options
1561 av_dict_free(&opts);
1562
1563 // Add video metadata (if any)
1564 for (auto iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1565 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1566 }
1567
1569 "FFmpegWriter::open_video",
1570 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1571
1572}
1573
1574// write all queued frames' audio to the video file
1575void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::Frame> frame) {
1576 if (!frame && !is_final)
1577 return;
1578
1579 // Init audio buffers / variables
1580 int total_frame_samples = 0;
1581 int frame_position = 0;
1582 int channels_in_frame = 0;
1583 int sample_rate_in_frame = 0;
1584 int samples_in_frame = 0;
1585 ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
1586
1587 // Create a new array (to hold all S16 audio samples, for the current queued frames
1588 unsigned int all_queued_samples_size = sizeof(int16_t) * AVCODEC_MAX_AUDIO_FRAME_SIZE;
1589 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1590 int16_t *all_resampled_samples = NULL;
1591 int16_t *final_samples_planar = NULL;
1592 int16_t *final_samples = NULL;
1593
1594 // Get audio sample array
1595 float *frame_samples_float = NULL;
1596
1597 // Get the audio details from this frame
1598 if (frame) {
1599 sample_rate_in_frame = frame->SampleRate();
1600 samples_in_frame = frame->GetAudioSamplesCount();
1601 channels_in_frame = frame->GetAudioChannelsCount();
1602 channel_layout_in_frame = frame->ChannelsLayout();
1603
1604 // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
1605 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1606 }
1607
1608 // Calculate total samples
1609 total_frame_samples = samples_in_frame * channels_in_frame;
1610
1611 // Translate audio sample values back to 16 bit integers with saturation
1612 const int16_t max16 = 32767;
1613 const int16_t min16 = -32768;
1614 for (int s = 0; s < total_frame_samples; s++, frame_position++) {
1615 float valF = frame_samples_float[s] * (1 << 15);
1616 int16_t conv;
1617 if (valF > max16) {
1618 conv = max16;
1619 } else if (valF < min16) {
1620 conv = min16;
1621 } else {
1622 conv = int(valF + 32768.5) - 32768; // +0.5 is for rounding
1623 }
1624
1625 // Copy into buffer
1626 all_queued_samples[frame_position] = conv;
1627 }
1628
1629 // Deallocate float array
1630 delete[] frame_samples_float;
1631
1632
1633 // Update total samples (since we've combined all queued frames)
1634 total_frame_samples = frame_position;
1635 int remaining_frame_samples = total_frame_samples;
1636 int samples_position = 0;
1637
1638
1640 "FFmpegWriter::write_audio_packets",
1641 "is_final", is_final,
1642 "total_frame_samples", total_frame_samples,
1643 "channel_layout_in_frame", channel_layout_in_frame,
1644 "channels_in_frame", channels_in_frame,
1645 "samples_in_frame", samples_in_frame,
1646 "LAYOUT_MONO", LAYOUT_MONO);
1647
1648 // Keep track of the original sample format
1649 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1650
1651 AVFrame *audio_frame = NULL;
1652 if (!is_final) {
1653 // Create input frame (and allocate arrays)
1654 audio_frame = AV_ALLOCATE_FRAME();
1655 AV_RESET_FRAME(audio_frame);
1656 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1657
1658 // Fill input frame with sample data
1659 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);
1660 if (error_code < 0) {
1662 "FFmpegWriter::write_audio_packets ERROR ["
1663 + av_err2string(error_code) + "]",
1664 "error_code", error_code);
1665 }
1666
1667 // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
1668 switch (audio_codec_ctx->sample_fmt) {
1669 case AV_SAMPLE_FMT_FLTP: {
1670 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1671 break;
1672 }
1673 case AV_SAMPLE_FMT_S32P: {
1674 output_sample_fmt = AV_SAMPLE_FMT_S32;
1675 break;
1676 }
1677 case AV_SAMPLE_FMT_S16P: {
1678 output_sample_fmt = AV_SAMPLE_FMT_S16;
1679 break;
1680 }
1681 case AV_SAMPLE_FMT_U8P: {
1682 output_sample_fmt = AV_SAMPLE_FMT_U8;
1683 break;
1684 }
1685 default: {
1686 // This is only here to silence unused-enum warnings
1687 break;
1688 }
1689 }
1690
1691 // Update total samples & input frame size (due to bigger or smaller data types)
1692 total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
1693 total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
1694
1695 // Create output frame (and allocate arrays)
1696 AVFrame *audio_converted = AV_ALLOCATE_FRAME();
1697 AV_RESET_FRAME(audio_converted);
1698 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1699 av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
1700
1702 "FFmpegWriter::write_audio_packets (1st resampling)",
1703 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1704 "out_sample_fmt", output_sample_fmt,
1705 "in_sample_rate", sample_rate_in_frame,
1706 "out_sample_rate", info.sample_rate,
1707 "in_channels", channels_in_frame,
1708 "out_channels", info.channels);
1709
1710 // setup resample context
1711 if (!avr) {
1712 avr = SWR_ALLOC();
1713#if HAVE_CH_LAYOUT
1714 AVChannelLayout in_chlayout;
1715 AVChannelLayout out_chlayout;
1716 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
1717 av_channel_layout_from_mask(&out_chlayout, info.channel_layout);
1718 av_opt_set_chlayout(avr, "in_chlayout", &in_chlayout, 0);
1719 av_opt_set_chlayout(avr, "out_chlayout", &out_chlayout, 0);
1720#else
1721 av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
1722 av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
1723 av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
1724 av_opt_set_int(avr, "out_channels", info.channels, 0);
1725#endif
1726 av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1727 av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
1728 av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
1729 av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
1730 SWR_INIT(avr);
1731 }
1732 // Convert audio samples
1733 int nb_samples = SWR_CONVERT(
1734 avr, // audio resample context
1735 audio_converted->data, // output data pointers
1736 audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
1737 audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
1738 audio_frame->data, // input data pointers
1739 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1740 audio_frame->nb_samples // number of input samples to convert
1741 );
1742
1743 // Set remaining samples
1744 remaining_frame_samples = total_frame_samples;
1745
1746 // Create a new array (to hold all resampled S16 audio samples)
1747 all_resampled_samples = (int16_t *) av_malloc(
1748 sizeof(int16_t) * nb_samples * info.channels
1749 * (av_get_bytes_per_sample(output_sample_fmt) /
1750 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1751 );
1752
1753 // Copy audio samples over original samples
1754 memcpy(all_resampled_samples, audio_converted->data[0],
1755 static_cast<size_t>(nb_samples)
1756 * info.channels
1757 * av_get_bytes_per_sample(output_sample_fmt));
1758
1759 // Remove converted audio
1760 av_freep(&(audio_frame->data[0]));
1761 AV_FREE_FRAME(&audio_frame);
1762 av_freep(&audio_converted->data[0]);
1763 AV_FREE_FRAME(&audio_converted);
1764 all_queued_samples = NULL; // this array cleared with above call
1765
1767 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1768 "nb_samples", nb_samples,
1769 "remaining_frame_samples", remaining_frame_samples);
1770 }
1771
1772 // Loop until no more samples
1773 while (remaining_frame_samples > 0 || is_final) {
1774 // Get remaining samples needed for this packet
1775 int remaining_packet_samples = (audio_input_frame_size * info.channels) - audio_input_position;
1776
1777 // Determine how many samples we need
1778 int diff = 0;
1779 if (remaining_frame_samples >= remaining_packet_samples) {
1780 diff = remaining_packet_samples;
1781 } else {
1782 diff = remaining_frame_samples;
1783 }
1784
1785 // Copy frame samples into the packet samples array
1786 if (!is_final)
1787 //TODO: Make this more sane
1788 memcpy(
1789 samples + (audio_input_position
1790 * (av_get_bytes_per_sample(output_sample_fmt) /
1791 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1792 ),
1793 all_resampled_samples + samples_position,
1794 static_cast<size_t>(diff)
1795 * av_get_bytes_per_sample(output_sample_fmt)
1796 );
1797
1798 // Increment counters
1799 audio_input_position += diff;
1800 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1801 remaining_frame_samples -= diff;
1802
1803 // Do we have enough samples to proceed?
1804 if (audio_input_position < (audio_input_frame_size * info.channels) && !is_final)
1805 // Not enough samples to encode... so wait until the next frame
1806 break;
1807
1808 // Convert to planar (if needed by audio codec)
1809 AVFrame *frame_final = AV_ALLOCATE_FRAME();
1810 AV_RESET_FRAME(frame_final);
1811 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1813 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1814 "in_sample_fmt", output_sample_fmt,
1815 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1816 "in_sample_rate", info.sample_rate,
1817 "out_sample_rate", info.sample_rate,
1818 "in_channels", info.channels,
1819 "out_channels", info.channels
1820 );
1821
1822 // setup resample context
1823 if (!avr_planar) {
1824 avr_planar = SWR_ALLOC();
1825#if HAVE_CH_LAYOUT
1826 AVChannelLayout layout;
1827 av_channel_layout_from_mask(&layout, info.channel_layout);
1828 av_opt_set_chlayout(avr_planar, "in_chlayout", &layout, 0);
1829 av_opt_set_chlayout(avr_planar, "out_chlayout", &layout, 0);
1830#else
1831 av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
1832 av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
1833 av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
1834 av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
1835#endif
1836 av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
1837 av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec_ctx->sample_fmt, 0); // planar not allowed here
1838 av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
1839 av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
1840 SWR_INIT(avr_planar);
1841 }
1842
1843 // Create input frame (and allocate arrays)
1844 audio_frame = AV_ALLOCATE_FRAME();
1845 AV_RESET_FRAME(audio_frame);
1846 audio_frame->nb_samples = audio_input_position / info.channels;
1847
1848 // Create a new array
1849 final_samples_planar = (int16_t *) av_malloc(
1850 sizeof(int16_t) * audio_frame->nb_samples * info.channels
1851 * (av_get_bytes_per_sample(output_sample_fmt) /
1852 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1853 );
1854
1855 // Copy audio into buffer for frame
1856 memcpy(final_samples_planar, samples,
1857 static_cast<size_t>(audio_frame->nb_samples)
1858 * info.channels
1859 * av_get_bytes_per_sample(output_sample_fmt));
1860
1861 // Fill input frame with sample data
1862 avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt,
1863 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1864
1865 // Create output frame (and allocate arrays)
1866 frame_final->nb_samples = audio_input_frame_size;
1867#if HAVE_CH_LAYOUT
1868 av_channel_layout_from_mask(&frame_final->ch_layout, info.channel_layout);
1869#else
1870 frame_final->channels = info.channels;
1871 frame_final->channel_layout = info.channel_layout;
1872#endif
1873 frame_final->format = audio_codec_ctx->sample_fmt;
1874 av_samples_alloc(frame_final->data, frame_final->linesize, info.channels,
1875 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1876
1877 // Convert audio samples
1878 int nb_samples = SWR_CONVERT(
1879 avr_planar, // audio resample context
1880 frame_final->data, // output data pointers
1881 frame_final->linesize[0], // output plane size, in bytes. (0 if unknown)
1882 frame_final->nb_samples, // maximum number of samples that the output buffer can hold
1883 audio_frame->data, // input data pointers
1884 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
1885 audio_frame->nb_samples // number of input samples to convert
1886 );
1887
1888 // Copy audio samples over original samples
1889 const auto copy_length = static_cast<size_t>(nb_samples)
1890 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
1891 * info.channels;
1892
1893 if (nb_samples > 0)
1894 memcpy(samples, frame_final->data[0], copy_length);
1895
1896 // deallocate AVFrame
1897 av_freep(&(audio_frame->data[0]));
1898 AV_FREE_FRAME(&audio_frame);
1899 all_queued_samples = NULL; // this array cleared with above call
1900
1902 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
1903 "nb_samples", nb_samples);
1904
1905 } else {
1906 // Create a new array
1907 const auto buf_size = static_cast<size_t>(audio_input_position)
1908 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1909 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
1910 );
1911 final_samples = reinterpret_cast<int16_t*>(
1912 av_malloc(sizeof(int16_t) * buf_size));
1913
1914 // Copy audio into buffer for frame
1915 memcpy(final_samples, samples,
1916 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1917
1918 // Init the nb_samples property
1919 frame_final->nb_samples = audio_input_frame_size;
1920
1921 // Fill the final_frame AVFrame with audio (non planar)
1922#if HAVE_CH_LAYOUT
1923 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
1924#else
1925 int nb_channels = audio_codec_ctx->channels;
1926#endif
1927 avcodec_fill_audio_frame(frame_final, nb_channels,
1928 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1929 audio_encoder_buffer_size, 0);
1930 }
1931
1932 // Set the AVFrame's PTS
1933 frame_final->pts = audio_timestamp;
1934
1935 // Init the packet
1936#if IS_FFMPEG_3_2
1937 AVPacket* pkt = av_packet_alloc();
1938#else
1939 AVPacket* pkt;
1940 av_init_packet(pkt);
1941#endif
1942 pkt->data = audio_encoder_buffer;
1943 pkt->size = audio_encoder_buffer_size;
1944
1945 // Set the packet's PTS prior to encoding
1946 pkt->pts = pkt->dts = audio_timestamp;
1947
1948 /* encode the audio samples */
1949 int got_packet_ptr = 0;
1950
1951#if IS_FFMPEG_3_2
1952 // Encode audio (latest version of FFmpeg)
1953 int error_code;
1954 int ret = 0;
1955 int frame_finished = 0;
1956 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1957 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1958 avcodec_send_frame(audio_codec_ctx, NULL);
1959 }
1960 else {
1961 if (ret >= 0)
1962 pkt->size = 0;
1963 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
1964 if (ret >= 0)
1965 frame_finished = 1;
1966 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1967 avcodec_flush_buffers(audio_codec_ctx);
1968 ret = 0;
1969 }
1970 if (ret >= 0) {
1971 ret = frame_finished;
1972 }
1973 }
1974 if (!pkt->data && !frame_finished)
1975 {
1976 ret = -1;
1977 }
1978 got_packet_ptr = ret;
1979#else
1980 // Encode audio (older versions of FFmpeg)
1981 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
1982#endif
1983 /* if zero size, it means the image was buffered */
1984 if (error_code == 0 && got_packet_ptr) {
1985
1986 // Since the PTS can change during encoding, set the value again. This seems like a huge hack,
1987 // but it fixes lots of PTS related issues when I do this.
1988 pkt->pts = pkt->dts = audio_timestamp;
1989
1990 // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
1991 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1992
1993 // set stream
1994 pkt->stream_index = audio_st->index;
1995 pkt->flags |= AV_PKT_FLAG_KEY;
1996
1997 /* write the compressed frame in the media file */
1998 error_code = av_interleaved_write_frame(oc, pkt);
1999 }
2000
2001 if (error_code < 0) {
2003 "FFmpegWriter::write_audio_packets ERROR ["
2004 + av_err2string(error_code) + "]",
2005 "error_code", error_code);
2006 }
2007
2008 // Increment PTS (no pkt.duration, so calculate with maths)
2009 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2010
2011 // deallocate AVFrame
2012 av_freep(&(frame_final->data[0]));
2013 AV_FREE_FRAME(&frame_final);
2014
2015 // deallocate memory for packet
2016 AV_FREE_PACKET(pkt);
2017
2018 // Reset position
2019 audio_input_position = 0;
2020 is_final = false;
2021 }
2022
2023 // Delete arrays (if needed)
2024 if (all_resampled_samples) {
2025 av_freep(&all_resampled_samples);
2026 all_resampled_samples = NULL;
2027 }
2028 if (all_queued_samples) {
2029 av_freep(&all_queued_samples);
2030 all_queued_samples = NULL;
2031 }
2032}
2033
2034// Allocate an AVFrame object
2035AVFrame *FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer) {
2036 // Create an RGB AVFrame
2037 AVFrame *new_av_frame = NULL;
2038
2039 // Allocate an AVFrame structure
2040 new_av_frame = AV_ALLOCATE_FRAME();
2041 if (new_av_frame == NULL)
2042 throw OutOfMemory("Could not allocate AVFrame", path);
2043
2044 // Determine required buffer size and allocate buffer
2045 *buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
2046
2047 // Create buffer (if not provided)
2048 if (!new_buffer) {
2049 // New Buffer
2050 new_buffer = (uint8_t *) av_malloc(*buffer_size * sizeof(uint8_t));
2051 // Attach buffer to AVFrame
2052 AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
2053 new_av_frame->width = width;
2054 new_av_frame->height = height;
2055 new_av_frame->format = pix_fmt;
2056 }
2057
2058 // return AVFrame
2059 return new_av_frame;
2060}
2061
2062// process video frame
2063void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2064 // Source dimensions (RGBA)
2065 int src_w = frame->GetWidth();
2066 int src_h = frame->GetHeight();
2067
2068 // Skip empty frames (1×1)
2069 if (src_w == 1 && src_h == 1)
2070 return;
2071
2072 // Point persistent_src_frame->data to RGBA pixels
2073 const uchar* pixels = frame->GetPixels();
2074 if (!persistent_src_frame) {
2075 persistent_src_frame = av_frame_alloc();
2076 if (!persistent_src_frame)
2077 throw OutOfMemory("Could not allocate persistent_src_frame", path);
2078 persistent_src_frame->format = AV_PIX_FMT_RGBA;
2079 persistent_src_frame->width = src_w;
2080 persistent_src_frame->height = src_h;
2081 persistent_src_frame->linesize[0] = src_w * 4;
2082 }
2083 persistent_src_frame->data[0] = const_cast<uint8_t*>(
2084 reinterpret_cast<const uint8_t*>(pixels)
2085 );
2086
2087 // Prepare persistent_dst_frame + buffer on first use
2088 if (!persistent_dst_frame) {
2089 persistent_dst_frame = av_frame_alloc();
2090 if (!persistent_dst_frame)
2091 throw OutOfMemory("Could not allocate persistent_dst_frame", path);
2092
2093 // Decide destination pixel format: NV12 if HW accel is on, else encoder’s pix_fmt
2094 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2095#if USE_HW_ACCEL
2096 if (hw_en_on && hw_en_supported) {
2097 dst_fmt = AV_PIX_FMT_NV12;
2098 }
2099#endif
2100 persistent_dst_frame->format = dst_fmt;
2101 persistent_dst_frame->width = info.width;
2102 persistent_dst_frame->height = info.height;
2103
2104 persistent_dst_size = av_image_get_buffer_size(
2105 dst_fmt, info.width, info.height, 1
2106 );
2107 if (persistent_dst_size < 0)
2108 throw ErrorEncodingVideo("Invalid destination image size", -1);
2109
2110 persistent_dst_buffer = static_cast<uint8_t*>(
2111 av_malloc(persistent_dst_size)
2112 );
2113 if (!persistent_dst_buffer)
2114 throw OutOfMemory("Could not allocate persistent_dst_buffer", path);
2115
2116 av_image_fill_arrays(
2117 persistent_dst_frame->data,
2118 persistent_dst_frame->linesize,
2119 persistent_dst_buffer,
2120 dst_fmt,
2121 info.width,
2122 info.height,
2123 1
2124 );
2125 }
2126
2127 // Initialize SwsContext (RGBA → dst_fmt) on first use
2128 if (!img_convert_ctx) {
2129 int flags = SWS_FAST_BILINEAR;
2130 if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) {
2131 flags = SWS_BICUBIC;
2132 }
2133 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2134#if USE_HW_ACCEL
2135 if (hw_en_on && hw_en_supported) {
2136 dst_fmt = AV_PIX_FMT_NV12;
2137 }
2138#endif
2139 img_convert_ctx = sws_getContext(
2140 src_w, src_h, AV_PIX_FMT_RGBA,
2141 info.width, info.height, dst_fmt,
2142 flags, NULL, NULL, NULL
2143 );
2144 if (!img_convert_ctx)
2145 throw ErrorEncodingVideo("Could not initialize sws context", -1);
2146 }
2147
2148 // Scale RGBA → dst_fmt into persistent_dst_buffer
2149 sws_scale(
2150 img_convert_ctx,
2151 persistent_src_frame->data,
2152 persistent_src_frame->linesize,
2153 0, src_h,
2154 persistent_dst_frame->data,
2155 persistent_dst_frame->linesize
2156 );
2157
2158 // Allocate a new AVFrame + buffer, then copy scaled data into it
2159 int bytes_final = 0;
2160 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2161#if USE_HW_ACCEL
2162 if (hw_en_on && hw_en_supported) {
2163 dst_fmt = AV_PIX_FMT_NV12;
2164 }
2165#endif
2166
2167 AVFrame* new_frame = allocate_avframe(
2168 dst_fmt,
2169 info.width,
2170 info.height,
2171 &bytes_final,
2172 nullptr
2173 );
2174 if (!new_frame)
2175 throw OutOfMemory("Could not allocate new_frame via allocate_avframe", path);
2176
2177 // Copy persistent_dst_buffer → new_frame buffer
2178 memcpy(
2179 new_frame->data[0],
2180 persistent_dst_buffer,
2181 static_cast<size_t>(bytes_final)
2182 );
2183
2184 // Queue the deep‐copied frame for encoding
2185 add_avframe(frame, new_frame);
2186}
2187
2188// write video frame
2189bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2190#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2191 // FFmpeg 4.0+
2193 "FFmpegWriter::write_video_packet",
2194 "frame->number", frame->number,
2195 "oc->oformat->flags", oc->oformat->flags);
2196
2197 if (AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) {
2198#else
2199 // TODO: Should we have moved away from oc->oformat->flags / AVFMT_RAWPICTURE
2200 // on ffmpeg < 4.0 as well?
2201 // Does AV_CODEC_ID_RAWVIDEO not work in ffmpeg 3.x?
2203 "FFmpegWriter::write_video_packet",
2204 "frame->number", frame->number,
2205 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2206
2207 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2208#endif
2209 // Raw video case.
2210#if IS_FFMPEG_3_2
2211 AVPacket* pkt = av_packet_alloc();
2212#else
2213 AVPacket* pkt;
2214 av_init_packet(pkt);
2215#endif
2216
2217 av_packet_from_data(
2218 pkt, frame_final->data[0],
2219 frame_final->linesize[0] * frame_final->height);
2220
2221 pkt->flags |= AV_PKT_FLAG_KEY;
2222 pkt->stream_index = video_st->index;
2223
2224 // Set PTS (in frames and scaled to the codec's timebase)
2225 pkt->pts = video_timestamp;
2226
2227 /* write the compressed frame in the media file */
2228 int error_code = av_interleaved_write_frame(oc, pkt);
2229 if (error_code < 0) {
2231 "FFmpegWriter::write_video_packet ERROR ["
2232 + av_err2string(error_code) + "]",
2233 "error_code", error_code);
2234 return false;
2235 }
2236
2237 // Deallocate packet
2238 AV_FREE_PACKET(pkt);
2239
2240 } else
2241 {
2242
2243#if IS_FFMPEG_3_2
2244 AVPacket* pkt = av_packet_alloc();
2245#else
2246 AVPacket* pkt;
2247 av_init_packet(pkt);
2248#endif
2249 pkt->data = NULL;
2250 pkt->size = 0;
2251 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2252
2253 // Assign the initial AVFrame PTS from the frame counter
2254 frame_final->pts = video_timestamp;
2255#if USE_HW_ACCEL
2256 if (hw_en_on && hw_en_supported) {
2257 if (!(hw_frame = av_frame_alloc())) {
2258 std::clog << "Error code: av_hwframe_alloc\n";
2259 }
2260 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx, hw_frame, 0) < 0) {
2261 std::clog << "Error code: av_hwframe_get_buffer\n";
2262 }
2263 if (!hw_frame->hw_frames_ctx) {
2264 std::clog << "Error hw_frames_ctx.\n";
2265 }
2266 hw_frame->format = AV_PIX_FMT_NV12;
2267 if ( av_hwframe_transfer_data(hw_frame, frame_final, 0) < 0) {
2268 std::clog << "Error while transferring frame data to surface.\n";
2269 }
2270 av_frame_copy_props(hw_frame, frame_final);
2271 }
2272#endif // USE_HW_ACCEL
2273 /* encode the image */
2274 int got_packet_ptr = 0;
2275 int error_code = 0;
2276#if IS_FFMPEG_3_2
2277 // Write video packet
2278 int ret;
2279
2280 #if USE_HW_ACCEL
2281 if (hw_en_on && hw_en_supported) {
2282 ret = avcodec_send_frame(video_codec_ctx, hw_frame); //hw_frame!!!
2283 } else
2284 #endif // USE_HW_ACCEL
2285 {
2286 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2287 }
2288 error_code = ret;
2289 if (ret < 0 ) {
2291 "FFmpegWriter::write_video_packet (Frame not sent)");
2292 if (ret == AVERROR(EAGAIN) ) {
2293 std::clog << "Frame EAGAIN\n";
2294 }
2295 if (ret == AVERROR_EOF ) {
2296 std::clog << "Frame AVERROR_EOF\n";
2297 }
2298 avcodec_send_frame(video_codec_ctx, NULL);
2299 }
2300 else {
2301 while (ret >= 0) {
2302 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2303
2304 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2305 got_packet_ptr = 0;
2306 break;
2307 }
2308 if (ret == 0) {
2309 got_packet_ptr = 1;
2310 break;
2311 }
2312 }
2313 }
2314#else
2315 // Write video packet (older than FFmpeg 3.2)
2316 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2317 if (error_code != 0) {
2319 "FFmpegWriter::write_video_packet ERROR ["
2320 + av_err2string(error_code) + "]",
2321 "error_code", error_code);
2322 }
2323 if (got_packet_ptr == 0) {
2325 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2326 }
2327#endif // IS_FFMPEG_3_2
2328
2329 /* if zero size, it means the image was buffered */
2330 if (error_code == 0 && got_packet_ptr) {
2331 // set the timestamp
2332 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2333 pkt->stream_index = video_st->index;
2334
2335 /* write the compressed frame in the media file */
2336 int result = av_interleaved_write_frame(oc, pkt);
2337 if (result < 0) {
2339 "FFmpegWriter::write_video_packet ERROR ["
2340 + av_err2string(result) + "]",
2341 "result", result);
2342 return false;
2343 }
2344 }
2345
2346 // Deallocate packet
2347 AV_FREE_PACKET(pkt);
2348#if USE_HW_ACCEL
2349 if (hw_en_on && hw_en_supported) {
2350 if (hw_frame) {
2351 av_frame_free(&hw_frame);
2352 hw_frame = NULL;
2353 }
2354 }
2355#endif // USE_HW_ACCEL
2356 }
2357
2358 // Increment PTS (in frames and scaled to the codec's timebase)
2359 video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
2360
2361 // Success
2362 return true;
2363}
2364
2365// Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
2367 // output debug info
2368 av_dump_format(oc, 0, path.c_str(), 1);
2369}
2370
2371// Set audio resample options
2372void FFmpegWriter::ResampleAudio(int sample_rate, int channels) {
2373 original_sample_rate = sample_rate;
2374 original_channels = channels;
2375}
2376
2377// In FFmpegWriter.cpp
2378void FFmpegWriter::AddSphericalMetadata(const std::string& projection, float yaw_deg, float pitch_deg, float roll_deg) {
2379 if (!oc) return;
2380 if (!info.has_video || !video_st) return;
2381
2382 // Allow movenc.c to write out the sv3d atom
2383 oc->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
2384
2385#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
2386 // Map the projection name to the enum (defaults to equirectangular)
2387 int proj = av_spherical_from_name(projection.c_str());
2388 if (proj < 0)
2389 proj = AV_SPHERICAL_EQUIRECTANGULAR;
2390
2391 // Allocate the side‐data structure
2392 size_t sd_size = 0;
2393 AVSphericalMapping* map = av_spherical_alloc(&sd_size);
2394 if (!map) return;
2395
2396 // Populate it
2397 map->projection = static_cast<AVSphericalProjection>(proj);
2398 // yaw/pitch/roll are 16.16 fixed point
2399 map->yaw = static_cast<int32_t>(yaw_deg * (1 << 16));
2400 map->pitch = static_cast<int32_t>(pitch_deg * (1 << 16));
2401 map->roll = static_cast<int32_t>(roll_deg * (1 << 16));
2402
2403 av_stream_add_side_data(video_st, AV_PKT_DATA_SPHERICAL, reinterpret_cast<uint8_t*>(map), sd_size);
2404#endif
2405}
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.
Exception when encoding audio packet.
Definition Exceptions.h:149
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 an invalid # of audio channels are detected.
Definition Exceptions.h:164
Exception when no valid codec is found for a file.
Definition Exceptions.h:179
Exception for files that can not be found or opened.
Definition Exceptions.h:194
Exception when no valid format is found for a file.
Definition Exceptions.h:209
Exception when invalid encoding options are used.
Definition Exceptions.h:239
Exception when invalid sample rate is detected during encoding.
Definition Exceptions.h:254
Exception when no streams are found in the file.
Definition Exceptions.h:292
Exception when memory could not be allocated.
Definition Exceptions.h:355
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:86
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:422
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
int audio_bit_rate
The bit rate of the audio stream (in bytes)
Definition WriterBase.h:53
int video_bit_rate
The bit rate of the video stream (in bytes)
Definition WriterBase.h:43
bool has_audio
Determines if this file has an audio stream.
Definition WriterBase.h:35
bool top_field_first
Which interlaced field should be displayed first.
Definition WriterBase.h:51
int channels
The number of audio channels used in the audio stream.
Definition WriterBase.h:55
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
std::string acodec
The name of the audio codec used to encode / decode the video stream.
Definition WriterBase.h:52
openshot::Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition WriterBase.h:49
openshot::ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition WriterBase.h:56
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
int width
The width of the video (in pixels)
Definition WriterBase.h:40
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
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition WriterBase.h:54
bool interlaced_frame
Are the contents of this frame interlaced.
Definition WriterBase.h:50