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