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