41static AVBufferRef *hw_device_ctx = NULL;
44static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
46 AVBufferRef *hw_frames_ref;
47 AVHWFramesContext *frames_ctx = NULL;
50 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
51 std::clog <<
"Failed to create HW frame context.\n";
54 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
56 frames_ctx->sw_format = AV_PIX_FMT_NV12;
57 frames_ctx->width = width;
58 frames_ctx->height = height;
59 frames_ctx->initial_pool_size = 20;
60 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
61 std::clog <<
"Failed to initialize HW frame context. " <<
62 "Error code: " << av_err2string(err) <<
"\n";
63 av_buffer_unref(&hw_frames_ref);
66 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
67 if (!ctx->hw_frames_ctx)
68 err = AVERROR(ENOMEM);
70 av_buffer_unref(&hw_frames_ref);
76 path(path), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
77 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
78 initial_audio_input_frame_size(0), img_convert_ctx(NULL),
79 video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
80 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
81 write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
84 info.has_audio =
false;
85 info.has_video =
false;
101 if (!prepare_streams)
105 if (
info.has_video && video_st)
106 open_video(oc, video_st);
107 if (
info.has_audio && audio_st)
108 open_audio(oc, audio_st);
117void FFmpegWriter::auto_detect_format() {
123 "Could not allocate memory for AVFormatContext.",
path);
127 oc->oformat = av_guess_format(NULL,
path.c_str(), NULL);
128 if (oc->oformat ==
nullptr) {
129 throw InvalidFormat(
"Could not deduce output format from file extension.",
path);
133 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.has_video) {
134 const AVCodec *vcodec = avcodec_find_encoder(oc->oformat->video_codec);
135 info.vcodec = vcodec ? vcodec->name : std::string();
137 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.has_audio) {
138 const AVCodec *acodec = avcodec_find_encoder(oc->oformat->audio_codec);
139 info.acodec = acodec ? acodec->name : std::string();
144void FFmpegWriter::initialize_streams() {
146 "FFmpegWriter::initialize_streams",
147 "oc->oformat->video_codec", oc->oformat->video_codec,
148 "oc->oformat->audio_codec", oc->oformat->audio_codec,
149 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
154 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.has_video)
156 video_st = add_video_stream();
158 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.has_audio)
160 audio_st = add_audio_stream();
166 if (
codec.length() > 0) {
167 const AVCodec *new_codec;
170#if defined(__linux__)
171 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
172 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
177 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
178 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
184 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
189 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
190 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
195 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
196 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
202 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
206#elif defined(__APPLE__)
207 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
208 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
214 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
219 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
222 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
224 if (new_codec == NULL)
225 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
228 info.vcodec = new_codec->name;
237 info.video_timebase.num =
info.fps.den;
238 info.video_timebase.den =
info.fps.num;
243 info.height = height;
244 if (pixel_ratio.
num > 0) {
245 info.pixel_ratio.num = pixel_ratio.
num;
246 info.pixel_ratio.den = pixel_ratio.
den;
248 if (bit_rate >= 1000)
249 info.video_bit_rate = bit_rate;
250 if ((bit_rate >= 0) && (bit_rate < 256))
251 info.video_bit_rate = bit_rate;
253 info.interlaced_frame = interlaced;
254 info.top_field_first = top_field_first;
263 info.display_ratio.num = size.
num;
264 info.display_ratio.den = size.
den;
267 "FFmpegWriter::SetVideoOptions (" +
codec +
")",
268 "width", width,
"height", height,
269 "size.num", size.
num,
"size.den", size.
den,
270 "fps.num", fps.
num,
"fps.den", fps.
den);
273 info.has_video = has_video;
280 true,
codec, fps, width, height,
289 if (
codec.length() > 0) {
290 const AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
291 if (new_codec == NULL)
292 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
295 info.acodec = new_codec->name;
298 if (sample_rate > 7999)
299 info.sample_rate = sample_rate;
301 info.channels = channels;
303 info.audio_bit_rate = bit_rate;
304 info.channel_layout = channel_layout;
307 if (original_sample_rate == 0)
308 original_sample_rate =
info.sample_rate;
309 if (original_channels == 0)
310 original_channels =
info.channels;
313 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
314 "sample_rate", sample_rate,
315 "channels", channels,
316 "bit_rate", bit_rate);
319 info.has_audio = has_audio;
327 true,
codec, sample_rate, 2,
336 AVCodecContext *c = NULL;
338 std::stringstream convert(value);
346 if (
info.interlaced_frame) {
347 c->field_order =
info.top_field_first ? AV_FIELD_TT : AV_FIELD_BB;
357 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
360 const AVOption *option = NULL;
368 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
369 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
370 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp")) {
374 convert >> c->gop_size;
376 else if (name ==
"qmin")
380 else if (name ==
"qmax")
384 else if (name ==
"max_b_frames")
386 convert >> c->max_b_frames;
388 else if (name ==
"mb_decision")
390 convert >> c->mb_decision;
392 else if (name ==
"level")
396 else if (name ==
"profile")
398 convert >> c->profile;
400 else if (name ==
"slices")
402 convert >> c->slices;
404 else if (name ==
"rc_min_rate")
406 convert >> c->rc_min_rate;
408 else if (name ==
"rc_max_rate")
410 convert >> c->rc_max_rate;
412 else if (name ==
"rc_buffer_size")
414 convert >> c->rc_buffer_size;
416 else if (name ==
"cqp") {
420 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
424 switch (c->codec_id) {
425#if (LIBAVCODEC_VERSION_MAJOR >= 58)
427 case AV_CODEC_ID_AV1 :
429 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
432 case AV_CODEC_ID_VP8 :
433 c->bit_rate = 10000000;
434 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
436 case AV_CODEC_ID_VP9 :
438 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
439 if (std::stoi(value) == 0) {
440 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
441 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
444 case AV_CODEC_ID_H264 :
445 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
446 if (std::stoi(value) == 0) {
447 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
451 case AV_CODEC_ID_HEVC :
452 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
453 if (std::stoi(value) == 0) {
454 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
455 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
460 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
464 }
else if (name ==
"crf") {
468 double mbs = 15000000.0;
469 if (
info.video_bit_rate > 0) {
470 if (
info.video_bit_rate > 42) {
474 mbs *= std::pow(0.912,
info.video_bit_rate);
477 c->bit_rate = (int)(mbs);
481 switch (c->codec_id) {
482#if (LIBAVCODEC_VERSION_MAJOR >= 58)
484 case AV_CODEC_ID_AV1 :
487 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
490 case AV_CODEC_ID_VP8 :
491 c->bit_rate = 10000000;
492 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
494 case AV_CODEC_ID_VP9 :
496 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
497 if (std::stoi(value) == 0) {
498 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
499 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
502 case AV_CODEC_ID_H264 :
503 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
504 if (std::stoi(value) == 0) {
505 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
509 case AV_CODEC_ID_HEVC :
510 if (strstr(
info.vcodec.c_str(),
"svt_hevc") != NULL) {
511 av_opt_set_int(c->priv_data,
"preset", 7, 0);
512 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
513 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
516 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
518 if (std::stoi(value) == 0) {
519 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
520 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
526 double mbs = 15000000.0;
527 if (
info.video_bit_rate > 0) {
528 if (
info.video_bit_rate > 42) {
531 mbs *= std::pow(0.912,
info.video_bit_rate);
534 c->bit_rate = (int) (mbs);
537 }
else if (name ==
"qp") {
539#if (LIBAVCODEC_VERSION_MAJOR >= 58)
541 switch (c->codec_id) {
542 case AV_CODEC_ID_AV1 :
544 if (strstr(
info.vcodec.c_str(),
"svtav1") != NULL) {
545 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
547 else if (strstr(
info.vcodec.c_str(),
"rav1e") != NULL) {
550 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
552 else if (strstr(
info.vcodec.c_str(),
"aom") != NULL) {
556 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
559 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
561 case AV_CODEC_ID_HEVC :
563 if (strstr(
info.vcodec.c_str(),
"svt_hevc") != NULL) {
564 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
565 av_opt_set_int(c->priv_data,
"preset", 7, 0);
566 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
573 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
577 "FFmpegWriter::SetOption (" + (std::string)name +
")",
582 }
else if (name ==
"muxing_preset") {
583 if (value ==
"mp4_faststart") {
585 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
586 }
else if (value ==
"mp4_fragmented") {
588 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
589 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
592 throw InvalidOptions(
"The option is not valid for this codec.", path);
603 return avcodec_find_encoder_by_name(codec_name.c_str()) != NULL;
608 if (!
info.has_audio && !
info.has_video)
609 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
612 "FFmpegWriter::PrepareStreams [" + path +
"]",
613 "info.has_audio",
info.has_audio,
614 "info.has_video",
info.has_video);
617 initialize_streams();
620 prepare_streams =
true;
625 if (!
info.has_audio && !
info.has_video)
626 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
629 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
630 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
631 throw InvalidFile(
"Could not open or write file.", path);
638 for (
auto iter =
info.metadata.begin(); iter !=
info.metadata.end(); ++iter) {
639 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
643 AVDictionary *dict = NULL;
649 if (avformat_write_header(oc, &dict) != 0) {
651 "FFmpegWriter::WriteHeader (avformat_write_header)");
652 throw InvalidFile(
"Could not write header to file.", path);
656 if (dict) av_dict_free(&dict);
669 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
672 "FFmpegWriter::WriteFrame",
673 "frame->number", frame->number,
674 "is_writing", is_writing);
684void FFmpegWriter::write_frame(std::shared_ptr<Frame> frame) {
689 bool has_error_encoding_video =
false;
693 write_audio_packets(
false, frame);
697 process_video_packet(frame);
701 if (av_frames.count(frame)) {
703 AVFrame *frame_final = av_frames[frame];
706 if (!write_video_packet(frame, frame_final)) {
707 has_error_encoding_video =
true;
711 av_freep(&(frame_final->data[0]));
713 av_frames.erase(frame);
721 if (has_error_encoding_video)
722 throw ErrorEncodingVideo(
"Error while writing raw video frame", -1);
728 "FFmpegWriter::WriteFrame (from Reader)",
733 for (int64_t number = start; number <= length; number++) {
735 std::shared_ptr<Frame> f = reader->
GetFrame(number);
745 if (
info.has_audio && audio_st)
746 write_audio_packets(
true, NULL);
755 av_write_trailer(oc);
758 write_trailer =
true;
764void FFmpegWriter::flush_encoders() {
767#if (LIBAVFORMAT_VERSION_MAJOR < 58)
781 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
784 AVPacket* pkt = av_packet_alloc();
798 error_code = avcodec_send_frame(video_codec_ctx, NULL);
800 while (error_code >= 0) {
801 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
802 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
805 avcodec_flush_buffers(video_codec_ctx);
808 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
809 pkt->stream_index = video_st->index;
810 error_code = av_interleaved_write_frame(oc, pkt);
815 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
819 if (error_code < 0) {
821 "FFmpegWriter::flush_encoders ERROR ["
822 + av_err2string(error_code) +
"]",
823 "error_code", error_code);
830 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
831 pkt->stream_index = video_st->index;
834 error_code = av_interleaved_write_frame(oc, pkt);
835 if (error_code < 0) {
837 "FFmpegWriter::flush_encoders ERROR ["
838 + av_err2string(error_code) +
"]",
839 "error_code", error_code);
845 if (
info.has_audio) {
848 AVPacket* pkt = av_packet_alloc();
855 pkt->pts = pkt->dts = audio_timestamp;
861 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
863 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
865 if (error_code < 0) {
867 "FFmpegWriter::flush_encoders ERROR ["
868 + av_err2string(error_code) +
"]",
869 "error_code", error_code);
877 pkt->pts = pkt->dts = audio_timestamp;
880 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
883 pkt->stream_index = audio_st->index;
884 pkt->flags |= AV_PKT_FLAG_KEY;
887 error_code = av_interleaved_write_frame(oc, pkt);
888 if (error_code < 0) {
890 "FFmpegWriter::flush_encoders ERROR ["
891 + av_err2string(error_code) +
"]",
892 "error_code", error_code);
896 audio_timestamp += pkt->duration;
906void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
911 av_buffer_unref(&hw_device_ctx);
912 hw_device_ctx = NULL;
918 if (video_codec_ctx !=
nullptr) {
920 av_free(video_codec_ctx);
925void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
929 delete[] audio_outbuf;
930 delete[] audio_encoder_buffer;
933 audio_encoder_buffer = NULL;
949 if (audio_codec_ctx !=
nullptr) {
951 av_free(audio_codec_ctx);
963 close_video(oc, video_st);
965 close_audio(oc, audio_st);
969 sws_freeContext(img_convert_ctx);
971 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
981 avformat_free_context(oc);
986 prepare_streams =
false;
987 write_header =
false;
988 write_trailer =
false;
994void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
996 if (!av_frames.count(frame)) {
998 av_frames[frame] = av_frame;
1006AVStream *FFmpegWriter::add_audio_stream() {
1008 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.acodec.c_str());
1010 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1013 if (audio_codec_ctx !=
nullptr) {
1018 AVStream* st = avformat_new_stream(oc,
codec);
1020 throw OutOfMemory(
"Could not allocate memory for the audio stream.", path);
1024#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1025 st->codecpar->codec_id =
codec->id;
1027 AVCodecContext* c = audio_codec_ctx;
1029 c->codec_id =
codec->id;
1030 c->codec_type = AVMEDIA_TYPE_AUDIO;
1033 c->bit_rate =
info.audio_bit_rate;
1035 c->channels =
info.channels;
1041 const int *supported_samplerates = NULL;
1042#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
1043 if (avcodec_get_supported_config(NULL,
codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0,
1044 (
const void **)&supported_samplerates, NULL) < 0)
1045 supported_samplerates = NULL;
1047 supported_samplerates =
codec->supported_samplerates;
1049 if (supported_samplerates) {
1051 for (i = 0; supported_samplerates[i] != 0; i++)
1052 if (
info.sample_rate == supported_samplerates[i]) {
1054 c->sample_rate =
info.sample_rate;
1057 if (supported_samplerates[i] == 0)
1058 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1061 c->sample_rate =
info.sample_rate;
1064 uint64_t channel_layout =
info.channel_layout;
1068 AVChannelLayout ch_layout;
1069 av_channel_layout_from_mask(&ch_layout,
info.channel_layout);
1071 const AVChannelLayout *ch_layouts = NULL;
1072#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
1073 if (avcodec_get_supported_config(NULL,
codec, AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0,
1074 (
const void **)&ch_layouts, NULL) < 0)
1077 ch_layouts =
codec->ch_layouts;
1081 for (i = 0; av_channel_layout_check(&ch_layouts[i]); i++)
1082 if (av_channel_layout_compare(&ch_layout, &ch_layouts[i])) {
1084 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1087 if (!av_channel_layout_check(&ch_layouts[i]))
1088 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1091 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1095 if (
codec->channel_layouts) {
1097 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1098 if (channel_layout ==
codec->channel_layouts[i]) {
1100 c->channel_layout = channel_layout;
1103 if (
codec->channel_layouts[i] == 0)
1104 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1107 c->channel_layout = channel_layout;
1113 const enum AVSampleFormat *sample_fmts = NULL;
1114#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
1115 if (avcodec_get_supported_config(NULL,
codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
1116 (
const void **)&sample_fmts, NULL) < 0)
1119 sample_fmts =
codec->sample_fmts;
1122 for (
int i = 0; sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1124 c->sample_fmt = sample_fmts[i];
1129 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1131 c->sample_fmt = AV_SAMPLE_FMT_S16;
1135 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1136#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1138 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1140 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1146 const char* nb_channels_label;
1147 const char* channel_layout_label;
1150 nb_channels = c->ch_layout.nb_channels;
1151 channel_layout = c->ch_layout.u.mask;
1152 nb_channels_label =
"c->ch_layout.nb_channels";
1153 channel_layout_label =
"c->ch_layout.u.mask";
1155 nb_channels = c->channels;
1156 nb_channels_label =
"c->channels";
1157 channel_layout_label =
"c->channel_layout";
1161 "FFmpegWriter::add_audio_stream",
1162 "c->codec_id", c->codec_id,
1163 "c->bit_rate", c->bit_rate,
1164 nb_channels_label, nb_channels,
1165 "c->sample_fmt", c->sample_fmt,
1166 channel_layout_label, channel_layout,
1167 "c->sample_rate", c->sample_rate);
1173AVStream *FFmpegWriter::add_video_stream() {
1175 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.vcodec.c_str());
1177 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1180 if (video_codec_ctx !=
nullptr) {
1185 AVStream* st = avformat_new_stream(oc,
codec);
1187 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1191#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1192 st->codecpar->codec_id =
codec->id;
1195 AVCodecContext* c = video_codec_ctx;
1197 c->codec_id =
codec->id;
1198 c->codec_type = AVMEDIA_TYPE_VIDEO;
1201 c->sample_aspect_ratio.num =
info.pixel_ratio.num;
1202 c->sample_aspect_ratio.den =
info.pixel_ratio.den;
1205 if (
info.video_bit_rate >= 1000
1206#
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1207 && c->codec_id != AV_CODEC_ID_AV1
1210 c->bit_rate =
info.video_bit_rate;
1211 if (
info.video_bit_rate >= 1500000) {
1212 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1221 switch (c->codec_id) {
1222#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1224 case AV_CODEC_ID_AV1 :
1226 if (
info.video_bit_rate >= 1000) {
1228 if (strstr(
info.vcodec.c_str(),
"aom") != NULL) {
1229 int calculated_quality = 35;
1230 if (
info.video_bit_rate < 500000) calculated_quality = 50;
1231 if (
info.video_bit_rate > 5000000) calculated_quality = 10;
1232 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1233 info.video_bit_rate = calculated_quality;
1235 int calculated_quality = 50;
1236 if (
info.video_bit_rate < 500000) calculated_quality = 60;
1237 if (
info.video_bit_rate > 5000000) calculated_quality = 15;
1238 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1239 info.video_bit_rate = calculated_quality;
1242 if (strstr(
info.vcodec.c_str(),
"svtav1") != NULL) {
1243 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1244 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1246 else if (strstr(
info.vcodec.c_str(),
"rav1e") != NULL) {
1247 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1248 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1249 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1251 else if (strstr(
info.vcodec.c_str(),
"aom") != NULL) {
1254 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1255 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1256 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1257 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1261 case AV_CODEC_ID_VP9 :
1262 case AV_CODEC_ID_HEVC :
1263 case AV_CODEC_ID_VP8 :
1264 case AV_CODEC_ID_H264 :
1265 if (
info.video_bit_rate < 40) {
1269 c->qmin =
info.video_bit_rate - 5;
1290 c->width =
info.width;
1291 c->height =
info.height;
1297 c->time_base.num =
info.video_timebase.num;
1298 c->time_base.den =
info.video_timebase.den;
1300#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1301 c->framerate = av_inv_q(c->time_base);
1303 st->avg_frame_rate = av_inv_q(c->time_base);
1304 st->time_base.num =
info.video_timebase.num;
1305 st->time_base.den =
info.video_timebase.den;
1308 c->max_b_frames = 10;
1309 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1311 c->max_b_frames = 2;
1312 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1318 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1319#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1321 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1323 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1328 const PixelFormat *supported_pixel_formats = NULL;
1329#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100)
1330 if (avcodec_get_supported_config(NULL,
codec, AV_CODEC_CONFIG_PIX_FORMAT, 0,
1331 (
const void **)&supported_pixel_formats, NULL) < 0)
1332 supported_pixel_formats = NULL;
1334 supported_pixel_formats =
codec->pix_fmts;
1336 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1339 c->pix_fmt = *supported_pixel_formats;
1340 ++supported_pixel_formats;
1345 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1349#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1351 if (strcmp(oc->oformat->name,
"gif") != 0)
1354 oc->oformat->flags |= AVFMT_RAWPICTURE;
1364 "FFmpegWriter::add_video_stream ("
1365 + (std::string)oc->oformat->name +
" : "
1366 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1367 "c->codec_id", c->codec_id,
1368 "c->bit_rate", c->bit_rate,
1369 "c->pix_fmt", c->pix_fmt,
1370 "oc->oformat->flags", oc->oformat->flags);
1375void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1376 const AVCodec *
codec;
1383 codec = avcodec_find_encoder_by_name(
info.acodec.c_str());
1385 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1387 throw InvalidCodec(
"Could not find codec", path);
1390 AVDictionary *
opts = NULL;
1391 av_dict_set(&
opts,
"strict",
"experimental", 0);
1394 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1395 throw InvalidCodec(
"Could not open audio codec", path);
1399 av_dict_free(&
opts);
1403 if (audio_codec_ctx->frame_size <= 1) {
1405 audio_input_frame_size = 50000 /
info.channels;
1409 case AV_CODEC_ID_PCM_S16LE:
1410 case AV_CODEC_ID_PCM_S16BE:
1411 case AV_CODEC_ID_PCM_U16LE:
1412 case AV_CODEC_ID_PCM_U16BE:
1413 audio_input_frame_size >>= 1;
1420 audio_input_frame_size = audio_codec_ctx->frame_size;
1424 initial_audio_input_frame_size = audio_input_frame_size;
1431 audio_outbuf =
new uint8_t[audio_outbuf_size];
1435 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1438 for (std::map<std::string, std::string>::iterator iter =
info.metadata.begin(); iter !=
info.metadata.end(); ++iter) {
1439 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1443 "FFmpegWriter::open_audio",
1444 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1445 "audio_input_frame_size", audio_input_frame_size,
1450void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1451 const AVCodec *
codec;
1461 char *adapter_ptr = NULL;
1465 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1466 if (adapter_num < 3 && adapter_num >=0) {
1467#if defined(__linux__)
1468 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1470 adapter_ptr = adapter;
1471#elif defined(_WIN32) || defined(__APPLE__)
1479#if defined(__linux__)
1480 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1481#elif defined(_WIN32) || defined(__APPLE__)
1482 if( adapter_ptr != NULL ) {
1485 "Encode Device present using device",
1486 "adapter", adapter_num);
1491 "Encode Device not present, using default");
1493 if (av_hwdevice_ctx_create(&hw_device_ctx,
1497 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1498 info.vcodec.c_str(), -1);
1499 throw InvalidCodec(
"Could not create hwdevice", path);
1512 if (video_codec_ctx->max_b_frames && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG4 && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO && video_codec_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO)
1513 video_codec_ctx->max_b_frames = 0;
1517 av_dict_set(&
opts,
"strict",
"experimental", 0);
1531 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1533 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1537 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1541 switch (video_codec_ctx->codec_id) {
1542 case AV_CODEC_ID_H264:
1543 video_codec_ctx->max_b_frames = 0;
1544 video_codec_ctx->profile = AV_PROFILE_H264_BASELINE | AV_PROFILE_H264_CONSTRAINED;
1545 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1546 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1547 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1549 case AV_CODEC_ID_HEVC:
1552 case AV_CODEC_ID_VP9:
1557 "No codec-specific options defined for this codec. HW encoding may fail",
1558 "codec_id", video_codec_ctx->codec_id);
1567 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1570 av_err2string(err), -1);
1578 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
1581 if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
1582 video_codec_ctx->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
1592 av_dict_free(&
opts);
1596 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1600 "FFmpegWriter::open_video",
1601 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1606void FFmpegWriter::write_audio_packets(
bool is_final, std::shared_ptr<openshot::Frame> frame) {
1607 if (!frame && !is_final)
1611 int total_frame_samples = 0;
1612 int frame_position = 0;
1613 int channels_in_frame = 0;
1614 int sample_rate_in_frame = 0;
1615 int samples_in_frame = 0;
1620 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1621 int16_t *all_resampled_samples = NULL;
1622 int16_t *final_samples_planar = NULL;
1623 int16_t *final_samples = NULL;
1626 float *frame_samples_float = NULL;
1630 sample_rate_in_frame = frame->SampleRate();
1631 samples_in_frame = frame->GetAudioSamplesCount();
1632 channels_in_frame = frame->GetAudioChannelsCount();
1633 channel_layout_in_frame = frame->ChannelsLayout();
1636 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1640 total_frame_samples = samples_in_frame * channels_in_frame;
1643 const int16_t max16 = 32767;
1644 const int16_t min16 = -32768;
1645 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1646 float valF = frame_samples_float[s] * (1 << 15);
1650 }
else if (valF < min16) {
1653 conv = int(valF + 32768.5) - 32768;
1657 all_queued_samples[frame_position] = conv;
1661 delete[] frame_samples_float;
1665 total_frame_samples = frame_position;
1666 int remaining_frame_samples = total_frame_samples;
1667 int samples_position = 0;
1671 "FFmpegWriter::write_audio_packets",
1672 "is_final", is_final,
1673 "total_frame_samples", total_frame_samples,
1674 "channel_layout_in_frame", channel_layout_in_frame,
1675 "channels_in_frame", channels_in_frame,
1676 "samples_in_frame", samples_in_frame,
1680 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1682 AVFrame *audio_frame = NULL;
1687 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1690 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);
1691 if (error_code < 0) {
1693 "FFmpegWriter::write_audio_packets ERROR ["
1694 + av_err2string(error_code) +
"]",
1695 "error_code", error_code);
1699 switch (audio_codec_ctx->sample_fmt) {
1700 case AV_SAMPLE_FMT_FLTP: {
1701 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1704 case AV_SAMPLE_FMT_S32P: {
1705 output_sample_fmt = AV_SAMPLE_FMT_S32;
1708 case AV_SAMPLE_FMT_S16P: {
1709 output_sample_fmt = AV_SAMPLE_FMT_S16;
1712 case AV_SAMPLE_FMT_U8P: {
1713 output_sample_fmt = AV_SAMPLE_FMT_U8;
1723 total_frame_samples *= (float(
info.sample_rate) / sample_rate_in_frame);
1724 total_frame_samples *= (float(
info.channels) / channels_in_frame);
1729 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1730 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.channels, audio_converted->nb_samples, output_sample_fmt, 0);
1733 "FFmpegWriter::write_audio_packets (1st resampling)",
1734 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1735 "out_sample_fmt", output_sample_fmt,
1736 "in_sample_rate", sample_rate_in_frame,
1737 "out_sample_rate",
info.sample_rate,
1738 "in_channels", channels_in_frame,
1739 "out_channels",
info.channels);
1745 AVChannelLayout in_chlayout;
1746 AVChannelLayout out_chlayout;
1747 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
1748 av_channel_layout_from_mask(&out_chlayout,
info.channel_layout);
1749 av_opt_set_chlayout(avr,
"in_chlayout", &in_chlayout, 0);
1750 av_opt_set_chlayout(avr,
"out_chlayout", &out_chlayout, 0);
1752 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1753 av_opt_set_int(avr,
"out_channel_layout",
info.channel_layout, 0);
1754 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1755 av_opt_set_int(avr,
"out_channels",
info.channels, 0);
1757 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1758 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1759 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1760 av_opt_set_int(avr,
"out_sample_rate",
info.sample_rate, 0);
1766 audio_converted->data,
1767 audio_converted->linesize[0],
1768 audio_converted->nb_samples,
1770 audio_frame->linesize[0],
1771 audio_frame->nb_samples
1775 remaining_frame_samples = total_frame_samples;
1778 all_resampled_samples = (int16_t *) av_malloc(
1779 sizeof(int16_t) * nb_samples *
info.channels
1780 * (av_get_bytes_per_sample(output_sample_fmt) /
1781 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1785 memcpy(all_resampled_samples, audio_converted->data[0],
1786 static_cast<size_t>(nb_samples)
1788 * av_get_bytes_per_sample(output_sample_fmt));
1791 av_freep(&(audio_frame->data[0]));
1793 av_freep(&audio_converted->data[0]);
1795 all_queued_samples = NULL;
1798 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1799 "nb_samples", nb_samples,
1800 "remaining_frame_samples", remaining_frame_samples);
1804 while (remaining_frame_samples > 0 || is_final) {
1806 int remaining_packet_samples = (audio_input_frame_size *
info.channels) - audio_input_position;
1810 if (remaining_frame_samples >= remaining_packet_samples) {
1811 diff = remaining_packet_samples;
1813 diff = remaining_frame_samples;
1820 samples + (audio_input_position
1821 * (av_get_bytes_per_sample(output_sample_fmt) /
1822 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1824 all_resampled_samples + samples_position,
1825 static_cast<size_t>(diff)
1826 * av_get_bytes_per_sample(output_sample_fmt)
1830 audio_input_position += diff;
1831 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1832 remaining_frame_samples -= diff;
1835 if (audio_input_position < (audio_input_frame_size *
info.channels) && !is_final)
1842 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1844 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1845 "in_sample_fmt", output_sample_fmt,
1846 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1847 "in_sample_rate",
info.sample_rate,
1848 "out_sample_rate",
info.sample_rate,
1849 "in_channels",
info.channels,
1850 "out_channels",
info.channels
1857 AVChannelLayout layout;
1858 av_channel_layout_from_mask(&layout,
info.channel_layout);
1859 av_opt_set_chlayout(avr_planar,
"in_chlayout", &layout, 0);
1860 av_opt_set_chlayout(avr_planar,
"out_chlayout", &layout, 0);
1862 av_opt_set_int(avr_planar,
"in_channel_layout",
info.channel_layout, 0);
1863 av_opt_set_int(avr_planar,
"out_channel_layout",
info.channel_layout, 0);
1864 av_opt_set_int(avr_planar,
"in_channels",
info.channels, 0);
1865 av_opt_set_int(avr_planar,
"out_channels",
info.channels, 0);
1867 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1868 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1869 av_opt_set_int(avr_planar,
"in_sample_rate",
info.sample_rate, 0);
1870 av_opt_set_int(avr_planar,
"out_sample_rate",
info.sample_rate, 0);
1877 audio_frame->nb_samples = audio_input_position /
info.channels;
1880 final_samples_planar = (int16_t *) av_malloc(
1881 sizeof(int16_t) * audio_frame->nb_samples *
info.channels
1882 * (av_get_bytes_per_sample(output_sample_fmt) /
1883 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1887 memcpy(final_samples_planar, samples,
1888 static_cast<size_t>(audio_frame->nb_samples)
1890 * av_get_bytes_per_sample(output_sample_fmt));
1893 avcodec_fill_audio_frame(audio_frame,
info.channels, output_sample_fmt,
1894 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1897 frame_final->nb_samples = audio_input_frame_size;
1899 av_channel_layout_from_mask(&frame_final->ch_layout,
info.channel_layout);
1901 frame_final->channels =
info.channels;
1902 frame_final->channel_layout =
info.channel_layout;
1904 frame_final->format = audio_codec_ctx->sample_fmt;
1905 av_samples_alloc(frame_final->data, frame_final->linesize,
info.channels,
1906 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1912 frame_final->linesize[0],
1913 frame_final->nb_samples,
1915 audio_frame->linesize[0],
1916 audio_frame->nb_samples
1920 const auto copy_length =
static_cast<size_t>(nb_samples)
1921 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
1925 memcpy(samples, frame_final->data[0], copy_length);
1928 av_freep(&(audio_frame->data[0]));
1930 all_queued_samples = NULL;
1933 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
1934 "nb_samples", nb_samples);
1938 const auto buf_size =
static_cast<size_t>(audio_input_position)
1939 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1940 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
1942 final_samples =
reinterpret_cast<int16_t*
>(
1943 av_malloc(
sizeof(int16_t) * buf_size));
1946 memcpy(final_samples, samples,
1947 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1950 frame_final->nb_samples = audio_input_frame_size;
1954 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
1956 int nb_channels = audio_codec_ctx->channels;
1958 avcodec_fill_audio_frame(frame_final, nb_channels,
1959 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1960 audio_encoder_buffer_size, 0);
1964 frame_final->pts = audio_timestamp;
1968 AVPacket* pkt = av_packet_alloc();
1971 av_init_packet(pkt);
1973 pkt->data = audio_encoder_buffer;
1974 pkt->size = audio_encoder_buffer_size;
1977 pkt->pts = pkt->dts = audio_timestamp;
1980 int got_packet_ptr = 0;
1986 int frame_finished = 0;
1987 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1988 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1989 avcodec_send_frame(audio_codec_ctx, NULL);
1994 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
1997 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1998 avcodec_flush_buffers(audio_codec_ctx);
2002 ret = frame_finished;
2005 if (!pkt->data && !frame_finished)
2009 got_packet_ptr = ret;
2012 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
2015 if (error_code == 0 && got_packet_ptr) {
2019 pkt->pts = pkt->dts = audio_timestamp;
2022 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2025 pkt->stream_index = audio_st->index;
2026 pkt->flags |= AV_PKT_FLAG_KEY;
2029 error_code = av_interleaved_write_frame(oc, pkt);
2032 if (error_code < 0) {
2034 "FFmpegWriter::write_audio_packets ERROR ["
2035 + av_err2string(error_code) +
"]",
2036 "error_code", error_code);
2040 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2043 av_freep(&(frame_final->data[0]));
2050 audio_input_position = 0;
2055 if (all_resampled_samples) {
2056 av_freep(&all_resampled_samples);
2057 all_resampled_samples = NULL;
2059 if (all_queued_samples) {
2060 av_freep(&all_queued_samples);
2061 all_queued_samples = NULL;
2066AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2068 AVFrame *new_av_frame = NULL;
2072 if (new_av_frame == NULL)
2073 throw OutOfMemory(
"Could not allocate AVFrame", path);
2081 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
2084 new_av_frame->width = width;
2085 new_av_frame->height = height;
2086 new_av_frame->format = pix_fmt;
2090 return new_av_frame;
2094void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2096 int src_w = frame->GetWidth();
2097 int src_h = frame->GetHeight();
2100 if (src_w == 1 && src_h == 1)
2104 const uchar* pixels = frame->GetPixels();
2105 if (!persistent_src_frame) {
2106 persistent_src_frame = av_frame_alloc();
2107 if (!persistent_src_frame)
2108 throw OutOfMemory(
"Could not allocate persistent_src_frame", path);
2109 persistent_src_frame->format = AV_PIX_FMT_RGBA;
2110 persistent_src_frame->width = src_w;
2111 persistent_src_frame->height = src_h;
2112 persistent_src_frame->linesize[0] = src_w * 4;
2114 persistent_src_frame->data[0] =
const_cast<uint8_t*
>(
2115 reinterpret_cast<const uint8_t*
>(pixels)
2119 if (!persistent_dst_frame) {
2120 persistent_dst_frame = av_frame_alloc();
2121 if (!persistent_dst_frame)
2122 throw OutOfMemory(
"Could not allocate persistent_dst_frame", path);
2125 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2128 dst_fmt = AV_PIX_FMT_NV12;
2131 persistent_dst_frame->format = dst_fmt;
2132 persistent_dst_frame->width =
info.width;
2133 persistent_dst_frame->height =
info.height;
2135 persistent_dst_size = av_image_get_buffer_size(
2136 dst_fmt,
info.width,
info.height, 1
2138 if (persistent_dst_size < 0)
2139 throw ErrorEncodingVideo(
"Invalid destination image size", -1);
2141 persistent_dst_buffer =
static_cast<uint8_t*
>(
2142 av_malloc(persistent_dst_size)
2144 if (!persistent_dst_buffer)
2145 throw OutOfMemory(
"Could not allocate persistent_dst_buffer", path);
2147 av_image_fill_arrays(
2148 persistent_dst_frame->data,
2149 persistent_dst_frame->linesize,
2150 persistent_dst_buffer,
2159 if (!img_convert_ctx) {
2160 int flags = SWS_FAST_BILINEAR;
2162 flags = SWS_BICUBIC;
2164 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2167 dst_fmt = AV_PIX_FMT_NV12;
2170 img_convert_ctx = sws_getContext(
2171 src_w, src_h, AV_PIX_FMT_RGBA,
2173 flags, NULL, NULL, NULL
2175 if (!img_convert_ctx)
2176 throw ErrorEncodingVideo(
"Could not initialize sws context", -1);
2182 persistent_src_frame->data,
2183 persistent_src_frame->linesize,
2185 persistent_dst_frame->data,
2186 persistent_dst_frame->linesize
2190 int bytes_final = 0;
2191 AVPixelFormat dst_fmt = video_codec_ctx->pix_fmt;
2194 dst_fmt = AV_PIX_FMT_NV12;
2198 AVFrame* new_frame = allocate_avframe(
2206 throw OutOfMemory(
"Could not allocate new_frame via allocate_avframe", path);
2211 persistent_dst_buffer,
2212 static_cast<size_t>(bytes_final)
2216 add_avframe(frame, new_frame);
2220bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2221#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2224 "FFmpegWriter::write_video_packet",
2225 "frame->number", frame->number,
2226 "oc->oformat->flags", oc->oformat->flags);
2234 "FFmpegWriter::write_video_packet",
2235 "frame->number", frame->number,
2236 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2238 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2242 AVPacket* pkt = av_packet_alloc();
2245 av_init_packet(pkt);
2248 av_packet_from_data(
2249 pkt, frame_final->data[0],
2250 frame_final->linesize[0] * frame_final->height);
2252 pkt->flags |= AV_PKT_FLAG_KEY;
2253 pkt->stream_index = video_st->index;
2256 pkt->pts = video_timestamp;
2259 int error_code = av_interleaved_write_frame(oc, pkt);
2260 if (error_code < 0) {
2262 "FFmpegWriter::write_video_packet ERROR ["
2263 + av_err2string(error_code) +
"]",
2264 "error_code", error_code);
2275 AVPacket* pkt = av_packet_alloc();
2278 av_init_packet(pkt);
2282 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2285 frame_final->pts = video_timestamp;
2288 if (!(
hw_frame = av_frame_alloc())) {
2289 std::clog <<
"Error code: av_hwframe_alloc\n";
2291 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2292 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2295 std::clog <<
"Error hw_frames_ctx.\n";
2297 hw_frame->format = AV_PIX_FMT_NV12;
2298 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2299 std::clog <<
"Error while transferring frame data to surface.\n";
2301 av_frame_copy_props(
hw_frame, frame_final);
2305 int got_packet_ptr = 0;
2313 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2317 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2322 "FFmpegWriter::write_video_packet (Frame not sent)");
2323 if (ret == AVERROR(EAGAIN) ) {
2324 std::clog <<
"Frame EAGAIN\n";
2326 if (ret == AVERROR_EOF ) {
2327 std::clog <<
"Frame AVERROR_EOF\n";
2329 avcodec_send_frame(video_codec_ctx, NULL);
2333 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2335 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2347 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2348 if (error_code != 0) {
2350 "FFmpegWriter::write_video_packet ERROR ["
2351 + av_err2string(error_code) +
"]",
2352 "error_code", error_code);
2354 if (got_packet_ptr == 0) {
2356 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2361 if (error_code == 0 && got_packet_ptr) {
2363 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2364 pkt->stream_index = video_st->index;
2367 int result = av_interleaved_write_frame(oc, pkt);
2370 "FFmpegWriter::write_video_packet ERROR ["
2371 + av_err2string(result) +
"]",
2390 video_timestamp += av_rescale_q(1, av_make_q(
info.fps.den,
info.fps.num), video_codec_ctx->time_base);
2399 av_dump_format(oc, 0, path.c_str(), 1);
2404 original_sample_rate = sample_rate;
2405 original_channels = channels;
2411 if (!
info.has_video || !video_st)
return;
2414 oc->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
2416#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
2418 int proj = av_spherical_from_name(projection.c_str());
2420 proj = AV_SPHERICAL_EQUIRECTANGULAR;
2424 AVSphericalMapping* map = av_spherical_alloc(&sd_size);
2428 map->projection =
static_cast<AVSphericalProjection
>(proj);
2430 map->yaw =
static_cast<int32_t
>(yaw_deg * (1 << 16));
2431 map->pitch =
static_cast<int32_t
>(pitch_deg * (1 << 16));
2432 map->roll =
static_cast<int32_t
>(roll_deg * (1 << 16));
2435#if (LIBAVFORMAT_VERSION_MAJOR < 62)
2436 av_stream_add_side_data(video_st, AV_PKT_DATA_SPHERICAL,
reinterpret_cast<uint8_t*
>(map), sd_size);
2438 av_packet_side_data_add(&video_st->codecpar->coded_side_data, &video_st->codecpar->nb_coded_side_data, AV_PKT_DATA_SPHERICAL,
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.
Header file for ZeroMQ-based Logger class.
void Close()
Close the writer.
void SetAudioOptions(bool has_audio, std::string codec, int sample_rate, int channels, openshot::ChannelLayout channel_layout, int bit_rate)
Set audio export options.
void SetOption(openshot::StreamType stream, std::string name, std::string value)
Set custom options (some codecs accept additional params). This must be called after the PrepareStrea...
void PrepareStreams()
Prepare & initialize streams and open codecs. This method is called automatically by the Open() metho...
void SetVideoOptions(bool has_video, std::string codec, openshot::Fraction fps, int width, int height, openshot::Fraction pixel_ratio, bool interlaced, bool top_field_first, int bit_rate)
Set video export options.
void ResampleAudio(int sample_rate, int channels)
Set audio resample options.
void 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 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 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).
bool has_audio
Determines if this file has an 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).
int width
The width of the video (in pixels).