42 static AVBufferRef *hw_device_ctx = NULL;
45 static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
47 AVBufferRef *hw_frames_ref;
48 AVHWFramesContext *frames_ctx = NULL;
51 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
52 std::clog <<
"Failed to create HW frame context.\n";
55 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
57 frames_ctx->sw_format = AV_PIX_FMT_NV12;
58 frames_ctx->width = width;
59 frames_ctx->height = height;
60 frames_ctx->initial_pool_size = 20;
61 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
62 std::clog <<
"Failed to initialize HW frame context. " <<
63 "Error code: " << av_err2string(err) <<
"\n";
64 av_buffer_unref(&hw_frames_ref);
67 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
68 if (!ctx->hw_frames_ctx)
69 err = AVERROR(ENOMEM);
71 av_buffer_unref(&hw_frames_ref);
77 path(
path), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
78 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
79 initial_audio_input_frame_size(0), img_convert_ctx(NULL),
80 video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
81 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
82 write_header(false), write_trailer(false), allow_b_frames(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
102 if (!prepare_streams)
107 open_video(oc, video_st);
109 open_audio(oc, audio_st);
118 void FFmpegWriter::auto_detect_format() {
124 "Could not allocate memory for AVFormatContext.", path);
128 oc->oformat = av_guess_format(NULL, path.c_str(), NULL);
129 if (oc->oformat ==
nullptr) {
130 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
134 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video) {
135 const AVCodec *vcodec = avcodec_find_encoder(oc->oformat->video_codec);
136 info.
vcodec = vcodec ? vcodec->name : std::string();
138 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio) {
139 const AVCodec *acodec = avcodec_find_encoder(oc->oformat->audio_codec);
140 info.
acodec = acodec ? acodec->name : std::string();
145 void FFmpegWriter::initialize_streams() {
147 "FFmpegWriter::initialize_streams",
148 "oc->oformat->video_codec", oc->oformat->video_codec,
149 "oc->oformat->audio_codec", oc->oformat->audio_codec,
150 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
155 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
157 video_st = add_video_stream();
159 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
161 audio_st = add_audio_stream();
167 if (
codec.length() > 0) {
168 const AVCodec *new_codec;
171 #if defined(__linux__)
172 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
173 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
178 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
179 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
185 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
189 #elif defined(_WIN32)
190 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
191 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
196 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
197 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
203 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
207 #elif defined(__APPLE__)
208 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
209 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
215 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
220 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
223 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
225 if (new_codec == NULL)
226 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
245 if (pixel_ratio.
num > 0) {
249 if (bit_rate >= 1000)
251 if ((bit_rate >= 0) && (bit_rate < 256))
268 "FFmpegWriter::SetVideoOptions (" +
codec +
")",
269 "width", width,
"height", height,
270 "size.num", size.
num,
"size.den", size.
den,
271 "fps.num", fps.
num,
"fps.den", fps.
den);
281 true,
codec, fps, width, height,
290 if (
codec.length() > 0) {
291 const AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
292 if (new_codec == NULL)
293 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
299 if (sample_rate > 7999)
308 if (original_sample_rate == 0)
310 if (original_channels == 0)
314 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
315 "sample_rate", sample_rate,
316 "channels", channels,
317 "bit_rate", bit_rate);
328 true,
codec, sample_rate, 2,
337 AVCodecContext *c = NULL;
339 std::stringstream convert(value);
358 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
361 const AVOption *option = NULL;
369 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
370 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
371 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp" || name ==
"allow_b_frames")) {
375 convert >> c->gop_size;
377 else if (name ==
"qmin")
381 else if (name ==
"qmax")
385 else if (name ==
"max_b_frames")
387 convert >> c->max_b_frames;
389 else if (name ==
"allow_b_frames")
392 allow_b_frames = (value ==
"1" || value ==
"true" || value ==
"yes" || value ==
"on");
394 else if (name ==
"mb_decision")
396 convert >> c->mb_decision;
398 else if (name ==
"level")
402 else if (name ==
"profile")
404 convert >> c->profile;
406 else if (name ==
"slices")
408 convert >> c->slices;
410 else if (name ==
"rc_min_rate")
412 convert >> c->rc_min_rate;
414 else if (name ==
"rc_max_rate")
416 convert >> c->rc_max_rate;
418 else if (name ==
"rc_buffer_size")
420 convert >> c->rc_buffer_size;
422 else if (name ==
"cqp") {
426 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
430 switch (c->codec_id) {
431 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
433 case AV_CODEC_ID_AV1 :
435 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
438 case AV_CODEC_ID_VP8 :
439 c->bit_rate = 10000000;
440 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
442 case AV_CODEC_ID_VP9 :
444 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
445 if (std::stoi(value) == 0) {
446 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
447 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
450 case AV_CODEC_ID_H264 :
451 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
452 if (std::stoi(value) == 0) {
453 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
457 case AV_CODEC_ID_HEVC :
458 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
459 if (std::stoi(value) == 0) {
460 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
461 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
466 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
470 }
else if (name ==
"crf") {
474 double mbs = 15000000.0;
483 c->bit_rate = (int)(mbs);
487 switch (c->codec_id) {
488 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
490 case AV_CODEC_ID_AV1 :
493 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
496 case AV_CODEC_ID_VP8 :
497 c->bit_rate = 10000000;
498 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
500 case AV_CODEC_ID_VP9 :
502 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
503 if (std::stoi(value) == 0) {
504 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
505 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
508 case AV_CODEC_ID_H264 :
509 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
510 if (std::stoi(value) == 0) {
511 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
515 case AV_CODEC_ID_HEVC :
516 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
517 av_opt_set_int(c->priv_data,
"preset", 7, 0);
518 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
519 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
522 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
524 if (std::stoi(value) == 0) {
525 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
526 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
532 double mbs = 15000000.0;
540 c->bit_rate = (int) (mbs);
543 }
else if (name ==
"qp") {
545 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
547 switch (c->codec_id) {
548 case AV_CODEC_ID_AV1 :
550 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
551 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
553 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
556 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
558 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
562 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
565 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
567 case AV_CODEC_ID_HEVC :
569 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
570 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
571 av_opt_set_int(c->priv_data,
"preset", 7, 0);
572 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
579 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
583 "FFmpegWriter::SetOption (" + (std::string)name +
")",
588 }
else if (name ==
"muxing_preset") {
589 if (value ==
"mp4_faststart") {
591 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
592 }
else if (value ==
"mp4_fragmented") {
594 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
595 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
598 throw InvalidOptions(
"The option is not valid for this codec.", path);
609 return avcodec_find_encoder_by_name(codec_name.c_str()) != NULL;
615 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
618 "FFmpegWriter::PrepareStreams [" + path +
"]",
623 initialize_streams();
626 prepare_streams =
true;
632 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
635 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
636 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
637 throw InvalidFile(
"Could not open or write file.", path);
645 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
649 AVDictionary *dict = NULL;
655 if (avformat_write_header(oc, &dict) != 0) {
657 "FFmpegWriter::WriteHeader (avformat_write_header)");
658 throw InvalidFile(
"Could not write header to file.", path);
662 if (dict) av_dict_free(&dict);
675 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
678 "FFmpegWriter::WriteFrame",
679 "frame->number", frame->number,
680 "is_writing", is_writing);
692 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
694 if (frame_number < 1) {
699 "FFmpegWriter::WriteFrameAt",
700 "frame->number", frame->number,
701 "output_frame_number", frame_number,
702 "is_writing", is_writing);
704 const int64_t previous_video_timestamp = video_timestamp;
706 video_timestamp = av_rescale_q(
709 video_codec_ctx->time_base);
715 video_timestamp = previous_video_timestamp;
722 void FFmpegWriter::write_frame(std::shared_ptr<Frame> frame) {
727 bool has_error_encoding_video =
false;
731 write_audio_packets(
false, frame);
735 process_video_packet(frame);
739 if (av_frames.count(frame)) {
741 AVFrame *frame_final = av_frames[frame];
744 if (!write_video_packet(frame, frame_final)) {
745 has_error_encoding_video =
true;
749 av_freep(&(frame_final->data[0]));
751 av_frames.erase(frame);
759 if (has_error_encoding_video)
766 "FFmpegWriter::WriteFrame (from Reader)",
771 for (int64_t number = start; number <= length; number++) {
773 std::shared_ptr<Frame> f = reader->
GetFrame(number);
784 write_audio_packets(
true, NULL);
789 if (
info.
has_audio && audio_st && audio_codec_ctx && audio_timestamp > 0) {
790 audio_st->duration = av_rescale_q(
792 audio_codec_ctx->time_base,
793 audio_st->time_base);
800 av_write_trailer(oc);
803 write_trailer =
true;
809 void FFmpegWriter::flush_encoders() {
812 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
826 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
829 AVPacket* pkt = av_packet_alloc();
843 error_code = avcodec_send_frame(video_codec_ctx, NULL);
845 while (error_code >= 0) {
846 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
847 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
850 avcodec_flush_buffers(video_codec_ctx);
853 if (pkt->duration <= 0) {
854 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
856 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
857 pkt->stream_index = video_st->index;
858 error_code = av_interleaved_write_frame(oc, pkt);
863 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
867 if (error_code < 0) {
869 "FFmpegWriter::flush_encoders ERROR ["
870 + av_err2string(error_code) +
"]",
871 "error_code", error_code);
878 if (pkt->duration <= 0) {
879 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
881 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
882 pkt->stream_index = video_st->index;
885 error_code = av_interleaved_write_frame(oc, pkt);
886 if (error_code < 0) {
888 "FFmpegWriter::flush_encoders ERROR ["
889 + av_err2string(error_code) +
"]",
890 "error_code", error_code);
899 AVPacket* pkt = av_packet_alloc();
906 pkt->pts = pkt->dts = audio_timestamp;
912 if (!audio_codec_ctx->codec || !(audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
913 av_packet_free(&pkt);
916 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
917 if (error_code < 0 && error_code != AVERROR_EOF) {
919 "FFmpegWriter::flush_encoders ERROR ["
920 + av_err2string(error_code) +
"]",
921 "error_code", error_code);
924 error_code = avcodec_receive_packet(audio_codec_ctx, pkt);
925 if (error_code == AVERROR(EAGAIN) || error_code == AVERROR_EOF) {
929 if (error_code < 0) {
931 "FFmpegWriter::flush_encoders ERROR ["
932 + av_err2string(error_code) +
"]",
933 "error_code", error_code);
939 if (pkt->pts == AV_NOPTS_VALUE) {
940 pkt->pts = audio_timestamp;
942 if (pkt->dts == AV_NOPTS_VALUE) {
945 if (pkt->duration <= 0) {
946 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
948 const int64_t packet_duration = pkt->duration;
949 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
950 pkt->stream_index = audio_st->index;
951 pkt->flags |= AV_PKT_FLAG_KEY;
953 error_code = av_interleaved_write_frame(oc, pkt);
954 if (error_code < 0) {
956 "FFmpegWriter::flush_encoders ERROR ["
957 + av_err2string(error_code) +
"]",
958 "error_code", error_code);
960 audio_timestamp += packet_duration;
963 av_packet_free(&pkt);
966 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
967 if (error_code < 0) {
969 "FFmpegWriter::flush_encoders ERROR ["
970 + av_err2string(error_code) +
"]",
971 "error_code", error_code);
979 pkt->pts = pkt->dts = audio_timestamp;
980 if (pkt->duration <= 0) {
981 pkt->duration = audio_codec_ctx->frame_size > 0 ? audio_codec_ctx->frame_size : audio_input_frame_size;
985 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
988 pkt->stream_index = audio_st->index;
989 pkt->flags |= AV_PKT_FLAG_KEY;
992 error_code = av_interleaved_write_frame(oc, pkt);
993 if (error_code < 0) {
995 "FFmpegWriter::flush_encoders ERROR ["
996 + av_err2string(error_code) +
"]",
997 "error_code", error_code);
1001 audio_timestamp += pkt->duration;
1012 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
1016 if (hw_device_ctx) {
1017 av_buffer_unref(&hw_device_ctx);
1018 hw_device_ctx = NULL;
1024 if (video_codec_ctx !=
nullptr) {
1026 av_free(video_codec_ctx);
1031 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
1035 delete[] audio_outbuf;
1036 delete[] audio_encoder_buffer;
1038 audio_outbuf = NULL;
1039 audio_encoder_buffer = NULL;
1055 if (audio_codec_ctx !=
nullptr) {
1057 av_free(audio_codec_ctx);
1069 close_video(oc, video_st);
1071 close_audio(oc, audio_st);
1074 if (img_convert_ctx)
1075 sws_freeContext(img_convert_ctx);
1077 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1083 video_timestamp = 0;
1084 audio_timestamp = 0;
1087 avformat_free_context(oc);
1092 prepare_streams =
false;
1093 write_header =
false;
1094 write_trailer =
false;
1100 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1102 if (!av_frames.count(frame)) {
1104 av_frames[frame] = av_frame;
1112 AVStream *FFmpegWriter::add_audio_stream() {
1114 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1116 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1119 if (audio_codec_ctx !=
nullptr) {
1124 AVStream* st = avformat_new_stream(oc,
codec);
1126 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
1130 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1131 st->codecpar->codec_id =
codec->id;
1133 AVCodecContext* c = audio_codec_ctx;
1135 c->codec_id =
codec->id;
1136 c->codec_type = AVMEDIA_TYPE_AUDIO;
1145 if (
codec->supported_samplerates) {
1147 for (i = 0;
codec->supported_samplerates[i] != 0; i++)
1153 if (
codec->supported_samplerates[i] == 0)
1154 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1159 c->time_base = AVRational{1, c->sample_rate};
1160 st->time_base = c->time_base;
1165 AVChannelLayout ch_layout;
1167 if (
codec->ch_layouts) {
1169 for (i = 0; av_channel_layout_check(&
codec->ch_layouts[i]); i++)
1170 if (av_channel_layout_compare(&ch_layout, &
codec->ch_layouts[i])) {
1172 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1175 if (!av_channel_layout_check(&
codec->ch_layouts[i]))
1176 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1179 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1182 if (
codec->channel_layouts) {
1184 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1185 if (channel_layout ==
codec->channel_layouts[i]) {
1187 c->channel_layout = channel_layout;
1190 if (
codec->channel_layouts[i] == 0)
1191 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1194 c->channel_layout = channel_layout;
1198 if (
codec->sample_fmts) {
1199 for (
int i = 0;
codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1201 c->sample_fmt =
codec->sample_fmts[i];
1205 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1207 c->sample_fmt = AV_SAMPLE_FMT_S16;
1211 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1212 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1214 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1216 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1222 const char* nb_channels_label;
1223 const char* channel_layout_label;
1226 nb_channels = c->ch_layout.nb_channels;
1227 channel_layout = c->ch_layout.u.mask;
1228 nb_channels_label =
"c->ch_layout.nb_channels";
1229 channel_layout_label =
"c->ch_layout.u.mask";
1231 nb_channels = c->channels;
1232 nb_channels_label =
"c->channels";
1233 channel_layout_label =
"c->channel_layout";
1237 "FFmpegWriter::add_audio_stream",
1238 "c->codec_id", c->codec_id,
1239 "c->bit_rate", c->bit_rate,
1240 nb_channels_label, nb_channels,
1241 "c->sample_fmt", c->sample_fmt,
1242 channel_layout_label, channel_layout,
1243 "c->sample_rate", c->sample_rate);
1249 AVStream *FFmpegWriter::add_video_stream() {
1251 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1253 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1256 if (video_codec_ctx !=
nullptr) {
1261 AVStream* st = avformat_new_stream(oc,
codec);
1263 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1267 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1268 st->codecpar->codec_id =
codec->id;
1271 AVCodecContext* c = video_codec_ctx;
1273 c->codec_id =
codec->id;
1274 c->codec_type = AVMEDIA_TYPE_VIDEO;
1282 #
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1283 && c->codec_id != AV_CODEC_ID_AV1
1288 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1297 switch (c->codec_id) {
1298 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
1300 case AV_CODEC_ID_AV1 :
1304 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1305 int calculated_quality = 35;
1308 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1311 int calculated_quality = 50;
1314 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1318 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1319 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1320 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1322 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1323 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1324 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1325 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1327 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1330 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1331 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1332 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1333 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1337 case AV_CODEC_ID_VP9 :
1338 case AV_CODEC_ID_HEVC :
1339 case AV_CODEC_ID_VP8 :
1340 case AV_CODEC_ID_H264 :
1376 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1377 c->framerate = av_inv_q(c->time_base);
1379 st->avg_frame_rate = av_inv_q(c->time_base);
1380 st->r_frame_rate = av_inv_q(c->time_base);
1385 c->max_b_frames = 10;
1386 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1388 c->max_b_frames = 2;
1389 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1395 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1396 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1398 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1400 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1405 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1408 c->pix_fmt = *supported_pixel_formats;
1409 ++supported_pixel_formats;
1414 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1418 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1420 if (strcmp(oc->oformat->name,
"gif") != 0)
1423 oc->oformat->flags |= AVFMT_RAWPICTURE;
1433 "FFmpegWriter::add_video_stream ("
1434 + (std::string)oc->oformat->name +
" : "
1435 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1436 "c->codec_id", c->codec_id,
1437 "c->bit_rate", c->bit_rate,
1438 "c->pix_fmt", c->pix_fmt,
1439 "oc->oformat->flags", oc->oformat->flags);
1444 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1445 const AVCodec *
codec;
1454 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1459 AVDictionary *
opts = NULL;
1460 av_dict_set(&
opts,
"strict",
"experimental", 0);
1463 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1464 throw InvalidCodec(
"Could not open audio codec", path);
1468 av_dict_free(&
opts);
1472 if (audio_codec_ctx->frame_size <= 1) {
1478 case AV_CODEC_ID_PCM_S16LE:
1479 case AV_CODEC_ID_PCM_S16BE:
1480 case AV_CODEC_ID_PCM_U16LE:
1481 case AV_CODEC_ID_PCM_U16BE:
1482 audio_input_frame_size >>= 1;
1489 audio_input_frame_size = audio_codec_ctx->frame_size;
1493 initial_audio_input_frame_size = audio_input_frame_size;
1500 audio_outbuf =
new uint8_t[audio_outbuf_size];
1504 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1507 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1508 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1512 "FFmpegWriter::open_audio",
1513 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1514 "audio_input_frame_size", audio_input_frame_size,
1519 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1520 const AVCodec *
codec;
1530 char *adapter_ptr = NULL;
1534 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1535 if (adapter_num < 3 && adapter_num >=0) {
1536 #if defined(__linux__)
1537 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1539 adapter_ptr = adapter;
1540 #elif defined(_WIN32) || defined(__APPLE__)
1548 #if defined(__linux__)
1549 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1550 #elif defined(_WIN32) || defined(__APPLE__)
1551 if( adapter_ptr != NULL ) {
1554 "Encode Device present using device",
1555 "adapter", adapter_num);
1560 "Encode Device not present, using default");
1562 if (av_hwdevice_ctx_create(&hw_device_ctx,
1566 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1582 if (!allow_b_frames && video_codec_ctx->max_b_frames &&
1583 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 &&
1584 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO &&
1585 video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1586 video_codec_ctx->max_b_frames = 0;
1590 av_dict_set(&
opts,
"strict",
"experimental", 0);
1604 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1606 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1610 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1614 switch (video_codec_ctx->codec_id) {
1615 case AV_CODEC_ID_H264:
1616 video_codec_ctx->max_b_frames = 0;
1617 video_codec_ctx->profile = AV_PROFILE_H264_CONSTRAINED_BASELINE;
1618 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1619 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1620 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1622 case AV_CODEC_ID_HEVC:
1625 case AV_CODEC_ID_VP9:
1630 "No codec-specific options defined for this codec. HW encoding may fail",
1631 "codec_id", video_codec_ctx->codec_id);
1640 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1643 av_err2string(err), -1);
1651 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
1654 if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
1655 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
1661 throw InvalidCodec(
"Could not open video codec", path);
1667 av_dict_free(&
opts);
1671 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1675 "FFmpegWriter::open_video",
1676 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1681 void FFmpegWriter::write_audio_packets(
bool is_final, std::shared_ptr<openshot::Frame> frame) {
1682 if (!frame && !is_final)
1686 int total_frame_samples = 0;
1687 int frame_position = 0;
1688 int channels_in_frame = 0;
1689 int sample_rate_in_frame = 0;
1690 int samples_in_frame = 0;
1695 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1696 int16_t *all_resampled_samples = NULL;
1697 int16_t *final_samples_planar = NULL;
1698 int16_t *final_samples = NULL;
1701 float *frame_samples_float = NULL;
1705 sample_rate_in_frame = frame->SampleRate();
1706 samples_in_frame = frame->GetAudioSamplesCount();
1707 channels_in_frame = frame->GetAudioChannelsCount();
1708 channel_layout_in_frame = frame->ChannelsLayout();
1711 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1715 total_frame_samples = samples_in_frame * channels_in_frame;
1718 const int16_t max16 = 32767;
1719 const int16_t min16 = -32768;
1720 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1721 float valF = frame_samples_float[s] * (1 << 15);
1725 }
else if (valF < min16) {
1728 conv = int(valF + 32768.5) - 32768;
1732 all_queued_samples[frame_position] = conv;
1736 delete[] frame_samples_float;
1740 total_frame_samples = frame_position;
1741 int remaining_frame_samples = total_frame_samples;
1742 int samples_position = 0;
1746 "FFmpegWriter::write_audio_packets",
1747 "is_final", is_final,
1748 "total_frame_samples", total_frame_samples,
1749 "channel_layout_in_frame", channel_layout_in_frame,
1750 "channels_in_frame", channels_in_frame,
1751 "samples_in_frame", samples_in_frame,
1755 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1757 AVFrame *audio_frame = NULL;
1762 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1765 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);
1766 if (error_code < 0) {
1768 "FFmpegWriter::write_audio_packets ERROR ["
1769 + av_err2string(error_code) +
"]",
1770 "error_code", error_code);
1774 switch (audio_codec_ctx->sample_fmt) {
1775 case AV_SAMPLE_FMT_FLTP: {
1776 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1779 case AV_SAMPLE_FMT_S32P: {
1780 output_sample_fmt = AV_SAMPLE_FMT_S32;
1783 case AV_SAMPLE_FMT_S16P: {
1784 output_sample_fmt = AV_SAMPLE_FMT_S16;
1787 case AV_SAMPLE_FMT_U8P: {
1788 output_sample_fmt = AV_SAMPLE_FMT_U8;
1798 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1799 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1804 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1805 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1808 "FFmpegWriter::write_audio_packets (1st resampling)",
1809 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1810 "out_sample_fmt", output_sample_fmt,
1811 "in_sample_rate", sample_rate_in_frame,
1813 "in_channels", channels_in_frame,
1820 AVChannelLayout in_chlayout = ffmpeg_default_channel_layout(channels_in_frame);
1821 AVChannelLayout out_chlayout = ffmpeg_default_channel_layout(
info.
channels);
1822 if (channel_layout_in_frame > 0) {
1823 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
1828 av_opt_set_chlayout(avr,
"in_chlayout", &in_chlayout, 0);
1829 av_opt_set_chlayout(avr,
"out_chlayout", &out_chlayout, 0);
1831 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1833 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1836 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1837 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1838 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1845 audio_converted->data,
1846 audio_converted->linesize[0],
1847 audio_converted->nb_samples,
1849 audio_frame->linesize[0],
1850 audio_frame->nb_samples
1854 remaining_frame_samples = total_frame_samples;
1857 all_resampled_samples = (int16_t *) av_malloc(
1859 * (av_get_bytes_per_sample(output_sample_fmt) /
1860 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1864 memcpy(all_resampled_samples, audio_converted->data[0],
1865 static_cast<size_t>(nb_samples)
1867 * av_get_bytes_per_sample(output_sample_fmt));
1870 av_freep(&(audio_frame->data[0]));
1872 av_freep(&audio_converted->data[0]);
1874 all_queued_samples = NULL;
1877 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1878 "nb_samples", nb_samples,
1879 "remaining_frame_samples", remaining_frame_samples);
1882 if (is_final && remaining_frame_samples <= 0 && audio_input_position <= 0) {
1883 if (all_queued_samples) {
1884 av_freep(&all_queued_samples);
1890 while (remaining_frame_samples > 0 || is_final) {
1892 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1896 if (remaining_frame_samples >= remaining_packet_samples) {
1897 diff = remaining_packet_samples;
1899 diff = remaining_frame_samples;
1906 samples + (audio_input_position
1907 * (av_get_bytes_per_sample(output_sample_fmt) /
1908 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1910 all_resampled_samples + samples_position,
1911 static_cast<size_t>(diff)
1912 * av_get_bytes_per_sample(output_sample_fmt)
1916 audio_input_position += diff;
1917 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1918 remaining_frame_samples -= diff;
1921 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1928 const int frame_nb_samples = audio_input_position /
info.
channels;
1929 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1931 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1932 "in_sample_fmt", output_sample_fmt,
1933 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1944 AVChannelLayout layout = ffmpeg_default_channel_layout(
info.
channels);
1948 av_opt_set_chlayout(avr_planar,
"in_chlayout", &layout, 0);
1949 av_opt_set_chlayout(avr_planar,
"out_chlayout", &layout, 0);
1953 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1954 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1956 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1957 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1966 audio_frame->nb_samples = audio_input_position /
info.
channels;
1969 final_samples_planar = (int16_t *) av_malloc(
1970 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1971 * (av_get_bytes_per_sample(output_sample_fmt) /
1972 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1976 memcpy(final_samples_planar, samples,
1977 static_cast<size_t>(audio_frame->nb_samples)
1979 * av_get_bytes_per_sample(output_sample_fmt));
1982 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1983 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1986 frame_final->nb_samples = frame_nb_samples;
1993 frame_final->format = audio_codec_ctx->sample_fmt;
1994 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1995 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
2001 frame_final->linesize[0],
2002 frame_final->nb_samples,
2004 audio_frame->linesize[0],
2005 audio_frame->nb_samples
2009 const auto copy_length =
static_cast<size_t>(nb_samples)
2010 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
2014 memcpy(samples, frame_final->data[0], copy_length);
2017 av_freep(&(audio_frame->data[0]));
2019 all_queued_samples = NULL;
2022 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
2023 "nb_samples", nb_samples);
2027 const auto buf_size =
static_cast<size_t>(audio_input_position)
2028 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
2029 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
2031 final_samples =
reinterpret_cast<int16_t*
>(
2032 av_malloc(
sizeof(int16_t) * buf_size));
2035 memcpy(final_samples, samples,
2036 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
2039 frame_final->nb_samples = frame_nb_samples;
2040 frame_final->format = audio_codec_ctx->sample_fmt;
2042 av_channel_layout_copy(&frame_final->ch_layout, &audio_codec_ctx->ch_layout);
2044 frame_final->channels = audio_codec_ctx->channels;
2045 frame_final->channel_layout = audio_codec_ctx->channel_layout;
2050 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
2052 int nb_channels = audio_codec_ctx->channels;
2054 avcodec_fill_audio_frame(frame_final, nb_channels,
2055 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
2056 audio_encoder_buffer_size, 0);
2060 frame_final->pts = audio_timestamp;
2064 AVPacket* pkt = av_packet_alloc();
2067 av_init_packet(pkt);
2068 pkt->data = audio_encoder_buffer;
2069 pkt->size = audio_encoder_buffer_size;
2073 pkt->pts = pkt->dts = audio_timestamp;
2076 int got_packet_ptr = 0;
2082 int frame_finished = 0;
2083 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
2084 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF
2085 && audio_codec_ctx->codec
2086 && (audio_codec_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
2087 avcodec_send_frame(audio_codec_ctx, NULL);
2092 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
2095 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
2099 ret = frame_finished;
2102 if (!pkt->data && !frame_finished)
2106 got_packet_ptr = ret;
2109 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
2112 if (error_code == 0 && got_packet_ptr) {
2116 pkt->pts = pkt->dts = audio_timestamp;
2117 if (pkt->duration <= 0) {
2118 pkt->duration = frame_nb_samples;
2122 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2125 pkt->stream_index = audio_st->index;
2126 pkt->flags |= AV_PKT_FLAG_KEY;
2129 error_code = av_interleaved_write_frame(oc, pkt);
2132 if (error_code < 0) {
2134 "FFmpegWriter::write_audio_packets ERROR ["
2135 + av_err2string(error_code) +
"]",
2136 "error_code", error_code);
2140 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2143 av_freep(&(frame_final->data[0]));
2150 audio_input_position = 0;
2155 if (all_resampled_samples) {
2156 av_freep(&all_resampled_samples);
2157 all_resampled_samples = NULL;
2159 if (all_queued_samples) {
2160 av_freep(&all_queued_samples);
2161 all_queued_samples = NULL;
2166 AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2168 AVFrame *new_av_frame = NULL;
2172 if (new_av_frame == NULL)
2173 throw OutOfMemory(
"Could not allocate AVFrame", path);
2181 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
2184 new_av_frame->width = width;
2185 new_av_frame->height = height;
2186 new_av_frame->format = pix_fmt;
2190 return new_av_frame;
2194 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2196 int src_w = frame->GetWidth();
2197 int src_h = frame->GetHeight();
2200 if (src_w == 1 && src_h == 1)
2204 const uchar* pixels = frame->GetPixels();
2205 if (!persistent_src_frame) {
2206 persistent_src_frame = av_frame_alloc();
2207 if (!persistent_src_frame)
2208 throw OutOfMemory(
"Could not allocate persistent_src_frame", path);
2209 persistent_src_frame->format = AV_PIX_FMT_RGBA;
2210 persistent_src_frame->width = src_w;
2211 persistent_src_frame->height = src_h;
2212 persistent_src_frame->linesize[0] = src_w * 4;
2214 persistent_src_frame->data[0] =
const_cast<uint8_t*
>(
2215 reinterpret_cast<const uint8_t*
>(pixels)
2219 if (!persistent_dst_frame) {
2220 persistent_dst_frame = av_frame_alloc();
2221 if (!persistent_dst_frame)
2222 throw OutOfMemory(
"Could not allocate persistent_dst_frame", path);
2225 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2228 dst_fmt = AV_PIX_FMT_NV12;
2231 persistent_dst_frame->format = dst_fmt;
2232 persistent_dst_frame->width =
info.
width;
2235 persistent_dst_size = av_image_get_buffer_size(
2238 if (persistent_dst_size < 0)
2241 persistent_dst_buffer =
static_cast<uint8_t*
>(
2242 av_malloc(persistent_dst_size)
2244 if (!persistent_dst_buffer)
2245 throw OutOfMemory(
"Could not allocate persistent_dst_buffer", path);
2247 av_image_fill_arrays(
2248 persistent_dst_frame->data,
2249 persistent_dst_frame->linesize,
2250 persistent_dst_buffer,
2259 if (!img_convert_ctx) {
2260 int flags = SWS_FAST_BILINEAR;
2262 flags = SWS_BICUBIC;
2264 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2267 dst_fmt = AV_PIX_FMT_NV12;
2270 img_convert_ctx = sws_getContext(
2271 src_w, src_h, AV_PIX_FMT_RGBA,
2273 flags, NULL, NULL, NULL
2275 if (!img_convert_ctx)
2282 persistent_src_frame->data,
2283 persistent_src_frame->linesize,
2285 persistent_dst_frame->data,
2286 persistent_dst_frame->linesize
2290 int bytes_final = 0;
2291 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2294 dst_fmt = AV_PIX_FMT_NV12;
2298 AVFrame* new_frame = allocate_avframe(
2306 throw OutOfMemory(
"Could not allocate new_frame via allocate_avframe", path);
2311 persistent_dst_buffer,
2312 static_cast<size_t>(bytes_final)
2316 add_avframe(frame, new_frame);
2320 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2321 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2324 "FFmpegWriter::write_video_packet",
2325 "frame->number", frame->number,
2326 "oc->oformat->flags", oc->oformat->flags);
2334 "FFmpegWriter::write_video_packet",
2335 "frame->number", frame->number,
2336 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2338 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2342 AVPacket* pkt = av_packet_alloc();
2345 av_init_packet(pkt);
2348 av_packet_from_data(
2349 pkt, frame_final->data[0],
2350 frame_final->linesize[0] * frame_final->height);
2352 pkt->flags |= AV_PKT_FLAG_KEY;
2353 pkt->stream_index = video_st->index;
2356 pkt->pts = video_timestamp;
2357 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2360 int error_code = av_interleaved_write_frame(oc, pkt);
2361 if (error_code < 0) {
2363 "FFmpegWriter::write_video_packet ERROR ["
2364 + av_err2string(error_code) +
"]",
2365 "error_code", error_code);
2376 AVPacket* pkt = av_packet_alloc();
2379 av_init_packet(pkt);
2383 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2386 frame_final->pts = video_timestamp;
2389 if (!(
hw_frame = av_frame_alloc())) {
2390 std::clog <<
"Error code: av_hwframe_alloc\n";
2392 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2393 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2396 std::clog <<
"Error hw_frames_ctx.\n";
2398 hw_frame->format = AV_PIX_FMT_NV12;
2399 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2400 std::clog <<
"Error while transferring frame data to surface.\n";
2402 av_frame_copy_props(
hw_frame, frame_final);
2406 int got_packet_ptr = 0;
2414 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2418 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2423 "FFmpegWriter::write_video_packet (Frame not sent)");
2424 if (ret == AVERROR(EAGAIN) ) {
2425 std::clog <<
"Frame EAGAIN\n";
2427 if (ret == AVERROR_EOF ) {
2428 std::clog <<
"Frame AVERROR_EOF\n";
2430 avcodec_send_frame(video_codec_ctx, NULL);
2434 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2436 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2448 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2449 if (error_code != 0) {
2451 "FFmpegWriter::write_video_packet ERROR ["
2452 + av_err2string(error_code) +
"]",
2453 "error_code", error_code);
2455 if (got_packet_ptr == 0) {
2457 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2462 if (error_code == 0 && got_packet_ptr) {
2464 if (pkt->duration <= 0) {
2465 pkt->duration = av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2467 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2468 pkt->stream_index = video_st->index;
2471 int result = av_interleaved_write_frame(oc, pkt);
2474 "FFmpegWriter::write_video_packet ERROR ["
2475 + av_err2string(result) +
"]",
2494 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2503 av_dump_format(oc, 0, path.c_str(), 1);
2508 original_sample_rate = sample_rate;
2509 original_channels = channels;
2518 oc->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
2520 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
2522 int proj = av_spherical_from_name(projection.c_str());
2524 proj = AV_SPHERICAL_EQUIRECTANGULAR;
2528 AVSphericalMapping* map = av_spherical_alloc(&sd_size);
2532 map->projection =
static_cast<AVSphericalProjection
>(proj);
2534 map->yaw =
static_cast<int32_t
>(yaw_deg * (1 << 16));
2535 map->pitch =
static_cast<int32_t
>(pitch_deg * (1 << 16));
2536 map->roll =
static_cast<int32_t
>(roll_deg * (1 << 16));
2538 ffmpeg_stream_add_side_data(video_st, AV_PKT_DATA_SPHERICAL,
2539 reinterpret_cast<uint8_t*
>(map), sd_size);
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_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
AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx)
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.
Header file for ZeroMQ-based Logger class.
Exception when encoding audio packet.
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 WriteFrameAt(std::shared_ptr< openshot::Frame > frame, int64_t frame_number)
Add a frame at a specific output video frame number.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
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)
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.
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.
void AppendDebugMethod(std::string method_name, std::string arg1_name="", float arg1_value=-1.0, std::string arg2_name="", float arg2_value=-1.0, std::string arg3_name="", float arg3_value=-1.0, std::string arg4_name="", float arg4_value=-1.0, std::string arg5_name="", float arg5_value=-1.0, std::string arg6_name="", float arg6_value=-1.0)
Append debug information.
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
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.