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