46static AVBufferRef *hw_device_ctx = NULL;
49static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
51 AVBufferRef *hw_frames_ref;
52 AVHWFramesContext *frames_ctx = NULL;
55 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
56 std::clog <<
"Failed to create HW frame context.\n";
59 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
61 frames_ctx->sw_format = AV_PIX_FMT_NV12;
62 frames_ctx->width = width;
63 frames_ctx->height = height;
64 frames_ctx->initial_pool_size = 20;
65 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
66 std::clog <<
"Failed to initialize HW frame context. " <<
67 "Error code: " << av_err2string(err) <<
"\n";
68 av_buffer_unref(&hw_frames_ref);
71 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
72 if (!ctx->hw_frames_ctx)
73 err = AVERROR(ENOMEM);
75 av_buffer_unref(&hw_frames_ref);
81 path(
path), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
82 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
83 initial_audio_input_frame_size(0), img_convert_ctx(NULL),
84 video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
85 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
86 write_header(false), write_trailer(false), allow_b_frames(false), testing(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
106 if (!prepare_streams)
111 open_video(oc, video_st);
113 open_audio(oc, audio_st);
122void FFmpegWriter::auto_detect_format() {
128 "Could not allocate memory for AVFormatContext.", path);
132 oc->oformat = av_guess_format(NULL, path.c_str(), NULL);
133 if (oc->oformat ==
nullptr) {
134 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
138 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video) {
139 const AVCodec *vcodec = avcodec_find_encoder(oc->oformat->video_codec);
140 info.
vcodec = vcodec ? vcodec->name : std::string();
142 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio) {
143 const AVCodec *acodec = avcodec_find_encoder(oc->oformat->audio_codec);
144 info.
acodec = acodec ? acodec->name : std::string();
149void FFmpegWriter::initialize_streams() {
151 "FFmpegWriter::initialize_streams",
152 "oc->oformat->video_codec", oc->oformat->video_codec,
153 "oc->oformat->audio_codec", oc->oformat->audio_codec,
154 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
159 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
161 video_st = add_video_stream();
163 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
165 audio_st = add_audio_stream();
171 if (
codec.length() > 0) {
172 const AVCodec *new_codec;
175#if defined(__linux__)
176 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
177 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
182 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
183 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
189 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
194 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
195 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
200 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
201 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
207 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
211#elif defined(__APPLE__)
212 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
213 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
219 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
224 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
227 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
229 if (new_codec == NULL)
230 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
249 if (pixel_ratio.
num > 0) {
253 if (bit_rate >= 1000)
255 if ((bit_rate >= 0) && (bit_rate < 256))
272 "FFmpegWriter::SetVideoOptions (" +
codec +
")",
273 "width", width,
"height", height,
274 "size.num", size.
num,
"size.den", size.
den,
275 "fps.num", fps.
num,
"fps.den", fps.
den);
285 true,
codec, fps, width, height,
294 if (
codec.length() > 0) {
295 const AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
296 if (new_codec == NULL)
297 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
303 if (sample_rate > 7999)
312 if (original_sample_rate == 0)
314 if (original_channels == 0)
318 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
319 "sample_rate", sample_rate,
320 "channels", channels,
321 "bit_rate", bit_rate);
332 true,
codec, sample_rate, 2,
341 AVCodecContext *c = NULL;
343 std::stringstream convert(value);
362 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
365 const AVOption *option = NULL;
373 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
374 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
375 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp" || name ==
"allow_b_frames")) {
379 convert >> c->gop_size;
381 else if (name ==
"qmin")
385 else if (name ==
"qmax")
389 else if (name ==
"max_b_frames")
391 convert >> c->max_b_frames;
393 else if (name ==
"allow_b_frames")
396 allow_b_frames = (value ==
"1" || value ==
"true" || value ==
"yes" || value ==
"on");
398 else if (name ==
"mb_decision")
400 convert >> c->mb_decision;
402 else if (name ==
"level")
406 else if (name ==
"profile")
408 convert >> c->profile;
410 else if (name ==
"slices")
412 convert >> c->slices;
414 else if (name ==
"rc_min_rate")
416 convert >> c->rc_min_rate;
418 else if (name ==
"rc_max_rate")
420 convert >> c->rc_max_rate;
422 else if (name ==
"rc_buffer_size")
424 convert >> c->rc_buffer_size;
426 else if (name ==
"cqp") {
430 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
434 switch (c->codec_id) {
435#if (LIBAVCODEC_VERSION_MAJOR >= 58)
437 case AV_CODEC_ID_AV1 :
439 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
442 case AV_CODEC_ID_VP8 :
443 c->bit_rate = 10000000;
444 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
446 case AV_CODEC_ID_VP9 :
448 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
449 if (std::stoi(value) == 0) {
450 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
451 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
454 case AV_CODEC_ID_H264 :
455 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
456 if (std::stoi(value) == 0) {
457 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
461 case AV_CODEC_ID_HEVC :
462 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
463 if (std::stoi(value) == 0) {
464 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
465 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
470 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
474 }
else if (name ==
"crf") {
478 double mbs = 15000000.0;
487 c->bit_rate = (int)(mbs);
491 switch (c->codec_id) {
492#if (LIBAVCODEC_VERSION_MAJOR >= 58)
494 case AV_CODEC_ID_AV1 :
497 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
500 case AV_CODEC_ID_VP8 :
501 c->bit_rate = 10000000;
502 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
504 case AV_CODEC_ID_VP9 :
506 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
507 if (std::stoi(value) == 0) {
508 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
509 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
512 case AV_CODEC_ID_H264 :
513 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
514 if (std::stoi(value) == 0) {
515 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
519 case AV_CODEC_ID_HEVC :
520 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
521 av_opt_set_int(c->priv_data,
"preset", 7, 0);
522 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
523 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
526 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
528 if (std::stoi(value) == 0) {
529 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
530 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
536 double mbs = 15000000.0;
544 c->bit_rate = (int) (mbs);
547 }
else if (name ==
"qp") {
549#if (LIBAVCODEC_VERSION_MAJOR >= 58)
551 switch (c->codec_id) {
552 case AV_CODEC_ID_AV1 :
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);
557 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
560 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
562 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
566 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
569 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
571 case AV_CODEC_ID_HEVC :
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);
583 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
587 "FFmpegWriter::SetOption (" + (std::string)name +
")",
592 }
else if (name ==
"muxing_preset") {
593 if (value ==
"mp4_faststart") {
595 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
596 }
else if (value ==
"mp4_fragmented") {
598 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
599 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
602 throw InvalidOptions(
"The option is not valid for this codec.", path);
613 return avcodec_find_encoder_by_name(codec_name.c_str()) != NULL;
617static const AVOutputFormat* find_output_format(std::string format_name) {
618 if (!format_name.empty() && format_name[0] ==
'.')
619 format_name.erase(0, 1);
620 if (format_name.empty())
622 const AVOutputFormat* format = av_guess_format(NULL, (
"file." + format_name).c_str(), NULL);
624 format = av_guess_format(format_name.c_str(), NULL, NULL);
629template<
typename Visitor>
630static void for_each_encoder(Visitor visit) {
631#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 10, 100)
632 void* iterator =
nullptr;
633 const AVCodec*
codec =
nullptr;
634 while ((
codec = av_codec_iterate(&iterator)))
636 const AVCodec*
codec =
nullptr;
639 if (av_codec_is_encoder(
codec))
644template<
typename Visitor>
645static void for_each_muxer(Visitor visit) {
646#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100)
647 void* iterator =
nullptr;
648 const AVOutputFormat* format =
nullptr;
649 while ((format = av_muxer_iterate(&iterator)))
651 AVOutputFormat* format =
nullptr;
652 while ((format = av_oformat_next(format)))
658static std::string default_encoder_name(AVCodecID codec_id) {
659 if (codec_id == AV_CODEC_ID_NONE)
661 const AVCodec*
codec = avcodec_find_encoder(codec_id);
666static const std::set<AVCodecID>& image_codec_ids() {
667 static const std::set<AVCodecID> ids = [] {
668 std::set<AVCodecID> found;
669 const AVOutputFormat* image2 = av_guess_format(
"image2", NULL, NULL);
670 if (!image2 || !image2->extensions)
672 std::stringstream extension_list(image2->extensions);
673 std::string extension;
674 while (std::getline(extension_list, extension,
',')) {
675 AVCodecID
id = av_guess_codec(
const_cast<AVOutputFormat*
>(image2), NULL,
676 (
"file." + extension).c_str(), NULL, AVMEDIA_TYPE_VIDEO);
677 if (
id != AV_CODEC_ID_NONE)
685static bool encoder_has_option(
const AVCodec*
codec,
const char* name) {
686 if (!
codec->priv_class)
688 const AVClass* priv_class =
codec->priv_class;
689 return av_opt_find(&priv_class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ) !=
nullptr;
696 const AVCodec*
codec = avcodec_find_encoder_by_name(codec_name.c_str());
697 root[
"found"] =
codec !=
nullptr;
699 return root.toStyledString();
701 root[
"name"] =
codec->name;
702 root[
"long_name"] =
codec->long_name ?
codec->long_name :
"";
703 const char* media_type = av_get_media_type_string(
codec->type);
704 root[
"type"] = media_type ? media_type :
"unknown";
706 bool hardware =
false;
707#ifdef AV_CODEC_CAP_HARDWARE
708 hardware = hardware || (
codec->capabilities & AV_CODEC_CAP_HARDWARE);
710#ifdef AV_CODEC_CAP_HYBRID
711 hardware = hardware || (
codec->capabilities & AV_CODEC_CAP_HYBRID);
713 root[
"hardware"] = hardware;
714#ifdef AV_CODEC_CAP_EXPERIMENTAL
715 root[
"experimental"] = (
codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) != 0;
717 root[
"experimental"] = (
codec->capabilities & CODEC_CAP_EXPERIMENTAL) != 0;
721 const AVCodecDescriptor* descriptor = avcodec_descriptor_get(
codec->id);
722 root[
"lossless"] = descriptor && (descriptor->props & AV_CODEC_PROP_LOSSLESS);
723 root[
"lossy"] = descriptor && (descriptor->props & AV_CODEC_PROP_LOSSY);
725 root[
"intra_only"] = descriptor && (descriptor->props & AV_CODEC_PROP_INTRA_ONLY);
727 root[
"image"] = image_codec_ids().count(
codec->id) > 0;
729 root[
"codec"] = avcodec_get_name(
codec->id);
731 Json::Value quality_options(Json::arrayValue);
732 for (
const char* option : {
"crf",
"qp",
"cq",
"global_quality"})
733 if (encoder_has_option(
codec, option))
734 quality_options.append(option);
735 root[
"quality_options"] = quality_options;
737 root[
"sample_rates"] = Json::Value(Json::nullValue);
738 root[
"channel_layouts"] = Json::Value(Json::nullValue);
739 root[
"sample_formats"] = Json::Value(Json::nullValue);
740 root[
"pixel_formats"] = Json::Value(Json::nullValue);
742 std::unique_ptr<AVCodecContext, void(*)(AVCodecContext*)> context(
743 avcodec_alloc_context3(
codec),
744 [](AVCodecContext* value) { avcodec_free_context(&value); });
746 return root.toStyledString();
749 if (
codec->type == AVMEDIA_TYPE_AUDIO) {
750 if (
const int* rates = ffmpeg_codec_sample_rates(
codec, context.get())) {
751 Json::Value values(Json::arrayValue);
752 for (
int i = 0; rates[i] != 0; i++)
753 values.append(rates[i]);
754 root[
"sample_rates"] = values;
757 if (
const AVChannelLayout* layouts = ffmpeg_codec_ch_layouts(
codec, context.get())) {
758 Json::Value values(Json::arrayValue);
759 for (
int i = 0; av_channel_layout_check(&layouts[i]); i++)
760 if (layouts[i].order == AV_CHANNEL_ORDER_NATIVE)
761 values.append((Json::UInt64) layouts[i].u.mask);
762 root[
"channel_layouts"] = values;
765 if (
codec->channel_layouts) {
766 Json::Value values(Json::arrayValue);
767 for (
int i = 0;
codec->channel_layouts[i] != 0; i++)
768 values.append((Json::UInt64)
codec->channel_layouts[i]);
769 root[
"channel_layouts"] = values;
772 if (
const AVSampleFormat* formats = ffmpeg_codec_sample_fmts(
codec, context.get())) {
773 Json::Value values(Json::arrayValue);
774 for (
int i = 0; formats[i] != AV_SAMPLE_FMT_NONE; i++) {
775 const char* name = av_get_sample_fmt_name(formats[i]);
779 root[
"sample_formats"] = values;
781 }
else if (
codec->type == AVMEDIA_TYPE_VIDEO) {
782 if (
const AVPixelFormat* formats = ffmpeg_codec_pix_fmts(
codec, context.get())) {
783 Json::Value values(Json::arrayValue);
784 for (
int i = 0; formats[i] != AV_PIX_FMT_NONE; i++) {
785 const char* name = av_get_pix_fmt_name(formats[i]);
789 root[
"pixel_formats"] = values;
796 return root.toStyledString();
803 const AVOutputFormat* format = find_output_format(format_name);
804 root[
"found"] = format !=
nullptr;
806 return root.toStyledString();
808 root[
"name"] = format->name;
809 root[
"long_name"] = format->long_name ? format->long_name :
"";
810 Json::Value extensions(Json::arrayValue);
811 std::stringstream extension_list(format->extensions ? format->extensions :
"");
812 std::string extension;
813 while (std::getline(extension_list, extension,
','))
814 if (!extension.empty())
815 extensions.append(extension);
816 root[
"extensions"] = extensions;
817 root[
"default_audio_codec"] = default_encoder_name(format->audio_codec);
818 root[
"default_video_codec"] = default_encoder_name(format->video_codec);
819 return root.toStyledString();
825 Json::Value formats(Json::arrayValue);
826 std::set<std::string> listed;
827 for_each_muxer([&](
const AVOutputFormat* format) {
828 std::stringstream extension_list(format->extensions ? format->extensions :
"");
829 std::string extension;
830 while (std::getline(extension_list, extension,
',')) {
832 extension.erase(0, extension.find_first_not_of(
" \t"));
833 extension.erase(extension.find_last_not_of(
" \t") + 1);
835 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
836 if (extension.empty() || listed.count(extension))
840 if (av_guess_format(NULL, (
"file." + extension).c_str(), NULL) != format)
842 listed.insert(extension);
844 row[
"extension"] = extension;
845 row[
"name"] = format->name;
846 row[
"long_name"] = format->long_name ? format->long_name :
"";
847 row[
"default_audio_codec"] = default_encoder_name(format->audio_codec);
848 row[
"default_video_codec"] = default_encoder_name(format->video_codec);
852 return formats.toStyledString();
858 Json::Value encoders(Json::arrayValue);
859 const AVOutputFormat* format =
nullptr;
860 if (!format_name.empty()) {
861 format = find_output_format(format_name);
863 return encoders.toStyledString();
866 for_each_encoder([&](
const AVCodec*
codec) {
867 const char* type = av_get_media_type_string(
codec->type);
868 if (!type || media_type != type)
871 if (format && avformat_query_codec(format,
codec->id, FF_COMPLIANCE_NORMAL) == 0)
874 encoder[
"name"] =
codec->name;
875 encoder[
"long_name"] =
codec->long_name ?
codec->long_name :
"";
876 encoders.append(encoder);
878 return encoders.toStyledString();
884 const AVOutputFormat* format = find_output_format(format_name);
885 const AVCodec*
codec = avcodec_find_encoder_by_name(codec_name.c_str());
886 if (!format || !
codec)
888 const int result = avformat_query_codec(format,
codec->id, FF_COMPLIANCE_NORMAL);
891 return result > 0 ? 1 : 0;
899static thread_local std::vector<TestLogLine>* test_log =
nullptr;
901static void test_log_callback(
void* avcl,
int level,
const char* fmt, va_list vl) {
903 av_log_default_callback(avcl, level, fmt, vl);
906 if (level > AV_LOG_WARNING)
909 vsnprintf(line,
sizeof(line), fmt, vl);
910 std::string text(line);
911 while (!text.empty() && (text.back() ==
'\n' || text.back() ==
'\r' || text.back() ==
' '))
916 AVClass* av_class = avcl ? *(AVClass**)avcl : nullptr;
917 if (av_class && av_class->item_name)
918 text = std::string(av_class->item_name(avcl)) +
": " + text;
919 test_log->push_back({level, text});
924 auto start = std::chrono::steady_clock::now();
925 std::vector<TestLogLine> messages;
930 test_log = &messages;
931 av_log_set_callback(test_log_callback);
934 if (!prepare_streams)
938 open_video(oc, video_st);
942 open_audio(oc, audio_st);
946 av_write_trailer(oc);
947 write_trailer =
true;
951 }
catch (
const std::exception& e) {
956 if (oc && oc->pb && !(oc->oformat->flags & AVFMT_NOFILE)) {
957 uint8_t* buffer = NULL;
958 avio_close_dyn_buf(oc->pb, &buffer);
963 close_video(oc, video_st);
965 close_audio(oc, audio_st);
966 video_codec_ctx = NULL;
967 audio_codec_ctx = NULL;
971 avformat_free_context(oc);
976 av_log_set_callback(av_log_default_callback);
979 prepare_streams =
false;
980 write_header =
false;
981 write_trailer =
false;
985 std::string message = error;
986 if (!error.empty()) {
987 for (
auto line = messages.rbegin(); line != messages.rend(); ++line) {
988 if (line->level <= AV_LOG_ERROR) {
989 message = line->text;
996 root[
"ok"] = error.empty();
997 root[
"stage"] = stage;
998 root[
"message"] = message;
999 root[
"log"] = Json::Value(Json::arrayValue);
1000 for (
const auto& line : messages)
1001 root[
"log"].append(line.text);
1002 root[
"elapsed_ms"] = (Json::Int64) std::chrono::duration_cast<std::chrono::milliseconds>(
1003 std::chrono::steady_clock::now() - start).count();
1004 return root.toStyledString();
1010 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
1013 "FFmpegWriter::PrepareStreams [" + path +
"]",
1018 initialize_streams();
1021 prepare_streams =
true;
1027 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
1030 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1033 if (avio_open_dyn_buf(&oc->pb) < 0)
1034 throw OutOfMemory(
"Could not allocate memory for the test output.", path);
1035 }
else if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
1036 throw InvalidFile(
"Could not open or write file.", path);
1044 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1048 AVDictionary *dict = NULL;
1054 if (avformat_write_header(oc, &dict) != 0) {
1056 "FFmpegWriter::WriteHeader (avformat_write_header)");
1057 throw InvalidFile(
"Could not write header to file.", path);
1061 if (dict) av_dict_free(&dict);
1065 write_header =
true;
1074 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
1077 "FFmpegWriter::WriteFrame",
1078 "frame->number", frame->number,
1079 "is_writing", is_writing);
1091 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
1093 if (frame_number < 1) {
1098 "FFmpegWriter::WriteFrameAt",
1099 "frame->number", frame->number,
1100 "output_frame_number", frame_number,
1101 "is_writing", is_writing);
1103 const int64_t previous_video_timestamp = video_timestamp;
1105 video_timestamp = av_rescale_q(
1108 video_codec_ctx->time_base);
1114 video_timestamp = previous_video_timestamp;
1121void FFmpegWriter::write_frame(std::shared_ptr<Frame> frame) {
1126 bool has_error_encoding_video =
false;
1130 write_audio_packets(
false, frame);
1134 process_video_packet(frame);
1138 if (av_frames.count(frame)) {
1140 AVFrame *frame_final = av_frames[frame];
1143 if (!write_video_packet(frame, frame_final)) {
1144 has_error_encoding_video =
true;
1148 av_freep(&(frame_final->data[0]));
1150 av_frames.erase(frame);
1158 if (has_error_encoding_video)
1165 "FFmpegWriter::WriteFrame (from Reader)",
1170 for (int64_t number = start; number <= length; number++) {
1172 std::shared_ptr<Frame> f = reader->
GetFrame(number);
1183 write_audio_packets(
true, NULL);
1188 if (
info.
has_audio && audio_st && audio_codec_ctx && audio_timestamp > 0) {
1189 audio_st->duration = av_rescale_q(
1191 audio_codec_ctx->time_base,
1192 audio_st->time_base);
1199 av_write_trailer(oc);
1202 write_trailer =
true;
1208void FFmpegWriter::flush_encoders() {
1211#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1225 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
1228 AVPacket* pkt = av_packet_alloc();
1231 av_init_packet(pkt);
1242 error_code = avcodec_send_frame(video_codec_ctx, NULL);
1244 while (error_code >= 0) {
1245 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
1246 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
1249 avcodec_flush_buffers(video_codec_ctx);
1252 if (pkt->duration <= 0) {
1253 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
1255 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
1256 pkt->stream_index = video_st->index;
1257 error_code = av_interleaved_write_frame(oc, pkt);
1262 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
1266 if (error_code < 0) {
1268 "FFmpegWriter::flush_encoders ERROR ["
1269 + av_err2string(error_code) +
"]",
1270 "error_code", error_code);
1277 if (pkt->duration <= 0) {
1278 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
1280 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
1281 pkt->stream_index = video_st->index;
1284 error_code = av_interleaved_write_frame(oc, pkt);
1285 if (error_code < 0) {
1287 "FFmpegWriter::flush_encoders ERROR ["
1288 + av_err2string(error_code) +
"]",
1289 "error_code", error_code);
1298 AVPacket* pkt = av_packet_alloc();
1301 av_init_packet(pkt);
1305 pkt->pts = pkt->dts = audio_timestamp;
1311 if (!audio_codec_ctx->codec || !(audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
1312 av_packet_free(&pkt);
1315 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
1316 if (error_code < 0 && error_code != AVERROR_EOF) {
1318 "FFmpegWriter::flush_encoders ERROR ["
1319 + av_err2string(error_code) +
"]",
1320 "error_code", error_code);
1323 error_code = avcodec_receive_packet(audio_codec_ctx, pkt);
1324 if (error_code == AVERROR(EAGAIN) || error_code == AVERROR_EOF) {
1328 if (error_code < 0) {
1330 "FFmpegWriter::flush_encoders ERROR ["
1331 + av_err2string(error_code) +
"]",
1332 "error_code", error_code);
1338 if (pkt->pts == AV_NOPTS_VALUE) {
1339 pkt->pts = audio_timestamp;
1341 if (pkt->dts == AV_NOPTS_VALUE) {
1342 pkt->dts = pkt->pts;
1344 if (pkt->duration <= 0) {
1345 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
1347 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1348 pkt->stream_index = audio_st->index;
1349 pkt->flags |= AV_PKT_FLAG_KEY;
1351 error_code = av_interleaved_write_frame(oc, pkt);
1352 if (error_code < 0) {
1354 "FFmpegWriter::flush_encoders ERROR ["
1355 + av_err2string(error_code) +
"]",
1356 "error_code", error_code);
1361 av_packet_free(&pkt);
1364 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
1365 if (error_code < 0) {
1367 "FFmpegWriter::flush_encoders ERROR ["
1368 + av_err2string(error_code) +
"]",
1369 "error_code", error_code);
1376 pkt->pts = pkt->dts = audio_timestamp;
1377 if (pkt->duration <= 0) {
1378 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
1382 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1385 pkt->stream_index = audio_st->index;
1386 pkt->flags |= AV_PKT_FLAG_KEY;
1389 error_code = av_interleaved_write_frame(oc, pkt);
1390 if (error_code < 0) {
1392 "FFmpegWriter::flush_encoders ERROR ["
1393 + av_err2string(error_code) +
"]",
1394 "error_code", error_code);
1398 audio_timestamp += pkt->duration;
1409void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
1413 if (hw_device_ctx) {
1414 av_buffer_unref(&hw_device_ctx);
1415 hw_device_ctx = NULL;
1421 if (video_codec_ctx !=
nullptr) {
1423 av_free(video_codec_ctx);
1428void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
1432 delete[] audio_outbuf;
1433 delete[] audio_encoder_buffer;
1435 audio_outbuf = NULL;
1436 audio_encoder_buffer = NULL;
1452 if (audio_codec_ctx !=
nullptr) {
1454 av_free(audio_codec_ctx);
1461 if (write_header && !write_trailer)
1466 close_video(oc, video_st);
1468 close_audio(oc, audio_st);
1471 if (img_convert_ctx)
1472 sws_freeContext(img_convert_ctx);
1474 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1480 video_timestamp = 0;
1481 audio_timestamp = 0;
1484 avformat_free_context(oc);
1489 prepare_streams =
false;
1490 write_header =
false;
1491 write_trailer =
false;
1497void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1499 if (!av_frames.count(frame)) {
1501 av_frames[frame] = av_frame;
1509AVStream *FFmpegWriter::add_audio_stream() {
1511 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1513 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1516 if (audio_codec_ctx !=
nullptr) {
1521 AVStream* st = avformat_new_stream(oc,
codec);
1523 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
1527#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1528 st->codecpar->codec_id =
codec->id;
1530 AVCodecContext* c = audio_codec_ctx;
1532 c->codec_id =
codec->id;
1533 c->codec_type = AVMEDIA_TYPE_AUDIO;
1542 if (
const int* supported_rates = ffmpeg_codec_sample_rates(
codec, c)) {
1544 for (i = 0; supported_rates[i] != 0; i++)
1550 if (supported_rates[i] == 0)
1551 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1556 c->time_base = AVRational{1, c->sample_rate};
1557 st->time_base = c->time_base;
1562 AVChannelLayout ch_layout = {};
1564 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1565 if (
const AVChannelLayout* codec_layouts = ffmpeg_codec_ch_layouts(
codec, c)) {
1567 for (i = 0; av_channel_layout_check(&codec_layouts[i]); i++)
1568 if (av_channel_layout_compare(&ch_layout, &codec_layouts[i]) == 0) {
1570 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1573 if (!av_channel_layout_check(&codec_layouts[i]))
1574 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1577 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1581 if (
codec->channel_layouts) {
1582 const uint64_t* layout =
codec->channel_layouts;
1583 while (*layout != 0 && *layout != channel_layout)
1586 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1588 c->channel_layout = channel_layout;
1592 if (
const AVSampleFormat* codec_fmts = ffmpeg_codec_sample_fmts(
codec, c)) {
1593 for (
int i = 0; codec_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1595 c->sample_fmt = codec_fmts[i];
1599 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1601 c->sample_fmt = AV_SAMPLE_FMT_S16;
1605 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1606#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1608 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1610 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1616 const char* nb_channels_label;
1617 const char* channel_layout_label;
1620 nb_channels = c->ch_layout.nb_channels;
1621 channel_layout = c->ch_layout.u.mask;
1622 nb_channels_label =
"c->ch_layout.nb_channels";
1623 channel_layout_label =
"c->ch_layout.u.mask";
1625 nb_channels = c->channels;
1626 nb_channels_label =
"c->channels";
1627 channel_layout_label =
"c->channel_layout";
1631 "FFmpegWriter::add_audio_stream",
1632 "c->codec_id", c->codec_id,
1633 "c->bit_rate", c->bit_rate,
1634 nb_channels_label, nb_channels,
1635 "c->sample_fmt", c->sample_fmt,
1636 channel_layout_label, channel_layout,
1637 "c->sample_rate", c->sample_rate);
1643AVStream *FFmpegWriter::add_video_stream() {
1645 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1647 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1650 if (video_codec_ctx !=
nullptr) {
1655 AVStream* st = avformat_new_stream(oc,
codec);
1657 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1661#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1662 st->codecpar->codec_id =
codec->id;
1665 AVCodecContext* c = video_codec_ctx;
1667 c->codec_id =
codec->id;
1668 c->codec_type = AVMEDIA_TYPE_VIDEO;
1676#
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1677 && c->codec_id != AV_CODEC_ID_AV1
1682 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1691 switch (c->codec_id) {
1692#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1694 case AV_CODEC_ID_AV1 :
1698 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1699 int calculated_quality = 35;
1702 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1705 int calculated_quality = 50;
1708 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1712 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1713 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1714 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1716 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1717 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1718 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1719 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1721 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1724 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1725 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1726 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1727 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1731 case AV_CODEC_ID_VP9 :
1732 case AV_CODEC_ID_HEVC :
1733 case AV_CODEC_ID_VP8 :
1734 case AV_CODEC_ID_H264 :
1770#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1771 c->framerate = av_inv_q(c->time_base);
1773 st->avg_frame_rate = av_inv_q(c->time_base);
1774 st->r_frame_rate = av_inv_q(c->time_base);
1779 c->max_b_frames = 10;
1780 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1782 c->max_b_frames = 2;
1783 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1789 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1790#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1792 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1794 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1798 if (
const PixelFormat* supported_pixel_formats = ffmpeg_codec_pix_fmts(
codec, c)) {
1802 c->pix_fmt = *supported_pixel_formats;
1803 ++supported_pixel_formats;
1809 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1813#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1815 if (strcmp(oc->oformat->name,
"gif") != 0)
1818 oc->oformat->flags |= AVFMT_RAWPICTURE;
1828 "FFmpegWriter::add_video_stream ("
1829 + (std::string)oc->oformat->name +
" : "
1830 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1831 "c->codec_id", c->codec_id,
1832 "c->bit_rate", c->bit_rate,
1833 "c->pix_fmt", c->pix_fmt,
1834 "oc->oformat->flags", oc->oformat->flags);
1839void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1840 const AVCodec *
codec;
1849 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1854 AVDictionary *
opts = NULL;
1855 av_dict_set(&
opts,
"strict",
"experimental", 0);
1858 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1859 throw InvalidCodec(
"Could not open audio codec", path);
1863 av_dict_free(&
opts);
1867 if (audio_codec_ctx->frame_size <= 1) {
1873 case AV_CODEC_ID_PCM_S16LE:
1874 case AV_CODEC_ID_PCM_S16BE:
1875 case AV_CODEC_ID_PCM_U16LE:
1876 case AV_CODEC_ID_PCM_U16BE:
1877 audio_input_frame_size >>= 1;
1884 audio_input_frame_size = audio_codec_ctx->frame_size;
1888 initial_audio_input_frame_size = audio_input_frame_size;
1895 audio_outbuf =
new uint8_t[audio_outbuf_size];
1899 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1902 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1903 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1907 "FFmpegWriter::open_audio",
1908 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1909 "audio_input_frame_size", audio_input_frame_size,
1914void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1915 const AVCodec *
codec;
1925 char *adapter_ptr = NULL;
1929 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1930 if (adapter_num < 3 && adapter_num >=0) {
1931#if defined(__linux__)
1932 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1934 adapter_ptr = adapter;
1935#elif defined(_WIN32) || defined(__APPLE__)
1943#if defined(__linux__)
1944 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1945#elif defined(_WIN32) || defined(__APPLE__)
1946 if( adapter_ptr != NULL ) {
1949 "Encode Device present using device",
1950 "adapter", adapter_num);
1955 "Encode Device not present, using default");
1957 if (av_hwdevice_ctx_create(&hw_device_ctx,
1961 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1977 if (!allow_b_frames && video_codec_ctx->max_b_frames &&
1978 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 &&
1979 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO &&
1980 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1981 video_codec_ctx->max_b_frames = 0;
1985 av_dict_set(&
opts,
"strict",
"experimental", 0);
1999 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
2001 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
2005 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
2009 switch (video_codec_ctx->codec_id) {
2010 case AV_CODEC_ID_H264:
2011 video_codec_ctx->max_b_frames = 0;
2012 video_codec_ctx->profile = AV_PROFILE_H264_CONSTRAINED_BASELINE;
2013 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
2014 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
2015 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
2017 case AV_CODEC_ID_HEVC:
2020 case AV_CODEC_ID_VP9:
2025 "No codec-specific options defined for this codec. HW encoding may fail",
2026 "codec_id", video_codec_ctx->codec_id);
2035 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
2038 av_err2string(err), -1);
2046 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
2049 if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
2050 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
2056 throw InvalidCodec(
"Could not open video codec", path);
2062 av_dict_free(&
opts);
2066 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
2070 "FFmpegWriter::open_video",
2071 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
2076void FFmpegWriter::write_audio_packets(
bool is_final, std::shared_ptr<openshot::Frame> frame) {
2077 if (!frame && !is_final)
2081 int total_frame_samples = 0;
2082 int frame_position = 0;
2083 int channels_in_frame = 0;
2084 int sample_rate_in_frame = 0;
2085 int samples_in_frame = 0;
2090 float *all_queued_samples = (
float *) av_malloc(all_queued_samples_size);
2091 int16_t *all_resampled_samples = NULL;
2092 int16_t *final_samples_planar = NULL;
2093 int16_t *final_samples = NULL;
2096 float *frame_samples_float = NULL;
2100 sample_rate_in_frame = frame->SampleRate();
2101 samples_in_frame = frame->GetAudioSamplesCount();
2102 channels_in_frame = frame->GetAudioChannelsCount();
2103 channel_layout_in_frame = frame->ChannelsLayout();
2106 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
2110 total_frame_samples = samples_in_frame * channels_in_frame;
2114 for (
int s = 0; s < total_frame_samples; s++, frame_position++)
2115 all_queued_samples[frame_position] = frame_samples_float[s];
2118 delete[] frame_samples_float;
2122 total_frame_samples = frame_position;
2123 int remaining_frame_samples = total_frame_samples;
2124 int samples_position = 0;
2128 "FFmpegWriter::write_audio_packets",
2129 "is_final", is_final,
2130 "total_frame_samples", total_frame_samples,
2131 "channel_layout_in_frame", channel_layout_in_frame,
2132 "channels_in_frame", channels_in_frame,
2133 "samples_in_frame", samples_in_frame,
2137 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
2139 AVFrame *audio_frame = NULL;
2144 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
2147 int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_FLT, (uint8_t *) all_queued_samples, all_queued_samples_size, 0);
2148 if (error_code < 0) {
2150 "FFmpegWriter::write_audio_packets ERROR ["
2151 + av_err2string(error_code) +
"]",
2152 "error_code", error_code);
2156 switch (audio_codec_ctx->sample_fmt) {
2157 case AV_SAMPLE_FMT_FLTP: {
2158 output_sample_fmt = AV_SAMPLE_FMT_FLT;
2161 case AV_SAMPLE_FMT_S32P: {
2162 output_sample_fmt = AV_SAMPLE_FMT_S32;
2165 case AV_SAMPLE_FMT_S16P: {
2166 output_sample_fmt = AV_SAMPLE_FMT_S16;
2169 case AV_SAMPLE_FMT_U8P: {
2170 output_sample_fmt = AV_SAMPLE_FMT_U8;
2180 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
2181 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
2186 audio_converted->nb_samples = total_frame_samples /
info.
channels;
2187 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
2190 "FFmpegWriter::write_audio_packets (1st resampling)",
2191 "in_sample_fmt", AV_SAMPLE_FMT_FLT,
2192 "out_sample_fmt", output_sample_fmt,
2193 "in_sample_rate", sample_rate_in_frame,
2195 "in_channels", channels_in_frame,
2202 AVChannelLayout in_chlayout = ffmpeg_default_channel_layout(channels_in_frame);
2203 AVChannelLayout out_chlayout = ffmpeg_default_channel_layout(
info.
channels);
2204 if (channel_layout_in_frame > 0) {
2205 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
2210 av_opt_set_chlayout(avr,
"in_chlayout", &in_chlayout, 0);
2211 av_opt_set_chlayout(avr,
"out_chlayout", &out_chlayout, 0);
2213 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
2215 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
2218 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
2219 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
2220 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
2225 const double mono_to_stereo[2] = { 1.0, 1.0 };
2227 swr_set_matrix(avr, mono_to_stereo, 1);
2229 avresample_set_matrix(avr, mono_to_stereo, 1);
2237 audio_converted->data,
2238 audio_converted->linesize[0],
2239 audio_converted->nb_samples,
2241 audio_frame->linesize[0],
2242 audio_frame->nb_samples
2252 all_resampled_samples = (int16_t *) av_malloc(
2254 * (av_get_bytes_per_sample(output_sample_fmt) /
2255 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2259 memcpy(all_resampled_samples, audio_converted->data[0],
2260 static_cast<size_t>(nb_samples)
2262 * av_get_bytes_per_sample(output_sample_fmt));
2265 av_freep(&(audio_frame->data[0]));
2267 av_freep(&audio_converted->data[0]);
2269 all_queued_samples = NULL;
2272 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
2273 "nb_samples", nb_samples,
2274 "remaining_frame_samples", remaining_frame_samples);
2277 if (is_final && remaining_frame_samples <= 0 && audio_input_position <= 0) {
2278 if (all_queued_samples) {
2279 av_freep(&all_queued_samples);
2285 while (remaining_frame_samples > 0 || is_final) {
2287 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
2291 if (remaining_frame_samples >= remaining_packet_samples) {
2292 diff = remaining_packet_samples;
2294 diff = remaining_frame_samples;
2301 samples + (audio_input_position
2302 * (av_get_bytes_per_sample(output_sample_fmt) /
2303 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2305 all_resampled_samples + samples_position,
2306 static_cast<size_t>(diff)
2307 * av_get_bytes_per_sample(output_sample_fmt)
2311 audio_input_position += diff;
2312 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
2313 remaining_frame_samples -= diff;
2316 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
2323 const int frame_nb_samples = audio_input_position /
info.
channels;
2324 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
2326 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
2327 "in_sample_fmt", output_sample_fmt,
2328 "out_sample_fmt", audio_codec_ctx->sample_fmt,
2339 AVChannelLayout layout = ffmpeg_default_channel_layout(
info.
channels);
2343 av_opt_set_chlayout(avr_planar,
"in_chlayout", &layout, 0);
2344 av_opt_set_chlayout(avr_planar,
"out_chlayout", &layout, 0);
2348 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
2349 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
2351 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
2352 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
2361 audio_frame->nb_samples = audio_input_position /
info.
channels;
2364 final_samples_planar = (int16_t *) av_malloc(
2365 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
2366 * (av_get_bytes_per_sample(output_sample_fmt) /
2367 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
2371 memcpy(final_samples_planar, samples,
2372 static_cast<size_t>(audio_frame->nb_samples)
2374 * av_get_bytes_per_sample(output_sample_fmt));
2377 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
2378 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
2381 frame_final->nb_samples = frame_nb_samples;
2388 frame_final->format = audio_codec_ctx->sample_fmt;
2389 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
2390 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
2396 frame_final->linesize[0],
2397 frame_final->nb_samples,
2399 audio_frame->linesize[0],
2400 audio_frame->nb_samples
2404 const auto copy_length =
static_cast<size_t>(nb_samples)
2405 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
2409 memcpy(samples, frame_final->data[0], copy_length);
2412 av_freep(&(audio_frame->data[0]));
2414 all_queued_samples = NULL;
2417 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
2418 "nb_samples", nb_samples);
2422 const auto buf_size =
static_cast<size_t>(audio_input_position)
2423 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
2424 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
2426 final_samples =
reinterpret_cast<int16_t*
>(
2427 av_malloc(
sizeof(int16_t) * buf_size));
2430 memcpy(final_samples, samples,
2431 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
2434 frame_final->nb_samples = frame_nb_samples;
2435 frame_final->format = audio_codec_ctx->sample_fmt;
2437 av_channel_layout_copy(&frame_final->ch_layout, &audio_codec_ctx->ch_layout);
2439 frame_final->channels = audio_codec_ctx->channels;
2440 frame_final->channel_layout = audio_codec_ctx->channel_layout;
2445 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
2447 int nb_channels = audio_codec_ctx->channels;
2449 avcodec_fill_audio_frame(frame_final, nb_channels,
2450 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
2451 audio_encoder_buffer_size, 0);
2455 frame_final->pts = audio_timestamp;
2459 AVPacket* pkt = av_packet_alloc();
2462 av_init_packet(pkt);
2463 pkt->data = audio_encoder_buffer;
2464 pkt->size = audio_encoder_buffer_size;
2468 pkt->pts = pkt->dts = audio_timestamp;
2471 int got_packet_ptr = 0;
2477 int frame_finished = 0;
2478 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
2479 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF
2480 && audio_codec_ctx->codec
2481 && (audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
2482 avcodec_send_frame(audio_codec_ctx, NULL);
2487 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
2490 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
2494 ret = frame_finished;
2497 if (!pkt->data && !frame_finished)
2501 got_packet_ptr = ret;
2504 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
2507 if (error_code == 0 && got_packet_ptr > 0) {
2511 if (pkt->pts == AV_NOPTS_VALUE)
2512 pkt->pts = audio_timestamp;
2513 if (pkt->dts == AV_NOPTS_VALUE)
2514 pkt->dts = pkt->pts;
2515 if (pkt->duration <= 0) {
2516 pkt->duration = frame_nb_samples;
2520 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2523 pkt->stream_index = audio_st->index;
2524 pkt->flags |= AV_PKT_FLAG_KEY;
2527 error_code = av_interleaved_write_frame(oc, pkt);
2530 if (error_code < 0) {
2532 "FFmpegWriter::write_audio_packets ERROR ["
2533 + av_err2string(error_code) +
"]",
2534 "error_code", error_code);
2538 audio_timestamp += frame_nb_samples;
2541 av_freep(&(frame_final->data[0]));
2548 audio_input_position = 0;
2553 if (all_resampled_samples) {
2554 av_freep(&all_resampled_samples);
2555 all_resampled_samples = NULL;
2557 if (all_queued_samples) {
2558 av_freep(&all_queued_samples);
2559 all_queued_samples = NULL;
2564AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2566 AVFrame *new_av_frame = NULL;
2570 if (new_av_frame == NULL)
2571 throw OutOfMemory(
"Could not allocate AVFrame", path);
2578 int palette_padding = 0;
2579#ifdef AV_PIX_FMT_FLAG_PSEUDOPAL
2583 if (av_pix_fmt_desc_get(pix_fmt)->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)
2584 palette_padding = 1024;
2587 new_buffer = (uint8_t *) av_malloc(*buffer_size + palette_padding);
2589 throw OutOfMemory(
"Could not allocate video frame buffer", path);
2590 if (palette_padding)
2591 memset(new_buffer + *buffer_size, 0, palette_padding);
2594 new_av_frame->width = width;
2595 new_av_frame->height = height;
2596 new_av_frame->format = pix_fmt;
2600 return new_av_frame;
2604void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2606 int src_w = frame->GetWidth();
2607 int src_h = frame->GetHeight();
2610 if (src_w == 1 && src_h == 1)
2614 const uchar* pixels = frame->GetPixels();
2615 if (!persistent_src_frame) {
2616 persistent_src_frame = av_frame_alloc();
2617 if (!persistent_src_frame)
2618 throw OutOfMemory(
"Could not allocate persistent_src_frame", path);
2619 persistent_src_frame->format = AV_PIX_FMT_RGBA;
2620 persistent_src_frame->width = src_w;
2621 persistent_src_frame->height = src_h;
2622 persistent_src_frame->linesize[0] = src_w * 4;
2624 persistent_src_frame->data[0] =
const_cast<uint8_t*
>(
2625 reinterpret_cast<const uint8_t*
>(pixels)
2629 if (!persistent_dst_frame) {
2630 persistent_dst_frame = av_frame_alloc();
2631 if (!persistent_dst_frame)
2632 throw OutOfMemory(
"Could not allocate persistent_dst_frame", path);
2635 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2638 dst_fmt = AV_PIX_FMT_NV12;
2641 persistent_dst_frame->format = dst_fmt;
2642 persistent_dst_frame->width =
info.
width;
2645 persistent_dst_size = av_image_get_buffer_size(
2648 if (persistent_dst_size < 0)
2651 persistent_dst_buffer =
static_cast<uint8_t*
>(
2652 av_malloc(persistent_dst_size)
2654 if (!persistent_dst_buffer)
2655 throw OutOfMemory(
"Could not allocate persistent_dst_buffer", path);
2657 av_image_fill_arrays(
2658 persistent_dst_frame->data,
2659 persistent_dst_frame->linesize,
2660 persistent_dst_buffer,
2669 if (!img_convert_ctx) {
2670 int flags = SWS_FAST_BILINEAR;
2672 flags = SWS_BICUBIC;
2674 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2677 dst_fmt = AV_PIX_FMT_NV12;
2680 img_convert_ctx = sws_getContext(
2681 src_w, src_h, AV_PIX_FMT_RGBA,
2683 flags, NULL, NULL, NULL
2685 if (!img_convert_ctx)
2692 persistent_src_frame->data,
2693 persistent_src_frame->linesize,
2695 persistent_dst_frame->data,
2696 persistent_dst_frame->linesize
2700 int bytes_final = 0;
2701 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2704 dst_fmt = AV_PIX_FMT_NV12;
2708 AVFrame* new_frame = allocate_avframe(
2716 throw OutOfMemory(
"Could not allocate new_frame via allocate_avframe", path);
2719#ifdef AV_PIX_FMT_FLAG_PSEUDOPAL
2722 if (av_pix_fmt_desc_get(dst_fmt)->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
2723 av_image_copy_plane(new_frame->data[0], new_frame->linesize[0],
2724 persistent_dst_frame->data[0], persistent_dst_frame->linesize[0],
2728 av_image_copy(new_frame->data, new_frame->linesize,
2729 const_cast<const uint8_t**
>(persistent_dst_frame->data),
2733 add_avframe(frame, new_frame);
2737bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2738#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2741 "FFmpegWriter::write_video_packet",
2742 "frame->number", frame->number,
2743 "oc->oformat->flags", oc->oformat->flags);
2751 "FFmpegWriter::write_video_packet",
2752 "frame->number", frame->number,
2753 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2755 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2759 AVPacket packet = {};
2761 const int size =
AV_GET_IMAGE_SIZE(format, frame_final->width, frame_final->height);
2762 int error_code = size < 0 ? size : av_new_packet(&packet, size);
2763 if (error_code >= 0) {
2765 error_code = av_image_copy_to_buffer(packet.data, packet.size,
2766 frame_final->data, frame_final->linesize, format,
2767 frame_final->width, frame_final->height, 1);
2769 if (error_code >= 0) {
2770 packet.flags |= AV_PKT_FLAG_KEY;
2771 packet.stream_index = video_st->index;
2772 packet.pts = packet.dts = video_timestamp;
2773 packet.duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2774 av_packet_rescale_ts(&packet, video_codec_ctx->time_base, video_st->time_base);
2775 error_code = av_interleaved_write_frame(oc, &packet);
2778 if (error_code < 0) {
2780 "FFmpegWriter::write_video_packet ERROR ["
2781 + av_err2string(error_code) +
"]",
2782 "error_code", error_code);
2789 AVPacket* pkt = av_packet_alloc();
2792 av_init_packet(pkt);
2796 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2799 frame_final->pts = video_timestamp;
2802 if (!(
hw_frame = av_frame_alloc())) {
2803 std::clog <<
"Error code: av_hwframe_alloc\n";
2805 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2806 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2809 std::clog <<
"Error hw_frames_ctx.\n";
2813 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2814 std::clog <<
"Error while transferring frame data to surface.\n";
2816 av_frame_copy_props(
hw_frame, frame_final);
2820 int got_packet_ptr = 0;
2828 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2832 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2837 "FFmpegWriter::write_video_packet (Frame not sent)");
2838 if (ret == AVERROR(EAGAIN) ) {
2839 std::clog <<
"Frame EAGAIN\n";
2841 if (ret == AVERROR_EOF ) {
2842 std::clog <<
"Frame AVERROR_EOF\n";
2844 avcodec_send_frame(video_codec_ctx, NULL);
2848 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2850 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2862 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2863 if (error_code != 0) {
2865 "FFmpegWriter::write_video_packet ERROR ["
2866 + av_err2string(error_code) +
"]",
2867 "error_code", error_code);
2869 if (got_packet_ptr == 0) {
2871 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2876 if (error_code == 0 && got_packet_ptr) {
2878 if (pkt->duration <= 0) {
2879 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2881 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2882 pkt->stream_index = video_st->index;
2885 int result = av_interleaved_write_frame(oc, pkt);
2888 "FFmpegWriter::write_video_packet ERROR ["
2889 + av_err2string(result) +
"]",
2908 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2917 av_dump_format(oc, 0, path.c_str(), 1);
2922 original_sample_rate = sample_rate;
2923 original_channels = channels;
2932 oc->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
2934#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
2936 int proj = av_spherical_from_name(projection.c_str());
2938 proj = AV_SPHERICAL_EQUIRECTANGULAR;
2942 AVSphericalMapping* map = av_spherical_alloc(&sd_size);
2946 map->projection =
static_cast<AVSphericalProjection
>(proj);
2948 map->yaw =
static_cast<int32_t
>(yaw_deg * (1 << 16));
2949 map->pitch =
static_cast<int32_t
>(pitch_deg * (1 << 16));
2950 map->roll =
static_cast<int32_t
>(roll_deg * (1 << 16));
2952#if LIBAVFORMAT_VERSION_MAJOR >= 61
2955 AVPacketSideData* side_data = av_packet_side_data_add(
2956 &video_codec_ctx->coded_side_data, &video_codec_ctx->nb_coded_side_data,
2957 AV_PKT_DATA_SPHERICAL,
reinterpret_cast<uint8_t*
>(map), sd_size, 0);
2961 if (ffmpeg_stream_add_side_data(video_st, AV_PKT_DATA_SPHERICAL,
2962 reinterpret_cast<uint8_t*
>(map), sd_size) < 0)
Header file for all Exception classes.
Header file for FFmpegUtilities.
#define AV_FREE_CONTEXT(av_context)
#define AUDIO_PACKET_ENCODING_SIZE
#define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in)
#define AV_SET_FILENAME(oc, f)
#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 AV_GET_CODEC_TYPE(av_stream)
#define ALLOC_CODEC_CTX(ctx, codec, stream)
#define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
#define AV_ALLOCATE_FRAME()
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)
#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)
AVPixelFormat hw_en_av_pix_fmt
if(avcodec_open2(video_codec_ctx, codec, &opts)< 0) throw InvalidCodec("Could not open video codec"
AVHWDeviceType hw_en_av_device_type
Header file for FFmpegWriter class.
Header file for Frame class.
Header file for OpenMPUtilities (set some common macros)
#define FF_VIDEO_NUM_PROCESSORS
#define FF_AUDIO_NUM_PROCESSORS
Header file for global Settings class.
Exception when encoding audio packet.
Exception when encoding audio packet.
Base exception class with a custom message variable.
virtual const char * what() const noexcept
static std::string GetEncoders(std::string media_type, std::string format_name="")
List the available encoders as a JSON array.
void Close()
Close the writer.
void SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, openshot::ChannelLayout channel_layout, int bit_rate)
Set audio export options.
void SetOption(openshot::StreamType stream, std::string name, std::string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
static std::string GetFormats()
List the file extensions the writer can export to, as a JSON array.
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
void SetVideoOptions(bool has_video, std::string codec, openshot::Fraction fps, int width, int height, openshot::Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
void WriteFrameAt(std::shared_ptr< openshot::Frame > frame, int64_t frame_number)
Add a frame at a specific output video frame number.
static std::string GetFormatInfo(std::string format_name)
Describe an output format as JSON (name, extensions, and default codecs).
static int IsCodecSupportedByFormat(std::string format_name, std::string codec_name)
Determine if an output format can store a codec.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
static std::string GetEncoderInfo(std::string codec_name)
Describe an encoder's capabilities as JSON.
void AddSphericalMetadata(const std::string &projection="equirectangular", float yaw_deg=0.0f, float pitch_deg=0.0f, float roll_deg=0.0f)
Add spherical (360°) video metadata to the video stream.
void WriteHeader()
Write the file header (after the options are set). This method is called automatically by the Open() ...
FFmpegWriter(const std::string &path)
Constructor for FFmpegWriter. Throws an exception on failure to open path.
static bool IsValidCodec(std::string codec_name)
Determine if codec name is valid.
void OutputStreamInfo()
Output the ffmpeg info about this format, streams, and codecs (i.e. dump format)
std::string Test()
Check the current settings without writing a file, and return the result as JSON.
void WriteFrame(std::shared_ptr< openshot::Frame > frame)
Add a frame to the stack waiting to be encoded.
void WriteTrailer()
Write the file trailer (after all frames are written). This is called automatically by the Close() me...
This class represents a fraction.
int num
Numerator for the fraction.
void Reduce()
Reduce this fraction (i.e. 640/480 = 4/3)
int den
Denominator for the fraction.
Exception when an invalid # of audio channels are detected.
Exception when no valid codec is found for a file.
Exception for files that can not be found or opened.
Exception when invalid encoding options are used.
Exception when invalid sample rate is detected during encoding.
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)
static Logger * Instance()
Exception when no streams are found in the file.
Exception when memory could not be allocated.
This abstract class is the base class, used by all readers in libopenshot.
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)
int HW_EN_DEVICE_SET
Which GPU to use to encode (0 is the first)
WriterInfo info
Information about the current media file.
Exception when a writer is closed, and a frame is requested.
This namespace is the default namespace for all code in the openshot library.
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
StreamType
This enumeration designates the type of stream when encoding (video or audio)
@ AUDIO_STREAM
An audio stream (used to determine which type of stream)
@ VIDEO_STREAM
A video stream (used to determine which type of stream)
int height
The height of the video (in pixels)
int audio_bit_rate
The bit rate of the audio stream (in bytes)
int video_bit_rate
The bit rate of the video stream (in bytes)
bool has_audio
Determines if this file has an audio stream.
bool top_field_first
Which interlaced field should be displayed first.
int channels
The number of audio channels used in the audio stream.
std::string vcodec
The name of the video codec used to encode / decode the video stream.
bool has_video
Determines if this file has a video stream.
std::map< std::string, std::string > metadata
An optional map/dictionary of video & audio metadata.
openshot::Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
std::string acodec
The name of the audio codec used to encode / decode the video stream.
openshot::Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
openshot::ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
openshot::Fraction display_ratio
The ratio of width to height of the video stream (i.e. 640x480 has a ratio of 4/3)
int width
The width of the video (in pixels)
openshot::Fraction pixel_ratio
The pixel ratio of the video stream as a fraction (i.e. some pixels are not square)
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
bool interlaced_frame
Are the contents of this frame interlaced.