OpenShot Library | libopenshot 1.1.1
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 <chrono>
18#include <cstdarg>
19#include <iostream>
20#include <memory>
21#include <set>
22#include <cmath>
23#include <ctime>
24#include <sstream>
25#include <unistd.h>
26
27#include "FFmpegUtilities.h"
28
29#include "FFmpegWriter.h"
30#include "Exceptions.h"
31#include "Frame.h"
32#include "OpenMPUtilities.h"
33#include "Settings.h"
34#include "Logger.h"
35
36using namespace openshot;
37
38// Multiplexer parameters temporary storage
39AVDictionary *mux_dict = NULL;
40
41#if USE_HW_ACCEL
42int hw_en_on = 1; // Is set in UI
43int hw_en_supported = 0; // Is set by FFmpegWriter
44AVPixelFormat hw_en_av_pix_fmt = AV_PIX_FMT_NONE;
45AVHWDeviceType hw_en_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
46static AVBufferRef *hw_device_ctx = NULL;
47AVFrame *hw_frame = NULL;
48
49static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
50{
51 AVBufferRef *hw_frames_ref;
52 AVHWFramesContext *frames_ctx = NULL;
53 int err = 0;
54
55 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
56 std::clog << "Failed to create HW frame context.\n";
57 return -1;
58 }
59 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
60 frames_ctx->format = hw_en_av_pix_fmt;
61 frames_ctx->sw_format = AV_PIX_FMT_NV12;
62 frames_ctx->width = width;
63 frames_ctx->height = height;
64 frames_ctx->initial_pool_size = 20;
65 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
66 std::clog << "Failed to initialize HW frame context. " <<
67 "Error code: " << av_err2string(err) << "\n";
68 av_buffer_unref(&hw_frames_ref);
69 return err;
70 }
71 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
72 if (!ctx->hw_frames_ctx)
73 err = AVERROR(ENOMEM);
74
75 av_buffer_unref(&hw_frames_ref);
76 return err;
77}
78#endif // USE_HW_ACCEL
79
80FFmpegWriter::FFmpegWriter(const std::string& path) :
81 path(path), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
82 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
83 initial_audio_input_frame_size(0), img_convert_ctx(NULL),
84 video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
85 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
86 write_header(false), write_trailer(false), allow_b_frames(false), testing(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
87
88 // Disable audio & video (so they can be independently enabled)
89 info.has_audio = false;
90 info.has_video = false;
91
92 // Initialize FFMpeg, and register all formats and codecs
94
95 // auto detect format
96 auto_detect_format();
97}
98
99// Open the writer
101 if (!is_open) {
102 // Open the writer
103 is_open = true;
104
105 // Prepare streams (if needed)
106 if (!prepare_streams)
108
109 // Now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers
110 if (info.has_video && video_st)
111 open_video(oc, video_st);
112 if (info.has_audio && audio_st)
113 open_audio(oc, audio_st);
114
115 // Write header (if needed)
116 if (!write_header)
117 WriteHeader();
118 }
119}
120
121// auto detect format (from path)
122void FFmpegWriter::auto_detect_format() {
123
124 // Allocate the output media context
125 AV_OUTPUT_CONTEXT(&oc, path.c_str());
126 if (!oc) {
127 throw OutOfMemory(
128 "Could not allocate memory for AVFormatContext.", path);
129 }
130
131 // Determine what format to use when encoding this output filename
132 oc->oformat = av_guess_format(NULL, path.c_str(), NULL);
133 if (oc->oformat == nullptr) {
134 throw InvalidFormat("Could not deduce output format from file extension.", path);
135 }
136
137 // Update video & audio codec name
138 if (oc->oformat->video_codec != AV_CODEC_ID_NONE && info.has_video) {
139 const AVCodec *vcodec = avcodec_find_encoder(oc->oformat->video_codec);
140 info.vcodec = vcodec ? vcodec->name : std::string();
141 }
142 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE && info.has_audio) {
143 const AVCodec *acodec = avcodec_find_encoder(oc->oformat->audio_codec);
144 info.acodec = acodec ? acodec->name : std::string();
145 }
146}
147
148// initialize streams
149void FFmpegWriter::initialize_streams() {
151 "FFmpegWriter::initialize_streams",
152 "oc->oformat->video_codec", oc->oformat->video_codec,
153 "oc->oformat->audio_codec", oc->oformat->audio_codec,
154 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
155
156 // Add the audio and video streams using the default format codecs and initialize the codecs
157 video_st = NULL;
158 audio_st = NULL;
159 if (oc->oformat->video_codec != AV_CODEC_ID_NONE && info.has_video)
160 // Add video stream
161 video_st = add_video_stream();
162
163 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE && info.has_audio)
164 // Add audio stream
165 audio_st = add_audio_stream();
166}
167
168// Set video export options
169void 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) {
170 // Set the video options
171 if (codec.length() > 0) {
172 const AVCodec *new_codec;
173 // Check if the codec selected is a hardware accelerated codec
174#if USE_HW_ACCEL
175#if defined(__linux__)
176 if (strstr(codec.c_str(), "_vaapi") != NULL) {
177 new_codec = avcodec_find_encoder_by_name(codec.c_str());
178 hw_en_on = 1;
179 hw_en_supported = 1;
180 hw_en_av_pix_fmt = AV_PIX_FMT_VAAPI;
181 hw_en_av_device_type = AV_HWDEVICE_TYPE_VAAPI;
182 } else if (strstr(codec.c_str(), "_nvenc") != NULL) {
183 new_codec = avcodec_find_encoder_by_name(codec.c_str());
184 hw_en_on = 1;
185 hw_en_supported = 1;
186 hw_en_av_pix_fmt = AV_PIX_FMT_CUDA;
187 hw_en_av_device_type = AV_HWDEVICE_TYPE_CUDA;
188 } else {
189 new_codec = avcodec_find_encoder_by_name(codec.c_str());
190 hw_en_on = 0;
191 hw_en_supported = 0;
192 }
193#elif defined(_WIN32)
194 if (strstr(codec.c_str(), "_dxva2") != NULL) {
195 new_codec = avcodec_find_encoder_by_name(codec.c_str());
196 hw_en_on = 1;
197 hw_en_supported = 1;
198 hw_en_av_pix_fmt = AV_PIX_FMT_DXVA2_VLD;
199 hw_en_av_device_type = AV_HWDEVICE_TYPE_DXVA2;
200 } else if (strstr(codec.c_str(), "_nvenc") != NULL) {
201 new_codec = avcodec_find_encoder_by_name(codec.c_str());
202 hw_en_on = 1;
203 hw_en_supported = 1;
204 hw_en_av_pix_fmt = AV_PIX_FMT_CUDA;
205 hw_en_av_device_type = AV_HWDEVICE_TYPE_CUDA;
206 } else {
207 new_codec = avcodec_find_encoder_by_name(codec.c_str());
208 hw_en_on = 0;
209 hw_en_supported = 0;
210 }
211#elif defined(__APPLE__)
212 if (strstr(codec.c_str(), "_videotoolbox") != NULL) {
213 new_codec = avcodec_find_encoder_by_name(codec.c_str());
214 hw_en_on = 1;
215 hw_en_supported = 1;
216 hw_en_av_pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX;
217 hw_en_av_device_type = AV_HWDEVICE_TYPE_VIDEOTOOLBOX;
218 } else {
219 new_codec = avcodec_find_encoder_by_name(codec.c_str());
220 hw_en_on = 0;
221 hw_en_supported = 0;
222 }
223#else // unknown OS
224 new_codec = avcodec_find_encoder_by_name(codec.c_str());
225#endif //__linux__/_WIN32/__APPLE__
226#else // USE_HW_ACCEL
227 new_codec = avcodec_find_encoder_by_name(codec.c_str());
228#endif // USE_HW_ACCEL
229 if (new_codec == NULL)
230 throw InvalidCodec("A valid video codec could not be found for this file.", path);
231 else {
232 // Set video codec
233 info.vcodec = new_codec->name;
234 }
235 }
236 if (fps.num > 0) {
237 // Set frames per second (if provided)
238 info.fps.num = fps.num;
239 info.fps.den = fps.den;
240
241 // Set the timebase (inverse of fps)
244 }
245 if (width >= 1)
246 info.width = width;
247 if (height >= 1)
248 info.height = height;
249 if (pixel_ratio.num > 0) {
250 info.pixel_ratio.num = pixel_ratio.num;
251 info.pixel_ratio.den = pixel_ratio.den;
252 }
253 if (bit_rate >= 1000) // bit_rate is the bitrate in b/s
254 info.video_bit_rate = bit_rate;
255 if ((bit_rate >= 0) && (bit_rate < 256)) // bit_rate is the bitrate in crf
256 info.video_bit_rate = bit_rate;
257
258 info.interlaced_frame = interlaced;
259 info.top_field_first = top_field_first;
260
261 // Calculate the DAR (display aspect ratio)
263
264 // Reduce size fraction
265 size.Reduce();
266
267 // Set the ratio based on the reduced fraction
268 info.display_ratio.num = size.num;
269 info.display_ratio.den = size.den;
270
272 "FFmpegWriter::SetVideoOptions (" + codec + ")",
273 "width", width, "height", height,
274 "size.num", size.num, "size.den", size.den,
275 "fps.num", fps.num, "fps.den", fps.den);
276
277 // Enable / Disable video
278 info.has_video = has_video;
279}
280
281// Set video export options (overloaded function)
282void FFmpegWriter::SetVideoOptions(std::string codec, int width, int height, Fraction fps, int bit_rate) {
283 // Call full signature with some default parameters
285 true, codec, fps, width, height,
286 openshot::Fraction(1, 1), false, true, bit_rate
287 );
288}
289
290
291// Set audio export options
292void FFmpegWriter::SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, ChannelLayout channel_layout, int bit_rate) {
293 // Set audio options
294 if (codec.length() > 0) {
295 const AVCodec *new_codec = avcodec_find_encoder_by_name(codec.c_str());
296 if (new_codec == NULL)
297 throw InvalidCodec("A valid audio codec could not be found for this file.", path);
298 else {
299 // Set audio codec
300 info.acodec = new_codec->name;
301 }
302 }
303 if (sample_rate > 7999)
304 info.sample_rate = sample_rate;
305 if (channels > 0)
306 info.channels = channels;
307 if (bit_rate > 999)
308 info.audio_bit_rate = bit_rate;
309 info.channel_layout = channel_layout;
310
311 // init resample options (if zero)
312 if (original_sample_rate == 0)
313 original_sample_rate = info.sample_rate;
314 if (original_channels == 0)
315 original_channels = info.channels;
316
318 "FFmpegWriter::SetAudioOptions (" + codec + ")",
319 "sample_rate", sample_rate,
320 "channels", channels,
321 "bit_rate", bit_rate);
322
323 // Enable / Disable audio
324 info.has_audio = has_audio;
325}
326
327
328// Set audio export options (overloaded function)
329void FFmpegWriter::SetAudioOptions(std::string codec, int sample_rate, int bit_rate) {
330 // Call full signature with some default parameters
332 true, codec, sample_rate, 2,
334 );
335}
336
337
338// Set custom options (some codecs accept additional params)
339void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string value) {
340 // Declare codec context
341 AVCodecContext *c = NULL;
342 AVStream *st = NULL;
343 std::stringstream convert(value);
344
345 if (info.has_video && stream == VIDEO_STREAM && video_st) {
346 st = video_st;
347 // Get codec context
348 c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec_ctx);
349 // Was a codec / stream found?
350 if (c) {
352 c->field_order = info.top_field_first ? AV_FIELD_TT : AV_FIELD_BB;
353 // We only use these two version and ignore AV_FIELD_TB and AV_FIELD_BT
354 // Otherwise we would need to change the whole export window
355 }
356 }
357 } else if (info.has_audio && stream == AUDIO_STREAM && audio_st) {
358 st = audio_st;
359 // Get codec context
360 c = AV_GET_CODEC_PAR_CONTEXT(st, audio_codec_ctx);
361 } else
362 throw NoStreamsFound("The stream was not found. Be sure to call PrepareStreams() first.", path);
363
364 // Init AVOption
365 const AVOption *option = NULL;
366
367 // Was a codec / stream found?
368 if (c)
369 // Find AVOption (if it exists)
370 option = AV_OPTION_FIND(c->priv_data, name.c_str());
371
372 // Was option found?
373 if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
374 name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" ||
375 name == "rc_buffer_size" || name == "crf" || name == "cqp" || name == "qp" || name == "allow_b_frames")) {
376 // Check for specific named options
377 if (name == "g")
378 // Set gop_size
379 convert >> c->gop_size;
380
381 else if (name == "qmin")
382 // Minimum quantizer
383 convert >> c->qmin;
384
385 else if (name == "qmax")
386 // Maximum quantizer
387 convert >> c->qmax;
388
389 else if (name == "max_b_frames")
390 // Maximum number of B-frames between non-B-frames
391 convert >> c->max_b_frames;
392
393 else if (name == "allow_b_frames")
394 // Preserve configured B-frames for codecs that support them.
395 // Values: 1/true/yes/on to enable, everything else disables.
396 allow_b_frames = (value == "1" || value == "true" || value == "yes" || value == "on");
397
398 else if (name == "mb_decision")
399 // Macroblock decision mode
400 convert >> c->mb_decision;
401
402 else if (name == "level")
403 // Set codec level
404 convert >> c->level;
405
406 else if (name == "profile")
407 // Set codec profile
408 convert >> c->profile;
409
410 else if (name == "slices")
411 // Indicates number of picture subdivisions
412 convert >> c->slices;
413
414 else if (name == "rc_min_rate")
415 // Minimum bitrate
416 convert >> c->rc_min_rate;
417
418 else if (name == "rc_max_rate")
419 // Maximum bitrate
420 convert >> c->rc_max_rate;
421
422 else if (name == "rc_buffer_size")
423 // Buffer size
424 convert >> c->rc_buffer_size;
425
426 else if (name == "cqp") {
427 // encode quality and special settings like lossless
428#if USE_HW_ACCEL
429 if (hw_en_on) {
430 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63
431 } else
432#endif // USE_HW_ACCEL
433 {
434 switch (c->codec_id) {
435#if (LIBAVCODEC_VERSION_MAJOR >= 58)
436 // FFmpeg 4.0+
437 case AV_CODEC_ID_AV1 :
438 c->bit_rate = 0;
439 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63
440 break;
441#endif
442 case AV_CODEC_ID_VP8 :
443 c->bit_rate = 10000000;
444 av_opt_set_int(c->priv_data, "qp", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63
445 break;
446 case AV_CODEC_ID_VP9 :
447 c->bit_rate = 0; // Must be zero!
448 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63
449 if (std::stoi(value) == 0) {
450 av_opt_set(c->priv_data, "preset", "veryslow", 0);
451 av_opt_set_int(c->priv_data, "lossless", 1, 0);
452 }
453 break;
454 case AV_CODEC_ID_H264 :
455 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51
456 if (std::stoi(value) == 0) {
457 av_opt_set(c->priv_data, "preset", "veryslow", 0);
458 c->pix_fmt = PIX_FMT_YUV444P; // no chroma subsampling
459 }
460 break;
461 case AV_CODEC_ID_HEVC :
462 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51
463 if (std::stoi(value) == 0) {
464 av_opt_set(c->priv_data, "preset", "veryslow", 0);
465 av_opt_set_int(c->priv_data, "lossless", 1, 0);
466 }
467 break;
468 default:
469 // For all other codecs assume a range of 0-63
470 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63
471 c->bit_rate = 0;
472 }
473 }
474 } else if (name == "crf") {
475 // encode quality and special settings like lossless
476#if USE_HW_ACCEL
477 if (hw_en_on) {
478 double mbs = 15000000.0;
479 if (info.video_bit_rate > 0) {
480 if (info.video_bit_rate > 42) {
481 mbs = 380000.0;
482 }
483 else {
484 mbs *= std::pow(0.912,info.video_bit_rate);
485 }
486 }
487 c->bit_rate = (int)(mbs);
488 } else
489#endif // USE_HW_ACCEL
490 {
491 switch (c->codec_id) {
492#if (LIBAVCODEC_VERSION_MAJOR >= 58)
493 // FFmpeg 4.0+
494 case AV_CODEC_ID_AV1 :
495 c->bit_rate = 0;
496 // AV1 only supports "crf" quality values
497 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
498 break;
499#endif
500 case AV_CODEC_ID_VP8 :
501 c->bit_rate = 10000000;
502 av_opt_set_int(c->priv_data, "crf", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63
503 break;
504 case AV_CODEC_ID_VP9 :
505 c->bit_rate = 0; // Must be zero!
506 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 63), 0); // 0-63
507 if (std::stoi(value) == 0) {
508 av_opt_set(c->priv_data, "preset", "veryslow", 0);
509 av_opt_set_int(c->priv_data, "lossless", 1, 0);
510 }
511 break;
512 case AV_CODEC_ID_H264 :
513 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51
514 if (std::stoi(value) == 0) {
515 av_opt_set(c->priv_data, "preset", "veryslow", 0);
516 c->pix_fmt = PIX_FMT_YUV444P; // no chroma subsampling
517 }
518 break;
519 case AV_CODEC_ID_HEVC :
520 if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) {
521 av_opt_set_int(c->priv_data, "preset", 7, 0);
522 av_opt_set_int(c->priv_data, "forced-idr",1,0);
523 av_opt_set_int(c->priv_data, "qp",std::min(std::stoi(value), 51),0);
524 }
525 else {
526 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51
527 }
528 if (std::stoi(value) == 0) {
529 av_opt_set(c->priv_data, "preset", "veryslow", 0);
530 av_opt_set_int(c->priv_data, "lossless", 1, 0);
531 }
532 break;
533 default:
534 // If this codec doesn't support crf calculate a bitrate
535 // TODO: find better formula
536 double mbs = 15000000.0;
537 if (info.video_bit_rate > 0) {
538 if (info.video_bit_rate > 42) {
539 mbs = 380000.0;
540 } else {
541 mbs *= std::pow(0.912, info.video_bit_rate);
542 }
543 }
544 c->bit_rate = (int) (mbs);
545 }
546 }
547 } else if (name == "qp") {
548 // encode quality and special settings like lossless
549#if (LIBAVCODEC_VERSION_MAJOR >= 58)
550 // FFmpeg 4.0+
551 switch (c->codec_id) {
552 case AV_CODEC_ID_AV1 :
553 c->bit_rate = 0;
554 if (strstr(info.vcodec.c_str(), "svtav1") != NULL) {
555 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0);
556 }
557 else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) {
558 // Set number of tiles to a fixed value
559 // TODO Let user choose number of tiles
560 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0);
561 }
562 else if (strstr(info.vcodec.c_str(), "aom") != NULL) {
563 // Set number of tiles to a fixed value
564 // TODO Let user choose number of tiles
565 // libaom doesn't have qp only crf
566 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
567 }
568 else {
569 av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0);
570 }
571 case AV_CODEC_ID_HEVC :
572 c->bit_rate = 0;
573 if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) {
574 av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),51), 0);
575 av_opt_set_int(c->priv_data, "preset", 7, 0);
576 av_opt_set_int(c->priv_data, "forced-idr",1,0);
577 }
578 break;
579 }
580#endif // FFmpeg 4.0+
581 } else {
582 // Set AVOption
583 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
584 }
585
587 "FFmpegWriter::SetOption (" + (std::string)name + ")",
588 "stream == VIDEO_STREAM", stream == VIDEO_STREAM);
589
590 // Muxing dictionary is not part of the codec context.
591 // Just reusing SetOption function to set popular multiplexing presets.
592 } else if (name == "muxing_preset") {
593 if (value == "mp4_faststart") {
594 // 'moov' box to the beginning; only for MOV, MP4
595 av_dict_set(&mux_dict, "movflags", "faststart", 0);
596 } else if (value == "mp4_fragmented") {
597 // write selfcontained fragmented file, minimum length of the fragment 8 sec; only for MOV, MP4
598 av_dict_set(&mux_dict, "movflags", "frag_keyframe", 0);
599 av_dict_set(&mux_dict, "min_frag_duration", "8000000", 0);
600 }
601 } else {
602 throw InvalidOptions("The option is not valid for this codec.", path);
603 }
604
605}
606
608bool FFmpegWriter::IsValidCodec(std::string codec_name) {
609 // Initialize FFMpeg, and register all formats and codecs
611
612 // Find the codec (if any)
613 return avcodec_find_encoder_by_name(codec_name.c_str()) != NULL;
614}
615
616// Find an output format the same way the writer does (by extension), or by short name
617static const AVOutputFormat* find_output_format(std::string format_name) {
618 if (!format_name.empty() && format_name[0] == '.')
619 format_name.erase(0, 1);
620 if (format_name.empty())
621 return nullptr;
622 const AVOutputFormat* format = av_guess_format(NULL, ("file." + format_name).c_str(), NULL);
623 if (!format)
624 format = av_guess_format(format_name.c_str(), NULL, NULL);
625 return format;
626}
627
628// Visit every registered encoder
629template<typename Visitor>
630static void for_each_encoder(Visitor visit) {
631#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 10, 100)
632 void* iterator = nullptr;
633 const AVCodec* codec = nullptr;
634 while ((codec = av_codec_iterate(&iterator)))
635#else
636 const AVCodec* codec = nullptr;
637 while ((codec = av_codec_next(codec)))
638#endif
639 if (av_codec_is_encoder(codec))
640 visit(codec);
641}
642
643// Visit every registered output format (muxer)
644template<typename Visitor>
645static void for_each_muxer(Visitor visit) {
646#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100)
647 void* iterator = nullptr;
648 const AVOutputFormat* format = nullptr;
649 while ((format = av_muxer_iterate(&iterator)))
650#else
651 AVOutputFormat* format = nullptr;
652 while ((format = av_oformat_next(format)))
653#endif
654 visit(format);
655}
656
657// Name of the encoder FFmpeg would pick for a codec ID (or an empty string)
658static std::string default_encoder_name(AVCodecID codec_id) {
659 if (codec_id == AV_CODEC_ID_NONE)
660 return "";
661 const AVCodec* codec = avcodec_find_encoder(codec_id);
662 return codec ? codec->name : "";
663}
664
665// Codecs FFmpeg uses for single image files (i.e. png, bmp, tiff), from its image2 format
666static const std::set<AVCodecID>& image_codec_ids() {
667 static const std::set<AVCodecID> ids = [] {
668 std::set<AVCodecID> found;
669 const AVOutputFormat* image2 = av_guess_format("image2", NULL, NULL);
670 if (!image2 || !image2->extensions)
671 return found;
672 std::stringstream extension_list(image2->extensions);
673 std::string extension;
674 while (std::getline(extension_list, extension, ',')) {
675 AVCodecID id = av_guess_codec(const_cast<AVOutputFormat*>(image2), NULL,
676 ("file." + extension).c_str(), NULL, AVMEDIA_TYPE_VIDEO);
677 if (id != AV_CODEC_ID_NONE)
678 found.insert(id);
679 }
680 return found;
681 }();
682 return ids;
683}
684
685static bool encoder_has_option(const AVCodec* codec, const char* name) {
686 if (!codec->priv_class)
687 return false;
688 const AVClass* priv_class = codec->priv_class;
689 return av_opt_find(&priv_class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ) != nullptr;
690}
691
692std::string FFmpegWriter::GetEncoderInfo(std::string codec_name) {
694
695 Json::Value root;
696 const AVCodec* codec = avcodec_find_encoder_by_name(codec_name.c_str());
697 root["found"] = codec != nullptr;
698 if (!codec)
699 return root.toStyledString();
700
701 root["name"] = codec->name;
702 root["long_name"] = codec->long_name ? codec->long_name : "";
703 const char* media_type = av_get_media_type_string(codec->type);
704 root["type"] = media_type ? media_type : "unknown";
705
706 bool hardware = false;
707#ifdef AV_CODEC_CAP_HARDWARE
708 hardware = hardware || (codec->capabilities & AV_CODEC_CAP_HARDWARE);
709#endif
710#ifdef AV_CODEC_CAP_HYBRID
711 hardware = hardware || (codec->capabilities & AV_CODEC_CAP_HYBRID);
712#endif
713 root["hardware"] = hardware;
714#ifdef AV_CODEC_CAP_EXPERIMENTAL
715 root["experimental"] = (codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) != 0;
716#else
717 root["experimental"] = (codec->capabilities & CODEC_CAP_EXPERIMENTAL) != 0;
718#endif
719
720 // Lossless-only codecs (FLAC, PCM, FFV1) ignore the bit rate
721 const AVCodecDescriptor* descriptor = avcodec_descriptor_get(codec->id);
722 root["lossless"] = descriptor && (descriptor->props & AV_CODEC_PROP_LOSSLESS);
723 root["lossy"] = descriptor && (descriptor->props & AV_CODEC_PROP_LOSSY);
724 // Every frame is a picture (i.e. ProRes, DNxHD, MJPEG), which suits editing over delivery
725 root["intra_only"] = descriptor && (descriptor->props & AV_CODEC_PROP_INTRA_ONLY);
726 // Writes single image files (i.e. png, bmp, tiff)
727 root["image"] = image_codec_ids().count(codec->id) > 0;
728 // The codec this encoder writes (i.e. "h264" for libx264 and h264_nvenc)
729 root["codec"] = avcodec_get_name(codec->id);
730
731 Json::Value quality_options(Json::arrayValue);
732 for (const char* option : {"crf", "qp", "cq", "global_quality"})
733 if (encoder_has_option(codec, option))
734 quality_options.append(option);
735 root["quality_options"] = quality_options;
736
737 root["sample_rates"] = Json::Value(Json::nullValue);
738 root["channel_layouts"] = Json::Value(Json::nullValue);
739 root["sample_formats"] = Json::Value(Json::nullValue);
740 root["pixel_formats"] = Json::Value(Json::nullValue);
741
742 std::unique_ptr<AVCodecContext, void(*)(AVCodecContext*)> context(
743 avcodec_alloc_context3(codec),
744 [](AVCodecContext* value) { avcodec_free_context(&value); });
745 if (!context)
746 return root.toStyledString();
747
748 try {
749 if (codec->type == AVMEDIA_TYPE_AUDIO) {
750 if (const int* rates = ffmpeg_codec_sample_rates(codec, context.get())) {
751 Json::Value values(Json::arrayValue);
752 for (int i = 0; rates[i] != 0; i++)
753 values.append(rates[i]);
754 root["sample_rates"] = values;
755 }
756#if HAVE_CH_LAYOUT
757 if (const AVChannelLayout* layouts = ffmpeg_codec_ch_layouts(codec, context.get())) {
758 Json::Value values(Json::arrayValue);
759 for (int i = 0; av_channel_layout_check(&layouts[i]); i++)
760 if (layouts[i].order == AV_CHANNEL_ORDER_NATIVE)
761 values.append((Json::UInt64) layouts[i].u.mask);
762 root["channel_layouts"] = values;
763 }
764#else
765 if (codec->channel_layouts) {
766 Json::Value values(Json::arrayValue);
767 for (int i = 0; codec->channel_layouts[i] != 0; i++)
768 values.append((Json::UInt64) codec->channel_layouts[i]);
769 root["channel_layouts"] = values;
770 }
771#endif
772 if (const AVSampleFormat* formats = ffmpeg_codec_sample_fmts(codec, context.get())) {
773 Json::Value values(Json::arrayValue);
774 for (int i = 0; formats[i] != AV_SAMPLE_FMT_NONE; i++) {
775 const char* name = av_get_sample_fmt_name(formats[i]);
776 if (name)
777 values.append(name);
778 }
779 root["sample_formats"] = values;
780 }
781 } else if (codec->type == AVMEDIA_TYPE_VIDEO) {
782 if (const AVPixelFormat* formats = ffmpeg_codec_pix_fmts(codec, context.get())) {
783 Json::Value values(Json::arrayValue);
784 for (int i = 0; formats[i] != AV_PIX_FMT_NONE; i++) {
785 const char* name = av_get_pix_fmt_name(formats[i]);
786 if (name)
787 values.append(name);
788 }
789 root["pixel_formats"] = values;
790 }
791 }
792 } catch (const InvalidCodec&) {
793 // Leave the remaining lists unrestricted; the writer reports real failures on open
794 }
795
796 return root.toStyledString();
797}
798
799std::string FFmpegWriter::GetFormatInfo(std::string format_name) {
801
802 Json::Value root;
803 const AVOutputFormat* format = find_output_format(format_name);
804 root["found"] = format != nullptr;
805 if (!format)
806 return root.toStyledString();
807
808 root["name"] = format->name;
809 root["long_name"] = format->long_name ? format->long_name : "";
810 Json::Value extensions(Json::arrayValue);
811 std::stringstream extension_list(format->extensions ? format->extensions : "");
812 std::string extension;
813 while (std::getline(extension_list, extension, ','))
814 if (!extension.empty())
815 extensions.append(extension);
816 root["extensions"] = extensions;
817 root["default_audio_codec"] = default_encoder_name(format->audio_codec);
818 root["default_video_codec"] = default_encoder_name(format->video_codec);
819 return root.toStyledString();
820}
821
824
825 Json::Value formats(Json::arrayValue);
826 std::set<std::string> listed;
827 for_each_muxer([&](const AVOutputFormat* format) {
828 std::stringstream extension_list(format->extensions ? format->extensions : "");
829 std::string extension;
830 while (std::getline(extension_list, extension, ',')) {
831 // Some formats list extensions with stray spaces (i.e. " A64")
832 extension.erase(0, extension.find_first_not_of(" \t"));
833 extension.erase(extension.find_last_not_of(" \t") + 1);
834 // Extensions match without case, so list each once, in lower case
835 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
836 if (extension.empty() || listed.count(extension))
837 continue;
838 // The writer picks its format from the file extension, so only list extensions
839 // that pick this format (several formats can claim the same extension)
840 if (av_guess_format(NULL, ("file." + extension).c_str(), NULL) != format)
841 continue;
842 listed.insert(extension);
843 Json::Value row;
844 row["extension"] = extension;
845 row["name"] = format->name;
846 row["long_name"] = format->long_name ? format->long_name : "";
847 row["default_audio_codec"] = default_encoder_name(format->audio_codec);
848 row["default_video_codec"] = default_encoder_name(format->video_codec);
849 formats.append(row);
850 }
851 });
852 return formats.toStyledString();
853}
854
855std::string FFmpegWriter::GetEncoders(std::string media_type, std::string format_name) {
857
858 Json::Value encoders(Json::arrayValue);
859 const AVOutputFormat* format = nullptr;
860 if (!format_name.empty()) {
861 format = find_output_format(format_name);
862 if (!format)
863 return encoders.toStyledString();
864 }
865
866 for_each_encoder([&](const AVCodec* codec) {
867 const char* type = av_get_media_type_string(codec->type);
868 if (!type || media_type != type)
869 return;
870 // Keep encoders FFmpeg can't rule out; the writer reports real failures on open
871 if (format && avformat_query_codec(format, codec->id, FF_COMPLIANCE_NORMAL) == 0)
872 return;
873 Json::Value encoder;
874 encoder["name"] = codec->name;
875 encoder["long_name"] = codec->long_name ? codec->long_name : "";
876 encoders.append(encoder);
877 });
878 return encoders.toStyledString();
879}
880
881int FFmpegWriter::IsCodecSupportedByFormat(std::string format_name, std::string codec_name) {
883
884 const AVOutputFormat* format = find_output_format(format_name);
885 const AVCodec* codec = avcodec_find_encoder_by_name(codec_name.c_str());
886 if (!format || !codec)
887 return 0;
888 const int result = avformat_query_codec(format, codec->id, FF_COMPLIANCE_NORMAL);
889 if (result < 0)
890 return -1;
891 return result > 0 ? 1 : 0;
892}
893
894// FFmpeg messages logged on a thread running Test() (other threads print as usual)
896 int level;
897 std::string text;
898};
899static thread_local std::vector<TestLogLine>* test_log = nullptr;
900
901static void test_log_callback(void* avcl, int level, const char* fmt, va_list vl) {
902 if (!test_log) {
903 av_log_default_callback(avcl, level, fmt, vl);
904 return;
905 }
906 if (level > AV_LOG_WARNING)
907 return;
908 char line[1024];
909 vsnprintf(line, sizeof(line), fmt, vl);
910 std::string text(line);
911 while (!text.empty() && (text.back() == '\n' || text.back() == '\r' || text.back() == ' '))
912 text.pop_back();
913 if (text.empty())
914 return;
915 // Name the component (i.e. "mp3: ...") instead of FFmpeg's "[mp3 @ 0x...]" prefix
916 AVClass* av_class = avcl ? *(AVClass**)avcl : nullptr;
917 if (av_class && av_class->item_name)
918 text = std::string(av_class->item_name(avcl)) + ": " + text;
919 test_log->push_back({level, text});
920}
921
922// Check the current settings without writing a file
923std::string FFmpegWriter::Test() {
924 auto start = std::chrono::steady_clock::now();
925 std::vector<TestLogLine> messages;
926 std::string stage;
927 std::string error;
928
929 testing = true;
930 test_log = &messages;
931 av_log_set_callback(test_log_callback);
932
933 try {
934 if (!prepare_streams)
936 if (info.has_video && video_st) {
937 stage = "video";
938 open_video(oc, video_st);
939 }
940 if (info.has_audio && audio_st) {
941 stage = "audio";
942 open_audio(oc, audio_st);
943 }
944 stage = "header";
945 WriteHeader();
946 av_write_trailer(oc);
947 write_trailer = true;
948 stage = "";
949 } catch (const ExceptionBase& e) {
950 error = e.what();
951 } catch (const std::exception& e) {
952 error = e.what();
953 }
954
955 // Release everything (the test output, encoders, and any hardware device)
956 if (oc && oc->pb && !(oc->oformat->flags & AVFMT_NOFILE)) {
957 uint8_t* buffer = NULL;
958 avio_close_dyn_buf(oc->pb, &buffer);
959 av_free(buffer);
960 oc->pb = NULL;
961 }
962 if (video_st)
963 close_video(oc, video_st);
964 if (audio_st)
965 close_audio(oc, audio_st);
966 video_codec_ctx = NULL;
967 audio_codec_ctx = NULL;
968 video_st = NULL;
969 audio_st = NULL;
970 if (oc) {
971 avformat_free_context(oc);
972 oc = NULL;
973 }
974 if (mux_dict)
975 av_dict_free(&mux_dict);
976 av_log_set_callback(av_log_default_callback);
977 test_log = nullptr;
978 is_open = false;
979 prepare_streams = false;
980 write_header = false;
981 write_trailer = false;
982 testing = false;
983
984 // FFmpeg's own explanation (its last error) is clearer than the exception text
985 std::string message = error;
986 if (!error.empty()) {
987 for (auto line = messages.rbegin(); line != messages.rend(); ++line) {
988 if (line->level <= AV_LOG_ERROR) {
989 message = line->text;
990 break;
991 }
992 }
993 }
994
995 Json::Value root;
996 root["ok"] = error.empty();
997 root["stage"] = stage;
998 root["message"] = message;
999 root["log"] = Json::Value(Json::arrayValue);
1000 for (const auto& line : messages)
1001 root["log"].append(line.text);
1002 root["elapsed_ms"] = (Json::Int64) std::chrono::duration_cast<std::chrono::milliseconds>(
1003 std::chrono::steady_clock::now() - start).count();
1004 return root.toStyledString();
1005}
1006
1007// Prepare & initialize streams and open codecs
1009 if (!info.has_audio && !info.has_video)
1010 throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
1011
1013 "FFmpegWriter::PrepareStreams [" + path + "]",
1014 "info.has_audio", info.has_audio,
1015 "info.has_video", info.has_video);
1016
1017 // Initialize the streams (i.e. add the streams)
1018 initialize_streams();
1019
1020 // Mark as 'prepared'
1021 prepare_streams = true;
1022}
1023
1024// Write the file header (after the options are set)
1026 if (!info.has_audio && !info.has_video)
1027 throw InvalidOptions("No video or audio options have been set. You must set has_video or has_audio (or both).", path);
1028
1029 // Open the output file, if needed
1030 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1031 if (testing) {
1032 // Test() writes the header to memory instead
1033 if (avio_open_dyn_buf(&oc->pb) < 0)
1034 throw OutOfMemory("Could not allocate memory for the test output.", path);
1035 } else if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
1036 throw InvalidFile("Could not open or write file.", path);
1037 }
1038
1039 // Force the output filename (which doesn't always happen for some reason)
1040 AV_SET_FILENAME(oc, path.c_str());
1041
1042 // Add general metadata (if any)
1043 for (auto iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1044 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1045 }
1046
1047 // Set multiplexing parameters (only for MP4/MOV containers)
1048 AVDictionary *dict = NULL;
1049 if (mux_dict) {
1050 av_dict_copy(&dict, mux_dict, 0);
1051 }
1052
1053 // Write the stream header
1054 if (avformat_write_header(oc, &dict) != 0) {
1056 "FFmpegWriter::WriteHeader (avformat_write_header)");
1057 throw InvalidFile("Could not write header to file.", path);
1058 };
1059
1060 // Free multiplexing dictionaries sets
1061 if (dict) av_dict_free(&dict);
1062 if (mux_dict) av_dict_free(&mux_dict);
1063
1064 // Mark as 'written'
1065 write_header = true;
1066
1067 Logger::Instance()->AppendDebugMethod("FFmpegWriter::WriteHeader");
1068}
1069
1070// Add a frame to the queue waiting to be encoded.
1071void FFmpegWriter::WriteFrame(std::shared_ptr<openshot::Frame> frame) {
1072 // Check for open reader (or throw exception)
1073 if (!is_open)
1074 throw WriterClosed("The FFmpegWriter is closed. Call Open() before calling this method.", path);
1075
1077 "FFmpegWriter::WriteFrame",
1078 "frame->number", frame->number,
1079 "is_writing", is_writing);
1080
1081 // Write frames to video file
1082 write_frame(frame);
1083
1084 // Keep track of the last frame added
1085 last_frame = frame;
1086}
1087
1088void FFmpegWriter::WriteFrameAt(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) {
1089 // Check for open reader (or throw exception)
1090 if (!is_open)
1091 throw WriterClosed("The FFmpegWriter is closed. Call Open() before calling this method.", path);
1092
1093 if (frame_number < 1) {
1094 frame_number = 1;
1095 }
1096
1098 "FFmpegWriter::WriteFrameAt",
1099 "frame->number", frame->number,
1100 "output_frame_number", frame_number,
1101 "is_writing", is_writing);
1102
1103 const int64_t previous_video_timestamp = video_timestamp;
1104 if (info.has_video && video_st && video_codec_ctx) {
1105 video_timestamp = av_rescale_q(
1106 frame_number - 1,
1107 av_make_q(info.fps.den, info.fps.num),
1108 video_codec_ctx->time_base);
1109 }
1110
1111 write_frame(frame);
1112
1113 if (!(info.has_video && video_st && video_codec_ctx)) {
1114 video_timestamp = previous_video_timestamp;
1115 }
1116
1117 last_frame = frame;
1118}
1119
1120// Write all frames in the queue to the video file.
1121void FFmpegWriter::write_frame(std::shared_ptr<Frame> frame) {
1122 // Flip writing flag
1123 is_writing = true;
1124
1125 // Create blank exception
1126 bool has_error_encoding_video = false;
1127
1128 // Process audio frame
1129 if (info.has_audio && audio_st)
1130 write_audio_packets(false, frame);
1131
1132 // Process video frame
1133 if (info.has_video && video_st)
1134 process_video_packet(frame);
1135
1136 if (info.has_video && video_st) {
1137 // Does this frame's AVFrame still exist
1138 if (av_frames.count(frame)) {
1139 // Get AVFrame
1140 AVFrame *frame_final = av_frames[frame];
1141
1142 // Write frame to video file
1143 if (!write_video_packet(frame, frame_final)) {
1144 has_error_encoding_video = true;
1145 }
1146
1147 // Deallocate buffer and AVFrame
1148 av_freep(&(frame_final->data[0]));
1149 AV_FREE_FRAME(&frame_final);
1150 av_frames.erase(frame);
1151 }
1152 }
1153
1154 // Done writing
1155 is_writing = false;
1156
1157 // Raise exception from main thread
1158 if (has_error_encoding_video)
1159 throw ErrorEncodingVideo("Error while writing raw video frame", -1);
1160}
1161
1162// Write a block of frames from a reader
1163void FFmpegWriter::WriteFrame(ReaderBase *reader, int64_t start, int64_t length) {
1165 "FFmpegWriter::WriteFrame (from Reader)",
1166 "start", start,
1167 "length", length);
1168
1169 // Loop through each frame (and encoded it)
1170 for (int64_t number = start; number <= length; number++) {
1171 // Get the frame
1172 std::shared_ptr<Frame> f = reader->GetFrame(number);
1173
1174 // Encode frame
1175 WriteFrame(f);
1176 }
1177}
1178
1179// Write the file trailer (after all frames are written)
1181 // Process final audio frame (if any)
1182 if (info.has_audio && audio_st)
1183 write_audio_packets(true, NULL);
1184
1185 // Flush encoders (who sometimes hold on to frames)
1186 flush_encoders();
1187
1188 if (info.has_audio && audio_st && audio_codec_ctx && audio_timestamp > 0) {
1189 audio_st->duration = av_rescale_q(
1190 audio_timestamp,
1191 audio_codec_ctx->time_base,
1192 audio_st->time_base);
1193 }
1194
1195 /* write the trailer, if any. The trailer must be written
1196 * before you close the CodecContexts open when you wrote the
1197 * header; otherwise write_trailer may try to use memory that
1198 * was freed on av_codec_close() */
1199 av_write_trailer(oc);
1200
1201 // Mark as 'written'
1202 write_trailer = true;
1203
1204 Logger::Instance()->AppendDebugMethod("FFmpegWriter::WriteTrailer");
1205}
1206
1207// Flush encoders
1208void FFmpegWriter::flush_encoders() {
1209 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)
1210 return;
1211#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1212 // FFmpeg < 4.0
1213 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)
1214 return;
1215#else
1216 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)
1217 return;
1218#endif
1219
1220 // FLUSH VIDEO ENCODER
1221 if (info.has_video) {
1222 for (;;) {
1223
1224 // Increment PTS (in frames and scaled to the codec's timebase)
1225 video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
1226
1227#if IS_FFMPEG_3_2
1228 AVPacket* pkt = av_packet_alloc();
1229#else
1230 AVPacket* pkt;
1231 av_init_packet(pkt);
1232#endif
1233 pkt->data = NULL;
1234 pkt->size = 0;
1235
1236 /* encode the image */
1237 int got_packet = 0;
1238 int error_code = 0;
1239
1240#if IS_FFMPEG_3_2
1241 // Encode video packet (latest version of FFmpeg)
1242 error_code = avcodec_send_frame(video_codec_ctx, NULL);
1243 got_packet = 0;
1244 while (error_code >= 0) {
1245 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
1246 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
1247 got_packet = 0;
1248 // Write packet
1249 avcodec_flush_buffers(video_codec_ctx);
1250 break;
1251 }
1252 if (pkt->duration <= 0) {
1253 pkt->duration = av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
1254 }
1255 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
1256 pkt->stream_index = video_st->index;
1257 error_code = av_interleaved_write_frame(oc, pkt);
1258 }
1259#else // IS_FFMPEG_3_2
1260
1261 // Encode video packet (older than FFmpeg 3.2)
1262 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
1263
1264#endif // IS_FFMPEG_3_2
1265
1266 if (error_code < 0) {
1268 "FFmpegWriter::flush_encoders ERROR ["
1269 + av_err2string(error_code) + "]",
1270 "error_code", error_code);
1271 }
1272 if (!got_packet) {
1273 break;
1274 }
1275
1276 // set the timestamp
1277 if (pkt->duration <= 0) {
1278 pkt->duration = av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
1279 }
1280 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
1281 pkt->stream_index = video_st->index;
1282
1283 // Write packet
1284 error_code = av_interleaved_write_frame(oc, pkt);
1285 if (error_code < 0) {
1287 "FFmpegWriter::flush_encoders ERROR ["
1288 + av_err2string(error_code) + "]",
1289 "error_code", error_code);
1290 }
1291 }
1292 }
1293
1294 // FLUSH AUDIO ENCODER
1295 if (info.has_audio) {
1296 for (;;) {
1297#if IS_FFMPEG_3_2
1298 AVPacket* pkt = av_packet_alloc();
1299#else
1300 AVPacket* pkt;
1301 av_init_packet(pkt);
1302#endif
1303 pkt->data = NULL;
1304 pkt->size = 0;
1305 pkt->pts = pkt->dts = audio_timestamp;
1306
1307 /* encode the image */
1308 int error_code = 0;
1309 int got_packet = 0;
1310#if IS_FFMPEG_3_2
1311 if (!audio_codec_ctx->codec || !(audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
1312 av_packet_free(&pkt);
1313 break;
1314 }
1315 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
1316 if (error_code < 0 && error_code != AVERROR_EOF) {
1318 "FFmpegWriter::flush_encoders ERROR ["
1319 + av_err2string(error_code) + "]",
1320 "error_code", error_code);
1321 }
1322 while (true) {
1323 error_code = avcodec_receive_packet(audio_codec_ctx, pkt);
1324 if (error_code == AVERROR(EAGAIN) || error_code == AVERROR_EOF) {
1325 got_packet = 0;
1326 break;
1327 }
1328 if (error_code < 0) {
1330 "FFmpegWriter::flush_encoders ERROR ["
1331 + av_err2string(error_code) + "]",
1332 "error_code", error_code);
1333 got_packet = 0;
1334 break;
1335 }
1336
1337 got_packet = 1;
1338 if (pkt->pts == AV_NOPTS_VALUE) {
1339 pkt->pts = audio_timestamp;
1340 }
1341 if (pkt->dts == AV_NOPTS_VALUE) {
1342 pkt->dts = pkt->pts;
1343 }
1344 if (pkt->duration <= 0) {
1345 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
1346 }
1347 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1348 pkt->stream_index = audio_st->index;
1349 pkt->flags |= AV_PKT_FLAG_KEY;
1350
1351 error_code = av_interleaved_write_frame(oc, pkt);
1352 if (error_code < 0) {
1354 "FFmpegWriter::flush_encoders ERROR ["
1355 + av_err2string(error_code) + "]",
1356 "error_code", error_code);
1357 }
1358 // Flushing emits already-submitted samples; do not advance the input clock.
1359 AV_FREE_PACKET(pkt);
1360 }
1361 av_packet_free(&pkt);
1362 break;
1363#else
1364 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
1365 if (error_code < 0) {
1367 "FFmpegWriter::flush_encoders ERROR ["
1368 + av_err2string(error_code) + "]",
1369 "error_code", error_code);
1370 }
1371 if (!got_packet) {
1372 break;
1373 }
1374
1375 // Legacy encoding API timestamp fallback.
1376 pkt->pts = pkt->dts = audio_timestamp;
1377 if (pkt->duration <= 0) {
1378 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
1379 }
1380
1381 // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
1382 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1383
1384 // set stream
1385 pkt->stream_index = audio_st->index;
1386 pkt->flags |= AV_PKT_FLAG_KEY;
1387
1388 // Write packet
1389 error_code = av_interleaved_write_frame(oc, pkt);
1390 if (error_code < 0) {
1392 "FFmpegWriter::flush_encoders ERROR ["
1393 + av_err2string(error_code) + "]",
1394 "error_code", error_code);
1395 }
1396
1397 // Increment PTS by duration of packet
1398 audio_timestamp += pkt->duration;
1399
1400 // deallocate memory for packet
1401 AV_FREE_PACKET(pkt);
1402#endif
1403 }
1404 }
1405
1406}
1407
1408// Close the video codec
1409void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
1410{
1411#if USE_HW_ACCEL
1412 if (hw_en_on && hw_en_supported) {
1413 if (hw_device_ctx) {
1414 av_buffer_unref(&hw_device_ctx);
1415 hw_device_ctx = NULL;
1416 }
1417 }
1418#endif // USE_HW_ACCEL
1419
1420 // Free any previous memory allocations
1421 if (video_codec_ctx != nullptr) {
1422 AV_FREE_CONTEXT(video_codec_ctx);
1423 av_free(video_codec_ctx);
1424 }
1425}
1426
1427// Close the audio codec
1428void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
1429{
1430 // Clear buffers
1431 delete[] samples;
1432 delete[] audio_outbuf;
1433 delete[] audio_encoder_buffer;
1434 samples = NULL;
1435 audio_outbuf = NULL;
1436 audio_encoder_buffer = NULL;
1437
1438 // Deallocate resample buffer
1439 if (avr) {
1440 SWR_CLOSE(avr);
1441 SWR_FREE(&avr);
1442 avr = NULL;
1443 }
1444
1445 if (avr_planar) {
1446 SWR_CLOSE(avr_planar);
1447 SWR_FREE(&avr_planar);
1448 avr_planar = NULL;
1449 }
1450
1451 // Free any previous memory allocations
1452 if (audio_codec_ctx != nullptr) {
1453 AV_FREE_CONTEXT(audio_codec_ctx);
1454 av_free(audio_codec_ctx);
1455 }
1456}
1457
1458// Close the writer
1460 // Write trailer (if needed). A failed header leaves nothing to finish.
1461 if (write_header && !write_trailer)
1462 WriteTrailer();
1463
1464 // Close each codec
1465 if (video_st)
1466 close_video(oc, video_st);
1467 if (audio_st)
1468 close_audio(oc, audio_st);
1469
1470 // Remove single software scaler
1471 if (img_convert_ctx)
1472 sws_freeContext(img_convert_ctx);
1473
1474 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1475 /* close the output file */
1476 avio_close(oc->pb);
1477 }
1478
1479 // Reset frame counters
1480 video_timestamp = 0;
1481 audio_timestamp = 0;
1482
1483 // Free the context which frees the streams too
1484 avformat_free_context(oc);
1485 oc = NULL;
1486
1487 // Close writer
1488 is_open = false;
1489 prepare_streams = false;
1490 write_header = false;
1491 write_trailer = false;
1492
1493 Logger::Instance()->AppendDebugMethod("FFmpegWriter::Close");
1494}
1495
1496// Add an AVFrame to the cache
1497void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1498 // Add AVFrame to map (if it does not already exist)
1499 if (!av_frames.count(frame)) {
1500 // Add av_frame
1501 av_frames[frame] = av_frame;
1502 } else {
1503 // Do not add, and deallocate this AVFrame
1504 AV_FREE_FRAME(&av_frame);
1505 }
1506}
1507
1508// Add an audio output stream
1509AVStream *FFmpegWriter::add_audio_stream() {
1510 // Find the audio codec
1511 const AVCodec *codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1512 if (codec == NULL)
1513 throw InvalidCodec("A valid audio codec could not be found for this file.", path);
1514
1515 // Free any previous memory allocations
1516 if (audio_codec_ctx != nullptr) {
1517 AV_FREE_CONTEXT(audio_codec_ctx);
1518 }
1519
1520 // Create a new audio stream
1521 AVStream* st = avformat_new_stream(oc, codec);
1522 if (!st)
1523 throw OutOfMemory("Could not allocate memory for the audio stream.", path);
1524
1525 // Allocate a new codec context for the stream
1526 ALLOC_CODEC_CTX(audio_codec_ctx, codec, st)
1527#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1528 st->codecpar->codec_id = codec->id;
1529#endif
1530 AVCodecContext* c = audio_codec_ctx;
1531
1532 c->codec_id = codec->id;
1533 c->codec_type = AVMEDIA_TYPE_AUDIO;
1534
1535 // Set the sample parameters
1536 c->bit_rate = info.audio_bit_rate;
1537#if !HAVE_CH_LAYOUT
1538 c->channels = info.channels;
1539#endif
1540
1541 // Set valid sample rate (or throw error)
1542 if (const int* supported_rates = ffmpeg_codec_sample_rates(codec, c)) {
1543 int i;
1544 for (i = 0; supported_rates[i] != 0; i++)
1545 if (info.sample_rate == supported_rates[i]) {
1546 // Set the valid sample rate
1547 c->sample_rate = info.sample_rate;
1548 break;
1549 }
1550 if (supported_rates[i] == 0)
1551 throw InvalidSampleRate("An invalid sample rate was detected for this codec.", path);
1552 } else
1553 // Set sample rate
1554 c->sample_rate = info.sample_rate;
1555
1556 c->time_base = AVRational{1, c->sample_rate};
1557 st->time_base = c->time_base;
1558
1559 uint64_t channel_layout = info.channel_layout;
1560#if HAVE_CH_LAYOUT
1561 // Set a valid number of channels (or throw error)
1562 AVChannelLayout ch_layout = {};
1563 if (av_channel_layout_from_mask(&ch_layout, info.channel_layout) < 0)
1564 throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1565 if (const AVChannelLayout* codec_layouts = ffmpeg_codec_ch_layouts(codec, c)) {
1566 int i;
1567 for (i = 0; av_channel_layout_check(&codec_layouts[i]); i++)
1568 if (av_channel_layout_compare(&ch_layout, &codec_layouts[i]) == 0) {
1569 // Set valid channel layout
1570 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1571 break;
1572 }
1573 if (!av_channel_layout_check(&codec_layouts[i]))
1574 throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1575 } else {
1576 // Set valid channel layout
1577 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1578 }
1579#else
1580 // Preserve validation on FFmpeg versions using legacy channel masks.
1581 if (codec->channel_layouts) {
1582 const uint64_t* layout = codec->channel_layouts;
1583 while (*layout != 0 && *layout != channel_layout)
1584 ++layout;
1585 if (*layout == 0)
1586 throw InvalidChannels("An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1587 }
1588 c->channel_layout = channel_layout;
1589#endif
1590
1591 // Choose a valid sample_fmt
1592 if (const AVSampleFormat* codec_fmts = ffmpeg_codec_sample_fmts(codec, c)) {
1593 for (int i = 0; codec_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1594 // Set sample format to 1st valid format (and then exit loop)
1595 c->sample_fmt = codec_fmts[i];
1596 break;
1597 }
1598 }
1599 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1600 // Default if no sample formats found
1601 c->sample_fmt = AV_SAMPLE_FMT_S16;
1602 }
1603
1604 // some formats want stream headers to be separate
1605 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1606#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1607 // FFmpeg 3.0+
1608 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1609#else
1610 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1611#endif
1612
1614
1615 int nb_channels;
1616 const char* nb_channels_label;
1617 const char* channel_layout_label;
1618
1619#if HAVE_CH_LAYOUT
1620 nb_channels = c->ch_layout.nb_channels;
1621 channel_layout = c->ch_layout.u.mask;
1622 nb_channels_label = "c->ch_layout.nb_channels";
1623 channel_layout_label = "c->ch_layout.u.mask";
1624#else
1625 nb_channels = c->channels;
1626 nb_channels_label = "c->channels";
1627 channel_layout_label = "c->channel_layout";
1628#endif
1629
1631 "FFmpegWriter::add_audio_stream",
1632 "c->codec_id", c->codec_id,
1633 "c->bit_rate", c->bit_rate,
1634 nb_channels_label, nb_channels,
1635 "c->sample_fmt", c->sample_fmt,
1636 channel_layout_label, channel_layout,
1637 "c->sample_rate", c->sample_rate);
1638
1639 return st;
1640}
1641
1642// Add a video output stream
1643AVStream *FFmpegWriter::add_video_stream() {
1644 // Find the video codec
1645 const AVCodec *codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1646 if (codec == NULL)
1647 throw InvalidCodec("A valid video codec could not be found for this file.", path);
1648
1649 // Free any previous memory allocations
1650 if (video_codec_ctx != nullptr) {
1651 AV_FREE_CONTEXT(video_codec_ctx);
1652 }
1653
1654 // Create a new video stream
1655 AVStream* st = avformat_new_stream(oc, codec);
1656 if (!st)
1657 throw OutOfMemory("Could not allocate memory for the video stream.", path);
1658
1659 // Allocate a new codec context for the stream
1660 ALLOC_CODEC_CTX(video_codec_ctx, codec, st)
1661#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1662 st->codecpar->codec_id = codec->id;
1663#endif
1664
1665 AVCodecContext* c = video_codec_ctx;
1666
1667 c->codec_id = codec->id;
1668 c->codec_type = AVMEDIA_TYPE_VIDEO;
1669
1670 // Set sample aspect ratio
1671 c->sample_aspect_ratio.num = info.pixel_ratio.num;
1672 c->sample_aspect_ratio.den = info.pixel_ratio.den;
1673
1674 /* Init video encoder options */
1675 if (info.video_bit_rate >= 1000
1676#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1677 && c->codec_id != AV_CODEC_ID_AV1
1678#endif
1679 ) {
1680 c->bit_rate = info.video_bit_rate;
1681 if (info.video_bit_rate >= 1500000) {
1682 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1683 c->qmin = 2;
1684 c->qmax = 30;
1685 }
1686 }
1687 // Here should be the setting for low fixed bitrate
1688 // Defaults are used because mpeg2 otherwise had problems
1689 } else {
1690 // Check if codec supports crf or qp
1691 switch (c->codec_id) {
1692#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1693 // FFmpeg 4.0+
1694 case AV_CODEC_ID_AV1 :
1695 // TODO: Set `crf` or `qp` according to bitrate, as bitrate is not supported by these encoders yet.
1696 if (info.video_bit_rate >= 1000) {
1697 c->bit_rate = 0;
1698 if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1699 int calculated_quality = 35;
1700 if (info.video_bit_rate < 500000) calculated_quality = 50;
1701 if (info.video_bit_rate > 5000000) calculated_quality = 10;
1702 av_opt_set_int(c->priv_data, "crf", calculated_quality, 0);
1703 info.video_bit_rate = calculated_quality;
1704 } else {
1705 int calculated_quality = 50;
1706 if (info.video_bit_rate < 500000) calculated_quality = 60;
1707 if (info.video_bit_rate > 5000000) calculated_quality = 15;
1708 av_opt_set_int(c->priv_data, "qp", calculated_quality, 0);
1709 info.video_bit_rate = calculated_quality;
1710 } // medium
1711 }
1712 if (strstr(info.vcodec.c_str(), "svtav1") != NULL) {
1713 av_opt_set_int(c->priv_data, "preset", 6, 0);
1714 av_opt_set_int(c->priv_data, "forced-idr",1,0);
1715 }
1716 else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) {
1717 av_opt_set_int(c->priv_data, "speed", 7, 0);
1718 av_opt_set_int(c->priv_data, "tile-rows", 2, 0);
1719 av_opt_set_int(c->priv_data, "tile-columns", 4, 0);
1720 }
1721 else if (strstr(info.vcodec.c_str(), "aom") != NULL) {
1722 // Set number of tiles to a fixed value
1723 // TODO: Allow user to chose their own number of tiles
1724 av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows
1725 av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns
1726 av_opt_set_int(c->priv_data, "row-mt", 1, 0); // use multiple cores
1727 av_opt_set_int(c->priv_data, "cpu-used", 3, 0); // default is 1, usable is 4
1728 }
1729 //break;
1730#endif
1731 case AV_CODEC_ID_VP9 :
1732 case AV_CODEC_ID_HEVC :
1733 case AV_CODEC_ID_VP8 :
1734 case AV_CODEC_ID_H264 :
1735 if (info.video_bit_rate < 40) {
1736 c->qmin = 0;
1737 c->qmax = 63;
1738 } else {
1739 c->qmin = info.video_bit_rate - 5;
1740 c->qmax = 63;
1741 }
1742 break;
1743 default:
1744 // Here should be the setting for codecs that don't support crf
1745 // For now defaults are used
1746 break;
1747 }
1748 }
1749
1750 //TODO: Implement variable bitrate feature (which actually works). This implementation throws
1751 //invalid bitrate errors and rc buffer underflow errors, etc...
1752 //c->rc_min_rate = info.video_bit_rate;
1753 //c->rc_max_rate = info.video_bit_rate;
1754 //c->rc_buffer_size = FFMAX(c->rc_max_rate, 15000000) * 112L / 15000000 * 16384;
1755 //if ( !c->rc_initial_buffer_occupancy )
1756 // c->rc_initial_buffer_occupancy = c->rc_buffer_size * 3/4;
1757
1758 /* resolution must be a multiple of two */
1759 // TODO: require /2 height and width
1760 c->width = info.width;
1761 c->height = info.height;
1762
1763 /* time base: this is the fundamental unit of time (in seconds) in terms
1764 of which frame timestamps are represented. for fixed-fps content,
1765 timebase should be 1/framerate and timestamp increments should be
1766 identically 1. */
1767 c->time_base.num = info.video_timebase.num;
1768 c->time_base.den = info.video_timebase.den;
1769// AVCodecContext->framerate was added in FFmpeg 2.6
1770#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1771 c->framerate = av_inv_q(c->time_base);
1772#endif
1773 st->avg_frame_rate = av_inv_q(c->time_base);
1774 st->r_frame_rate = av_inv_q(c->time_base);
1775 st->time_base.num = info.video_timebase.num;
1776 st->time_base.den = info.video_timebase.den;
1777
1778 c->gop_size = 12; /* TODO: add this to "info"... emit one intra frame every twelve frames at most */
1779 c->max_b_frames = 10;
1780 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1781 /* just for testing, we also add B frames */
1782 c->max_b_frames = 2;
1783 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1784 /* Needed to avoid using macroblocks in which some coeffs overflow.
1785 This does not happen with normal video, it just happens here as
1786 the motion of the chroma plane does not match the luma plane. */
1787 c->mb_decision = 2;
1788 // some formats want stream headers to be separate
1789 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1790#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1791 // FFmpeg 3.0+
1792 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1793#else
1794 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1795#endif
1796
1797 // Find all supported pixel formats for this codec
1798 if (const PixelFormat* supported_pixel_formats = ffmpeg_codec_pix_fmts(codec, c)) {
1799 while (*supported_pixel_formats != PIX_FMT_NONE) {
1800 // Assign the 1st valid pixel format (if one is missing)
1801 if (c->pix_fmt == PIX_FMT_NONE)
1802 c->pix_fmt = *supported_pixel_formats;
1803 ++supported_pixel_formats;
1804 }
1805 }
1806
1807 // Codec doesn't have any pix formats?
1808 if (c->pix_fmt == PIX_FMT_NONE) {
1809 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1810 // Raw video should use RGB24
1811 c->pix_fmt = PIX_FMT_RGB24;
1812
1813#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1814 // FFmpeg < 4.0
1815 if (strcmp(oc->oformat->name, "gif") != 0)
1816 // If not GIF format, skip the encoding process
1817 // Set raw picture flag (so we don't encode this video)
1818 oc->oformat->flags |= AVFMT_RAWPICTURE;
1819#endif
1820 } else {
1821 // Set the default codec
1822 c->pix_fmt = PIX_FMT_YUV420P;
1823 }
1824 }
1825
1828 "FFmpegWriter::add_video_stream ("
1829 + (std::string)oc->oformat->name + " : "
1830 + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")",
1831 "c->codec_id", c->codec_id,
1832 "c->bit_rate", c->bit_rate,
1833 "c->pix_fmt", c->pix_fmt,
1834 "oc->oformat->flags", oc->oformat->flags);
1835 return st;
1836}
1837
1838// open audio codec
1839void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1840 const AVCodec *codec;
1841 AV_GET_CODEC_FROM_STREAM(st, audio_codec_ctx)
1842
1843 // Audio encoding does not typically use more than 2 threads (most codecs use 1 thread)
1844 audio_codec_ctx->thread_count = std::min(FF_AUDIO_NUM_PROCESSORS, 2);
1845
1846 // Find the audio encoder
1847 codec = avcodec_find_encoder_by_name(info.acodec.c_str());
1848 if (!codec)
1849 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1850 if (!codec)
1851 throw InvalidCodec("Could not find codec", path);
1852
1853 // Init options
1854 AVDictionary *opts = NULL;
1855 av_dict_set(&opts, "strict", "experimental", 0);
1856
1857 // Open the codec
1858 if (avcodec_open2(audio_codec_ctx, codec, &opts) < 0)
1859 throw InvalidCodec("Could not open audio codec", path);
1860 AV_COPY_PARAMS_FROM_CONTEXT(st, audio_codec_ctx);
1861
1862 // Free options
1863 av_dict_free(&opts);
1864
1865 // Calculate the size of the input frame (i..e how many samples per packet), and the output buffer
1866 // TODO: Ugly hack for PCM codecs (will be removed ASAP with new PCM support to compute the input frame size in samples
1867 if (audio_codec_ctx->frame_size <= 1) {
1868 // No frame size found... so calculate
1869 audio_input_frame_size = 50000 / info.channels;
1870
1871 int s = AV_FIND_DECODER_CODEC_ID(st);
1872 switch (s) {
1873 case AV_CODEC_ID_PCM_S16LE:
1874 case AV_CODEC_ID_PCM_S16BE:
1875 case AV_CODEC_ID_PCM_U16LE:
1876 case AV_CODEC_ID_PCM_U16BE:
1877 audio_input_frame_size >>= 1;
1878 break;
1879 default:
1880 break;
1881 }
1882 } else {
1883 // Set frame size based on the codec
1884 audio_input_frame_size = audio_codec_ctx->frame_size;
1885 }
1886
1887 // Set the initial frame size (since it might change during resampling)
1888 initial_audio_input_frame_size = audio_input_frame_size;
1889
1890 // Allocate array for samples
1891 samples = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
1892
1893 // Set audio output buffer (used to store the encoded audio)
1894 audio_outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
1895 audio_outbuf = new uint8_t[audio_outbuf_size];
1896
1897 // Set audio packet encoding buffer
1898 audio_encoder_buffer_size = AUDIO_PACKET_ENCODING_SIZE;
1899 audio_encoder_buffer = new uint8_t[audio_encoder_buffer_size];
1900
1901 // Add audio metadata (if any)
1902 for (std::map<std::string, std::string>::iterator iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
1903 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1904 }
1905
1907 "FFmpegWriter::open_audio",
1908 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1909 "audio_input_frame_size", audio_input_frame_size,
1911}
1912
1913// open video codec
1914void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1915 const AVCodec *codec;
1916 AV_GET_CODEC_FROM_STREAM(st, video_codec_ctx)
1917
1918 // Set number of threads equal to number of processors (not to exceed 16, FFmpeg doesn't recommend more than 16)
1919 video_codec_ctx->thread_count = std::min(FF_VIDEO_NUM_PROCESSORS, 16);
1920
1921#if USE_HW_ACCEL
1922 if (hw_en_on && hw_en_supported) {
1923 //char *dev_hw = NULL;
1924 char adapter[256];
1925 char *adapter_ptr = NULL;
1926 int adapter_num;
1927 // Use the hw device given in the environment variable HW_EN_DEVICE_SET or the default if not set
1929 std::clog << "Encoding Device Nr: " << adapter_num << "\n";
1930 if (adapter_num < 3 && adapter_num >=0) {
1931#if defined(__linux__)
1932 snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128);
1933 // Maybe 127 is better because the first card would be 1?!
1934 adapter_ptr = adapter;
1935#elif defined(_WIN32) || defined(__APPLE__)
1936 adapter_ptr = NULL;
1937#endif
1938 }
1939 else {
1940 adapter_ptr = NULL; // Just to be sure
1941 }
1942// Check if it is there and writable
1943#if defined(__linux__)
1944 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1945#elif defined(_WIN32) || defined(__APPLE__)
1946 if( adapter_ptr != NULL ) {
1947#endif
1949 "Encode Device present using device",
1950 "adapter", adapter_num);
1951 }
1952 else {
1953 adapter_ptr = NULL; // use default
1955 "Encode Device not present, using default");
1956 }
1957 if (av_hwdevice_ctx_create(&hw_device_ctx,
1958 hw_en_av_device_type, adapter_ptr, NULL, 0) < 0)
1959 {
1961 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1962 info.vcodec.c_str(), -1);
1963 throw InvalidCodec("Could not create hwdevice", path);
1964 }
1965 }
1966#endif // USE_HW_ACCEL
1967
1968 /* find the video encoder */
1969 codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
1970 if (!codec)
1971 codec = avcodec_find_encoder(AV_FIND_DECODER_CODEC_ID(st));
1972 if (!codec)
1973 throw InvalidCodec("Could not find codec", path);
1974
1975 /* Legacy behavior: force max_b_frames to 0 for many codecs.
1976 * This can be disabled via SetOption(VIDEO_STREAM, "allow_b_frames", "1"). */
1977 if (!allow_b_frames && video_codec_ctx->max_b_frames &&
1978 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 &&
1979 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO &&
1980 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1981 video_codec_ctx->max_b_frames = 0;
1982
1983 // Init options
1984 AVDictionary *opts = NULL;
1985 av_dict_set(&opts, "strict", "experimental", 0);
1986
1987#if USE_HW_ACCEL
1989 video_codec_ctx->pix_fmt = hw_en_av_pix_fmt;
1990
1991 // for the list of possible options, see the list of codec-specific options:
1992 // e.g. ffmpeg -h encoder=h264_vaapi or ffmpeg -h encoder=hevc_vaapi
1993 // and "man ffmpeg-codecs"
1994
1995 // For VAAPI, it is safer to explicitly set rc_mode instead of relying on auto-selection
1996 // which is ffmpeg version-specific.
1997 if (hw_en_av_pix_fmt == AV_PIX_FMT_VAAPI) {
1998 int64_t qp;
1999 if (av_opt_get_int(video_codec_ctx->priv_data, "qp", 0, &qp) != 0 || qp == 0) {
2000 // unless "qp" was set for CQP, switch to VBR RC mode
2001 av_opt_set(video_codec_ctx->priv_data, "rc_mode", "VBR", 0);
2002
2003 // In the current state (ffmpeg-4.2-4 libva-mesa-driver-19.1.5-1) to use VBR,
2004 // one has to specify both bit_rate and maxrate, otherwise a small low quality file is generated on Intel iGPU).
2005 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
2006 }
2007 }
2008
2009 switch (video_codec_ctx->codec_id) {
2010 case AV_CODEC_ID_H264:
2011 video_codec_ctx->max_b_frames = 0; // At least this GPU doesn't support b-frames
2012 video_codec_ctx->profile = AV_PROFILE_H264_CONSTRAINED_BASELINE;
2013 av_opt_set(video_codec_ctx->priv_data, "preset", "slow", 0);
2014 av_opt_set(video_codec_ctx->priv_data, "tune", "zerolatency", 0);
2015 av_opt_set(video_codec_ctx->priv_data, "vprofile", "baseline", AV_OPT_SEARCH_CHILDREN);
2016 break;
2017 case AV_CODEC_ID_HEVC:
2018 // tested to work with defaults
2019 break;
2020 case AV_CODEC_ID_VP9:
2021 // tested to work with defaults
2022 break;
2023 default:
2025 "No codec-specific options defined for this codec. HW encoding may fail",
2026 "codec_id", video_codec_ctx->codec_id);
2027 break;
2028 }
2029
2030 // set hw_frames_ctx for encoder's AVCodecContext
2031 int err;
2032 if ((err = set_hwframe_ctx(video_codec_ctx, hw_device_ctx, info.width, info.height)) < 0)
2033 {
2035 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
2036 "width", info.width,
2037 "height", info.height,
2038 av_err2string(err), -1);
2039 }
2040 }
2041#endif // USE_HW_ACCEL
2042
2043// Set libx265 hvc1 tag (for Apple playback compatibility).
2044#if USE_HW_ACCEL
2045 if (!(hw_en_on && hw_en_supported) && video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
2046 video_codec_ctx->codec_tag = MKTAG('h', 'v', 'c', '1');
2047 }
2048#else
2049 if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
2050 video_codec_ctx->codec_tag = MKTAG('h', 'v', 'c', '1');
2051 }
2052#endif
2053
2054 /* open the codec */
2055 if (avcodec_open2(video_codec_ctx, codec, &opts) < 0)
2056 throw InvalidCodec("Could not open video codec", path);
2057 AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx);
2058 st->avg_frame_rate = av_make_q(info.fps.num, info.fps.den);
2059 st->r_frame_rate = av_make_q(info.fps.num, info.fps.den);
2060
2061 // Free options
2062 av_dict_free(&opts);
2063
2064 // Add video metadata (if any)
2065 for (auto iter = info.metadata.begin(); iter != info.metadata.end(); ++iter) {
2066 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
2067 }
2068
2070 "FFmpegWriter::open_video",
2071 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
2072
2073}
2074
2075// write all queued frames' audio to the video file
2076void FFmpegWriter::write_audio_packets(bool is_final, std::shared_ptr<openshot::Frame> frame) {
2077 if (!frame && !is_final)
2078 return;
2079
2080 // Init audio buffers / variables
2081 int total_frame_samples = 0;
2082 int frame_position = 0;
2083 int channels_in_frame = 0;
2084 int sample_rate_in_frame = 0;
2085 int samples_in_frame = 0;
2086 ChannelLayout channel_layout_in_frame = LAYOUT_MONO; // default channel layout
2087
2088 // Create a new array (to hold all float audio samples, for the current queued frames
2089 unsigned int all_queued_samples_size = sizeof(float) * AVCODEC_MAX_AUDIO_FRAME_SIZE;
2090 float *all_queued_samples = (float *) av_malloc(all_queued_samples_size);
2091 int16_t *all_resampled_samples = NULL;
2092 int16_t *final_samples_planar = NULL;
2093 int16_t *final_samples = NULL;
2094
2095 // Get audio sample array
2096 float *frame_samples_float = NULL;
2097
2098 // Get the audio details from this frame
2099 if (frame) {
2100 sample_rate_in_frame = frame->SampleRate();
2101 samples_in_frame = frame->GetAudioSamplesCount();
2102 channels_in_frame = frame->GetAudioChannelsCount();
2103 channel_layout_in_frame = frame->ChannelsLayout();
2104
2105 // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
2106 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
2107 }
2108
2109 // Calculate total samples
2110 total_frame_samples = samples_in_frame * channels_in_frame;
2111
2112 // Keep samples as floats, so float codecs (such as AAC) are not limited to
2113 // 16 bits or clipped early. Integer codecs are converted by the resampler.
2114 for (int s = 0; s < total_frame_samples; s++, frame_position++)
2115 all_queued_samples[frame_position] = frame_samples_float[s];
2116
2117 // Deallocate float array
2118 delete[] frame_samples_float;
2119
2120
2121 // Update total samples (since we've combined all queued frames)
2122 total_frame_samples = frame_position;
2123 int remaining_frame_samples = total_frame_samples;
2124 int samples_position = 0;
2125
2126
2128 "FFmpegWriter::write_audio_packets",
2129 "is_final", is_final,
2130 "total_frame_samples", total_frame_samples,
2131 "channel_layout_in_frame", channel_layout_in_frame,
2132 "channels_in_frame", channels_in_frame,
2133 "samples_in_frame", samples_in_frame,
2134 "LAYOUT_MONO", LAYOUT_MONO);
2135
2136 // Keep track of the original sample format
2137 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
2138
2139 AVFrame *audio_frame = NULL;
2140 if (!is_final) {
2141 // Create input frame (and allocate arrays)
2142 audio_frame = AV_ALLOCATE_FRAME();
2143 AV_RESET_FRAME(audio_frame);
2144 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
2145
2146 // Fill input frame with sample data
2147 int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_FLT, (uint8_t *) all_queued_samples, all_queued_samples_size, 0);
2148 if (error_code < 0) {
2150 "FFmpegWriter::write_audio_packets ERROR ["
2151 + av_err2string(error_code) + "]",
2152 "error_code", error_code);
2153 }
2154
2155 // Do not convert audio to planar format (yet). We need to keep everything interleaved at this point.
2156 switch (audio_codec_ctx->sample_fmt) {
2157 case AV_SAMPLE_FMT_FLTP: {
2158 output_sample_fmt = AV_SAMPLE_FMT_FLT;
2159 break;
2160 }
2161 case AV_SAMPLE_FMT_S32P: {
2162 output_sample_fmt = AV_SAMPLE_FMT_S32;
2163 break;
2164 }
2165 case AV_SAMPLE_FMT_S16P: {
2166 output_sample_fmt = AV_SAMPLE_FMT_S16;
2167 break;
2168 }
2169 case AV_SAMPLE_FMT_U8P: {
2170 output_sample_fmt = AV_SAMPLE_FMT_U8;
2171 break;
2172 }
2173 default: {
2174 // This is only here to silence unused-enum warnings
2175 break;
2176 }
2177 }
2178
2179 // Update total samples & input frame size (due to bigger or smaller data types)
2180 total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
2181 total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
2182
2183 // Create output frame (and allocate arrays)
2184 AVFrame *audio_converted = AV_ALLOCATE_FRAME();
2185 AV_RESET_FRAME(audio_converted);
2186 audio_converted->nb_samples = total_frame_samples / info.channels;
2187 av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
2188
2190 "FFmpegWriter::write_audio_packets (1st resampling)",
2191 "in_sample_fmt", AV_SAMPLE_FMT_FLT,
2192 "out_sample_fmt", output_sample_fmt,
2193 "in_sample_rate", sample_rate_in_frame,
2194 "out_sample_rate", info.sample_rate,
2195 "in_channels", channels_in_frame,
2196 "out_channels", info.channels);
2197
2198 // setup resample context
2199 if (!avr) {
2200 avr = SWR_ALLOC();
2201#if HAVE_CH_LAYOUT
2202 AVChannelLayout in_chlayout = ffmpeg_default_channel_layout(channels_in_frame);
2203 AVChannelLayout out_chlayout = ffmpeg_default_channel_layout(info.channels);
2204 if (channel_layout_in_frame > 0) {
2205 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
2206 }
2207 if (info.channel_layout > 0) {
2208 av_channel_layout_from_mask(&out_chlayout, info.channel_layout);
2209 }
2210 av_opt_set_chlayout(avr, "in_chlayout", &in_chlayout, 0);
2211 av_opt_set_chlayout(avr, "out_chlayout", &out_chlayout, 0);
2212#else
2213 av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
2214 av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
2215 av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
2216 av_opt_set_int(avr, "out_channels", info.channels, 0);
2217#endif
2218 av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
2219 av_opt_set_int(avr, "out_sample_fmt", output_sample_fmt, 0); // planar not allowed here
2220 av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
2221 av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
2222 if (channels_in_frame == 1 && info.channels == 2) {
2223 // FFmpeg's default mono to stereo mix lowers each side by 3 dB. Copy
2224 // mono to both sides at full level, like media players do.
2225 const double mono_to_stereo[2] = { 1.0, 1.0 };
2226#if USE_SW
2227 swr_set_matrix(avr, mono_to_stereo, 1);
2228#else
2229 avresample_set_matrix(avr, mono_to_stereo, 1);
2230#endif
2231 }
2232 SWR_INIT(avr);
2233 }
2234 // Convert audio samples
2235 int nb_samples = SWR_CONVERT(
2236 avr, // audio resample context
2237 audio_converted->data, // output data pointers
2238 audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
2239 audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
2240 audio_frame->data, // input data pointers
2241 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
2242 audio_frame->nb_samples // number of input samples to convert
2243 );
2244
2245 // Resampling can buffer samples internally. Only copy samples actually
2246 // returned, not the estimated capacity (which can read past the buffer).
2247 if (nb_samples < 0)
2248 throw ErrorEncodingAudio("Could not resample audio", nb_samples);
2249 remaining_frame_samples = nb_samples * info.channels;
2250
2251 // Create a new array (to hold all resampled S16 audio samples)
2252 all_resampled_samples = (int16_t *) av_malloc(
2253 sizeof(int16_t) * nb_samples * info.channels
2254 * (av_get_bytes_per_sample(output_sample_fmt) /
2255 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2256 );
2257
2258 // Copy audio samples over original samples
2259 memcpy(all_resampled_samples, audio_converted->data[0],
2260 static_cast<size_t>(nb_samples)
2261 * info.channels
2262 * av_get_bytes_per_sample(output_sample_fmt));
2263
2264 // Remove converted audio
2265 av_freep(&(audio_frame->data[0]));
2266 AV_FREE_FRAME(&audio_frame);
2267 av_freep(&audio_converted->data[0]);
2268 AV_FREE_FRAME(&audio_converted);
2269 all_queued_samples = NULL; // this array cleared with above call
2270
2272 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
2273 "nb_samples", nb_samples,
2274 "remaining_frame_samples", remaining_frame_samples);
2275 }
2276
2277 if (is_final && remaining_frame_samples <= 0 && audio_input_position <= 0) {
2278 if (all_queued_samples) {
2279 av_freep(&all_queued_samples);
2280 }
2281 return;
2282 }
2283
2284 // Loop until no more samples
2285 while (remaining_frame_samples > 0 || is_final) {
2286 // Get remaining samples needed for this packet
2287 int remaining_packet_samples = (audio_input_frame_size * info.channels) - audio_input_position;
2288
2289 // Determine how many samples we need
2290 int diff = 0;
2291 if (remaining_frame_samples >= remaining_packet_samples) {
2292 diff = remaining_packet_samples;
2293 } else {
2294 diff = remaining_frame_samples;
2295 }
2296
2297 // Copy frame samples into the packet samples array
2298 if (!is_final)
2299 //TODO: Make this more sane
2300 memcpy(
2301 samples + (audio_input_position
2302 * (av_get_bytes_per_sample(output_sample_fmt) /
2303 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2304 ),
2305 all_resampled_samples + samples_position,
2306 static_cast<size_t>(diff)
2307 * av_get_bytes_per_sample(output_sample_fmt)
2308 );
2309
2310 // Increment counters
2311 audio_input_position += diff;
2312 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
2313 remaining_frame_samples -= diff;
2314
2315 // Do we have enough samples to proceed?
2316 if (audio_input_position < (audio_input_frame_size * info.channels) && !is_final)
2317 // Not enough samples to encode... so wait until the next frame
2318 break;
2319
2320 // Convert to planar (if needed by audio codec)
2321 AVFrame *frame_final = AV_ALLOCATE_FRAME();
2322 AV_RESET_FRAME(frame_final);
2323 const int frame_nb_samples = audio_input_position / info.channels;
2324 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
2326 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
2327 "in_sample_fmt", output_sample_fmt,
2328 "out_sample_fmt", audio_codec_ctx->sample_fmt,
2329 "in_sample_rate", info.sample_rate,
2330 "out_sample_rate", info.sample_rate,
2331 "in_channels", info.channels,
2332 "out_channels", info.channels
2333 );
2334
2335 // setup resample context
2336 if (!avr_planar) {
2337 avr_planar = SWR_ALLOC();
2338#if HAVE_CH_LAYOUT
2339 AVChannelLayout layout = ffmpeg_default_channel_layout(info.channels);
2340 if (info.channel_layout > 0) {
2341 av_channel_layout_from_mask(&layout, info.channel_layout);
2342 }
2343 av_opt_set_chlayout(avr_planar, "in_chlayout", &layout, 0);
2344 av_opt_set_chlayout(avr_planar, "out_chlayout", &layout, 0);
2345#else
2346 av_opt_set_int(avr_planar, "in_channel_layout", info.channel_layout, 0);
2347 av_opt_set_int(avr_planar, "out_channel_layout", info.channel_layout, 0);
2348 av_opt_set_int(avr_planar, "in_channels", info.channels, 0);
2349 av_opt_set_int(avr_planar, "out_channels", info.channels, 0);
2350#endif
2351 av_opt_set_int(avr_planar, "in_sample_fmt", output_sample_fmt, 0);
2352 av_opt_set_int(avr_planar, "out_sample_fmt", audio_codec_ctx->sample_fmt, 0); // planar not allowed here
2353 av_opt_set_int(avr_planar, "in_sample_rate", info.sample_rate, 0);
2354 av_opt_set_int(avr_planar, "out_sample_rate", info.sample_rate, 0);
2355 SWR_INIT(avr_planar);
2356 }
2357
2358 // Create input frame (and allocate arrays)
2359 audio_frame = AV_ALLOCATE_FRAME();
2360 AV_RESET_FRAME(audio_frame);
2361 audio_frame->nb_samples = audio_input_position / info.channels;
2362
2363 // Create a new array
2364 final_samples_planar = (int16_t *) av_malloc(
2365 sizeof(int16_t) * audio_frame->nb_samples * info.channels
2366 * (av_get_bytes_per_sample(output_sample_fmt) /
2367 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2368 );
2369
2370 // Copy audio into buffer for frame
2371 memcpy(final_samples_planar, samples,
2372 static_cast<size_t>(audio_frame->nb_samples)
2373 * info.channels
2374 * av_get_bytes_per_sample(output_sample_fmt));
2375
2376 // Fill input frame with sample data
2377 avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt,
2378 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
2379
2380 // Create output frame (and allocate arrays)
2381 frame_final->nb_samples = frame_nb_samples;
2382#if HAVE_CH_LAYOUT
2383 av_channel_layout_from_mask(&frame_final->ch_layout, info.channel_layout);
2384#else
2385 frame_final->channels = info.channels;
2386 frame_final->channel_layout = info.channel_layout;
2387#endif
2388 frame_final->format = audio_codec_ctx->sample_fmt;
2389 av_samples_alloc(frame_final->data, frame_final->linesize, info.channels,
2390 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
2391
2392 // Convert audio samples
2393 int nb_samples = SWR_CONVERT(
2394 avr_planar, // audio resample context
2395 frame_final->data, // output data pointers
2396 frame_final->linesize[0], // output plane size, in bytes. (0 if unknown)
2397 frame_final->nb_samples, // maximum number of samples that the output buffer can hold
2398 audio_frame->data, // input data pointers
2399 audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
2400 audio_frame->nb_samples // number of input samples to convert
2401 );
2402
2403 // Copy audio samples over original samples
2404 const auto copy_length = static_cast<size_t>(nb_samples)
2405 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
2406 * info.channels;
2407
2408 if (nb_samples > 0)
2409 memcpy(samples, frame_final->data[0], copy_length);
2410
2411 // deallocate AVFrame
2412 av_freep(&(audio_frame->data[0]));
2413 AV_FREE_FRAME(&audio_frame);
2414 all_queued_samples = NULL; // this array cleared with above call
2415
2417 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
2418 "nb_samples", nb_samples);
2419
2420 } else {
2421 // Create a new array
2422 const auto buf_size = static_cast<size_t>(audio_input_position)
2423 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
2424 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
2425 );
2426 final_samples = reinterpret_cast<int16_t*>(
2427 av_malloc(sizeof(int16_t) * buf_size));
2428
2429 // Copy audio into buffer for frame
2430 memcpy(final_samples, samples,
2431 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
2432
2433 // Init the nb_samples property
2434 frame_final->nb_samples = frame_nb_samples;
2435 frame_final->format = audio_codec_ctx->sample_fmt;
2436#if HAVE_CH_LAYOUT
2437 av_channel_layout_copy(&frame_final->ch_layout, &audio_codec_ctx->ch_layout);
2438#else
2439 frame_final->channels = audio_codec_ctx->channels;
2440 frame_final->channel_layout = audio_codec_ctx->channel_layout;
2441#endif
2442
2443 // Fill the final_frame AVFrame with audio (non planar)
2444#if HAVE_CH_LAYOUT
2445 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
2446#else
2447 int nb_channels = audio_codec_ctx->channels;
2448#endif
2449 avcodec_fill_audio_frame(frame_final, nb_channels,
2450 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
2451 audio_encoder_buffer_size, 0);
2452 }
2453
2454 // Set the AVFrame's PTS
2455 frame_final->pts = audio_timestamp;
2456
2457 // Init the packet
2458#if IS_FFMPEG_3_2
2459 AVPacket* pkt = av_packet_alloc();
2460#else
2461 AVPacket* pkt;
2462 av_init_packet(pkt);
2463 pkt->data = audio_encoder_buffer;
2464 pkt->size = audio_encoder_buffer_size;
2465#endif
2466
2467 // Set the packet's PTS prior to encoding
2468 pkt->pts = pkt->dts = audio_timestamp;
2469
2470 /* encode the audio samples */
2471 int got_packet_ptr = 0;
2472
2473#if IS_FFMPEG_3_2
2474 // Encode audio (latest version of FFmpeg)
2475 int error_code;
2476 int ret = 0;
2477 int frame_finished = 0;
2478 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
2479 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF
2480 && audio_codec_ctx->codec
2481 && (audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
2482 avcodec_send_frame(audio_codec_ctx, NULL);
2483 }
2484 else {
2485 if (ret >= 0)
2486 pkt->size = 0;
2487 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
2488 if (ret >= 0)
2489 frame_finished = 1;
2490 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
2491 ret = 0;
2492 }
2493 if (ret >= 0) {
2494 ret = frame_finished;
2495 }
2496 }
2497 if (!pkt->data && !frame_finished)
2498 {
2499 ret = -1;
2500 }
2501 got_packet_ptr = ret;
2502#else
2503 // Encode audio (older versions of FFmpeg)
2504 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
2505#endif
2506 /* if zero size, it means the image was buffered */
2507 if (error_code == 0 && got_packet_ptr > 0) {
2508
2509 // Delayed encoders (AAC) return timestamps for earlier input frames.
2510 // Preserve those timestamps, just as the flush path does.
2511 if (pkt->pts == AV_NOPTS_VALUE)
2512 pkt->pts = audio_timestamp;
2513 if (pkt->dts == AV_NOPTS_VALUE)
2514 pkt->dts = pkt->pts;
2515 if (pkt->duration <= 0) {
2516 pkt->duration = frame_nb_samples;
2517 }
2518
2519 // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase)
2520 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2521
2522 // set stream
2523 pkt->stream_index = audio_st->index;
2524 pkt->flags |= AV_PKT_FLAG_KEY;
2525
2526 /* write the compressed frame in the media file */
2527 error_code = av_interleaved_write_frame(oc, pkt);
2528 }
2529
2530 if (error_code < 0) {
2532 "FFmpegWriter::write_audio_packets ERROR ["
2533 + av_err2string(error_code) + "]",
2534 "error_code", error_code);
2535 }
2536
2537 // Count submitted samples per channel, including a partial final frame.
2538 audio_timestamp += frame_nb_samples;
2539
2540 // deallocate AVFrame
2541 av_freep(&(frame_final->data[0]));
2542 AV_FREE_FRAME(&frame_final);
2543
2544 // deallocate memory for packet
2545 AV_FREE_PACKET(pkt);
2546
2547 // Reset position
2548 audio_input_position = 0;
2549 is_final = false;
2550 }
2551
2552 // Delete arrays (if needed)
2553 if (all_resampled_samples) {
2554 av_freep(&all_resampled_samples);
2555 all_resampled_samples = NULL;
2556 }
2557 if (all_queued_samples) {
2558 av_freep(&all_queued_samples);
2559 all_queued_samples = NULL;
2560 }
2561}
2562
2563// Allocate an AVFrame object
2564AVFrame *FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int height, int *buffer_size, uint8_t *new_buffer) {
2565 // Create an RGB AVFrame
2566 AVFrame *new_av_frame = NULL;
2567
2568 // Allocate an AVFrame structure
2569 new_av_frame = AV_ALLOCATE_FRAME();
2570 if (new_av_frame == NULL)
2571 throw OutOfMemory("Could not allocate AVFrame", path);
2572
2573 // Determine required buffer size and allocate buffer
2574 *buffer_size = AV_GET_IMAGE_SIZE(pix_fmt, width, height);
2575
2576 // Create buffer (if not provided)
2577 if (!new_buffer) {
2578 int palette_padding = 0;
2579#ifdef AV_PIX_FMT_FLAG_PSEUDOPAL
2580 // Old av_frame_ref/av_image_copy still read a synthetic RGB8 palette,
2581 // even though av_image_get_buffer_size excludes it. Keep it readable
2582 // when the encoder takes a reference to this externally owned buffer.
2583 if (av_pix_fmt_desc_get(pix_fmt)->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
2584 palette_padding = 1024;
2585#endif
2586 // New Buffer
2587 new_buffer = (uint8_t *) av_malloc(*buffer_size + palette_padding);
2588 if (!new_buffer)
2589 throw OutOfMemory("Could not allocate video frame buffer", path);
2590 if (palette_padding)
2591 memset(new_buffer + *buffer_size, 0, palette_padding);
2592 // Attach buffer to AVFrame
2593 AV_COPY_PICTURE_DATA(new_av_frame, new_buffer, pix_fmt, width, height);
2594 new_av_frame->width = width;
2595 new_av_frame->height = height;
2596 new_av_frame->format = pix_fmt;
2597 }
2598
2599 // return AVFrame
2600 return new_av_frame;
2601}
2602
2603// process video frame
2604void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2605 // Source dimensions (RGBA)
2606 int src_w = frame->GetWidth();
2607 int src_h = frame->GetHeight();
2608
2609 // Skip empty frames (1×1)
2610 if (src_w == 1 && src_h == 1)
2611 return;
2612
2613 // Point persistent_src_frame->data to RGBA pixels
2614 const uchar* pixels = frame->GetPixels();
2615 if (!persistent_src_frame) {
2616 persistent_src_frame = av_frame_alloc();
2617 if (!persistent_src_frame)
2618 throw OutOfMemory("Could not allocate persistent_src_frame", path);
2619 persistent_src_frame->format = AV_PIX_FMT_RGBA;
2620 persistent_src_frame->width = src_w;
2621 persistent_src_frame->height = src_h;
2622 persistent_src_frame->linesize[0] = src_w * 4;
2623 }
2624 persistent_src_frame->data[0] = const_cast<uint8_t*>(
2625 reinterpret_cast<const uint8_t*>(pixels)
2626 );
2627
2628 // Prepare persistent_dst_frame + buffer on first use
2629 if (!persistent_dst_frame) {
2630 persistent_dst_frame = av_frame_alloc();
2631 if (!persistent_dst_frame)
2632 throw OutOfMemory("Could not allocate persistent_dst_frame", path);
2633
2634 // Decide destination pixel format: NV12 if HW accel is on, else encoder’s pix_fmt
2635 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2636#if USE_HW_ACCEL
2637 if (hw_en_on && hw_en_supported) {
2638 dst_fmt = AV_PIX_FMT_NV12;
2639 }
2640#endif
2641 persistent_dst_frame->format = dst_fmt;
2642 persistent_dst_frame->width = info.width;
2643 persistent_dst_frame->height = info.height;
2644
2645 persistent_dst_size = av_image_get_buffer_size(
2646 dst_fmt, info.width, info.height, 32
2647 );
2648 if (persistent_dst_size < 0)
2649 throw ErrorEncodingVideo("Invalid destination image size", -1);
2650
2651 persistent_dst_buffer = static_cast<uint8_t*>(
2652 av_malloc(persistent_dst_size)
2653 );
2654 if (!persistent_dst_buffer)
2655 throw OutOfMemory("Could not allocate persistent_dst_buffer", path);
2656
2657 av_image_fill_arrays(
2658 persistent_dst_frame->data,
2659 persistent_dst_frame->linesize,
2660 persistent_dst_buffer,
2661 dst_fmt,
2662 info.width,
2663 info.height,
2664 32
2665 );
2666 }
2667
2668 // Initialize SwsContext (RGBA → dst_fmt) on first use
2669 if (!img_convert_ctx) {
2670 int flags = SWS_FAST_BILINEAR;
2671 if (openshot::Settings::Instance()->HIGH_QUALITY_SCALING) {
2672 flags = SWS_BICUBIC;
2673 }
2674 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2675#if USE_HW_ACCEL
2676 if (hw_en_on && hw_en_supported) {
2677 dst_fmt = AV_PIX_FMT_NV12;
2678 }
2679#endif
2680 img_convert_ctx = sws_getContext(
2681 src_w, src_h, AV_PIX_FMT_RGBA,
2682 info.width, info.height, dst_fmt,
2683 flags, NULL, NULL, NULL
2684 );
2685 if (!img_convert_ctx)
2686 throw ErrorEncodingVideo("Could not initialize sws context", -1);
2687 }
2688
2689 // Scale RGBA → dst_fmt into persistent_dst_buffer
2690 sws_scale(
2691 img_convert_ctx,
2692 persistent_src_frame->data,
2693 persistent_src_frame->linesize,
2694 0, src_h,
2695 persistent_dst_frame->data,
2696 persistent_dst_frame->linesize
2697 );
2698
2699 // Allocate a new AVFrame + buffer, then copy scaled data into it
2700 int bytes_final = 0;
2701 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2702#if USE_HW_ACCEL
2703 if (hw_en_on && hw_en_supported) {
2704 dst_fmt = AV_PIX_FMT_NV12;
2705 }
2706#endif
2707
2708 AVFrame* new_frame = allocate_avframe(
2709 dst_fmt,
2710 info.width,
2711 info.height,
2712 &bytes_final,
2713 nullptr
2714 );
2715 if (!new_frame)
2716 throw OutOfMemory("Could not allocate new_frame via allocate_avframe", path);
2717
2718 // Copy visible pixels from padded scaler planes into the packed encoder frame.
2719#ifdef AV_PIX_FMT_FLAG_PSEUDOPAL
2720 // Older FFmpeg's av_image_copy also copies a synthetic palette for RGB8
2721 // (GIF), although av_image_get_buffer_size no longer allocates that palette.
2722 if (av_pix_fmt_desc_get(dst_fmt)->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
2723 av_image_copy_plane(new_frame->data[0], new_frame->linesize[0],
2724 persistent_dst_frame->data[0], persistent_dst_frame->linesize[0],
2725 av_image_get_linesize(dst_fmt, info.width, 0), info.height);
2726 } else
2727#endif
2728 av_image_copy(new_frame->data, new_frame->linesize,
2729 const_cast<const uint8_t**>(persistent_dst_frame->data),
2730 persistent_dst_frame->linesize, dst_fmt, info.width, info.height);
2731
2732 // Queue the deep‐copied frame for encoding
2733 add_avframe(frame, new_frame);
2734}
2735
2736// write video frame
2737bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2738#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2739 // FFmpeg 4.0+
2741 "FFmpegWriter::write_video_packet",
2742 "frame->number", frame->number,
2743 "oc->oformat->flags", oc->oformat->flags);
2744
2745 if (AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) {
2746#else
2747 // TODO: Should we have moved away from oc->oformat->flags / AVFMT_RAWPICTURE
2748 // on ffmpeg < 4.0 as well?
2749 // Does AV_CODEC_ID_RAWVIDEO not work in ffmpeg 3.x?
2751 "FFmpegWriter::write_video_packet",
2752 "frame->number", frame->number,
2753 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2754
2755 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2756#endif
2757 // The packet owns a separate, padded buffer. write_frame() still owns
2758 // frame_final, so handing its data to av_packet_from_data would free it twice.
2759 AVPacket packet = {};
2760 const PixelFormat format = static_cast<PixelFormat>(frame_final->format);
2761 const int size = AV_GET_IMAGE_SIZE(format, frame_final->width, frame_final->height);
2762 int error_code = size < 0 ? size : av_new_packet(&packet, size);
2763 if (error_code >= 0) {
2764 // Copy every plane, not just the first plane's stride * height.
2765 error_code = av_image_copy_to_buffer(packet.data, packet.size,
2766 frame_final->data, frame_final->linesize, format,
2767 frame_final->width, frame_final->height, 1);
2768 }
2769 if (error_code >= 0) {
2770 packet.flags |= AV_PKT_FLAG_KEY;
2771 packet.stream_index = video_st->index;
2772 packet.pts = packet.dts = video_timestamp;
2773 packet.duration = av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
2774 av_packet_rescale_ts(&packet, video_codec_ctx->time_base, video_st->time_base);
2775 error_code = av_interleaved_write_frame(oc, &packet);
2776 }
2777 AV_FREE_PACKET(&packet);
2778 if (error_code < 0) {
2780 "FFmpegWriter::write_video_packet ERROR ["
2781 + av_err2string(error_code) + "]",
2782 "error_code", error_code);
2783 return false;
2784 }
2785 } else
2786 {
2787
2788#if IS_FFMPEG_3_2
2789 AVPacket* pkt = av_packet_alloc();
2790#else
2791 AVPacket* pkt;
2792 av_init_packet(pkt);
2793#endif
2794 pkt->data = NULL;
2795 pkt->size = 0;
2796 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2797
2798 // Assign the initial AVFrame PTS from the frame counter
2799 frame_final->pts = video_timestamp;
2800#if USE_HW_ACCEL
2801 if (hw_en_on && hw_en_supported) {
2802 if (!(hw_frame = av_frame_alloc())) {
2803 std::clog << "Error code: av_hwframe_alloc\n";
2804 }
2805 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx, hw_frame, 0) < 0) {
2806 std::clog << "Error code: av_hwframe_get_buffer\n";
2807 }
2808 if (!hw_frame->hw_frames_ctx) {
2809 std::clog << "Error hw_frames_ctx.\n";
2810 }
2811 // Keep the hardware format assigned by av_hwframe_get_buffer().
2812 // NV12 describes the CPU source, not the encoder surface.
2813 if ( av_hwframe_transfer_data(hw_frame, frame_final, 0) < 0) {
2814 std::clog << "Error while transferring frame data to surface.\n";
2815 }
2816 av_frame_copy_props(hw_frame, frame_final);
2817 }
2818#endif // USE_HW_ACCEL
2819 /* encode the image */
2820 int got_packet_ptr = 0;
2821 int error_code = 0;
2822#if IS_FFMPEG_3_2
2823 // Write video packet
2824 int ret;
2825
2826 #if USE_HW_ACCEL
2827 if (hw_en_on && hw_en_supported) {
2828 ret = avcodec_send_frame(video_codec_ctx, hw_frame); //hw_frame!!!
2829 } else
2830 #endif // USE_HW_ACCEL
2831 {
2832 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2833 }
2834 error_code = ret;
2835 if (ret < 0 ) {
2837 "FFmpegWriter::write_video_packet (Frame not sent)");
2838 if (ret == AVERROR(EAGAIN) ) {
2839 std::clog << "Frame EAGAIN\n";
2840 }
2841 if (ret == AVERROR_EOF ) {
2842 std::clog << "Frame AVERROR_EOF\n";
2843 }
2844 avcodec_send_frame(video_codec_ctx, NULL);
2845 }
2846 else {
2847 while (ret >= 0) {
2848 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2849
2850 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2851 got_packet_ptr = 0;
2852 break;
2853 }
2854 if (ret == 0) {
2855 got_packet_ptr = 1;
2856 break;
2857 }
2858 }
2859 }
2860#else
2861 // Write video packet (older than FFmpeg 3.2)
2862 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2863 if (error_code != 0) {
2865 "FFmpegWriter::write_video_packet ERROR ["
2866 + av_err2string(error_code) + "]",
2867 "error_code", error_code);
2868 }
2869 if (got_packet_ptr == 0) {
2871 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2872 }
2873#endif // IS_FFMPEG_3_2
2874
2875 /* if zero size, it means the image was buffered */
2876 if (error_code == 0 && got_packet_ptr) {
2877 // set the timestamp
2878 if (pkt->duration <= 0) {
2879 pkt->duration = av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
2880 }
2881 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2882 pkt->stream_index = video_st->index;
2883
2884 /* write the compressed frame in the media file */
2885 int result = av_interleaved_write_frame(oc, pkt);
2886 if (result < 0) {
2888 "FFmpegWriter::write_video_packet ERROR ["
2889 + av_err2string(result) + "]",
2890 "result", result);
2891 return false;
2892 }
2893 }
2894
2895 // Deallocate packet
2896 AV_FREE_PACKET(pkt);
2897#if USE_HW_ACCEL
2898 if (hw_en_on && hw_en_supported) {
2899 if (hw_frame) {
2900 av_frame_free(&hw_frame);
2901 hw_frame = NULL;
2902 }
2903 }
2904#endif // USE_HW_ACCEL
2905 }
2906
2907 // Increment PTS (in frames and scaled to the codec's timebase)
2908 video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
2909
2910 // Success
2911 return true;
2912}
2913
2914// Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
2916 // output debug info
2917 av_dump_format(oc, 0, path.c_str(), 1);
2918}
2919
2920// Set audio resample options
2921void FFmpegWriter::ResampleAudio(int sample_rate, int channels) {
2922 original_sample_rate = sample_rate;
2923 original_channels = channels;
2924}
2925
2926// In FFmpegWriter.cpp
2927void FFmpegWriter::AddSphericalMetadata(const std::string& projection, float yaw_deg, float pitch_deg, float roll_deg) {
2928 if (!oc) return;
2929 if (!info.has_video || !video_st) return;
2930
2931 // Allow movenc.c to write out the sv3d atom
2932 oc->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
2933
2934#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
2935 // Map the projection name to the enum (defaults to equirectangular)
2936 int proj = av_spherical_from_name(projection.c_str());
2937 if (proj < 0)
2938 proj = AV_SPHERICAL_EQUIRECTANGULAR;
2939
2940 // Allocate the side‐data structure
2941 size_t sd_size = 0;
2942 AVSphericalMapping* map = av_spherical_alloc(&sd_size);
2943 if (!map) return;
2944
2945 // Populate it
2946 map->projection = static_cast<AVSphericalProjection>(proj);
2947 // yaw/pitch/roll are 16.16 fixed point
2948 map->yaw = static_cast<int32_t>(yaw_deg * (1 << 16));
2949 map->pitch = static_cast<int32_t>(pitch_deg * (1 << 16));
2950 map->roll = static_cast<int32_t>(roll_deg * (1 << 16));
2951
2952#if LIBAVFORMAT_VERSION_MAJOR >= 61
2953 // Encoder initialization copies coded side data into the stream parameters.
2954 // Keep the mapping on the context so that copy does not discard it.
2955 AVPacketSideData* side_data = av_packet_side_data_add(
2956 &video_codec_ctx->coded_side_data, &video_codec_ctx->nb_coded_side_data,
2957 AV_PKT_DATA_SPHERICAL, reinterpret_cast<uint8_t*>(map), sd_size, 0);
2958 if (!side_data)
2959 av_free(map);
2960#else
2961 if (ffmpeg_stream_add_side_data(video_st, AV_PKT_DATA_SPHERICAL,
2962 reinterpret_cast<uint8_t*>(map), sd_size) < 0)
2963 av_free(map);
2964#endif
2965#endif
2966}
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.
Exception when encoding audio packet.
Definition Exceptions.h:134
Exception when encoding audio packet.
Definition Exceptions.h:149
Base exception class with a custom message variable.
Definition Exceptions.h:28
virtual const char * what() const noexcept
Definition Exceptions.h:34
static std::string GetEncoders(std::string media_type, std::string format_name="")
List the available encoders as a JSON array.
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...
static std::string GetFormats()
List the file extensions the writer can export to, as a JSON array.
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 WriteFrameAt(std::shared_ptr< openshot::Frame > frame, int64_t frame_number)
Add a frame at a specific output video frame number.
static std::string GetFormatInfo(std::string format_name)
Describe an output format as JSON (name, extensions, and default codecs).
static int IsCodecSupportedByFormat(std::string format_name, std::string codec_name)
Determine if an output format can store a codec.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
static std::string GetEncoderInfo(std::string codec_name)
Describe an encoder's capabilities as JSON.
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)
std::string Test()
Check the current settings without writing a file, and return the result as JSON.
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
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)
Definition Logger.cpp:168
static Logger * Instance()
Definition Logger.cpp:55
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:43
int HW_EN_DEVICE_SET
Which GPU to use to encode (0 is the first)
Definition Settings.h:95
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
This namespace is the default namespace for all code in the openshot library.
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)
std::string text
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