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