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), cache_size(1), num_of_rescalers(1),
79 rescaler_position(0), 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) {
101 if (!prepare_streams)
106 open_video(oc, video_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) {
130 "Could not deduce output format from file extension.", path);
134 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
135 info.
vcodec = avcodec_find_encoder(oc->oformat->video_codec)->name;
138 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
139 info.
acodec = avcodec_find_encoder(oc->oformat->audio_codec)->name;
143void FFmpegWriter::initialize_streams() {
145 "FFmpegWriter::initialize_streams",
146 "oc->oformat->video_codec", oc->oformat->video_codec,
147 "oc->oformat->audio_codec", oc->oformat->audio_codec,
148 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
153 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
155 video_st = add_video_stream();
157 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
159 audio_st = add_audio_stream();
165 if (
codec.length() > 0) {
166 const AVCodec *new_codec;
169#if defined(__linux__)
170 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
171 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
176 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
177 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
183 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
188 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
189 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
194 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
195 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
201 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
205#elif defined(__APPLE__)
206 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
207 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
213 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
218 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
221 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
223 if (new_codec == NULL)
224 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
243 if (pixel_ratio.
num > 0) {
247 if (bit_rate >= 1000)
249 if ((bit_rate >= 0) && (bit_rate < 256))
266 "FFmpegWriter::SetVideoOptions (" +
codec +
")",
267 "width", width,
"height", height,
268 "size.num", size.
num,
"size.den", size.
den,
269 "fps.num", fps.
num,
"fps.den", fps.
den);
279 true,
codec, fps, width, height,
288 if (
codec.length() > 0) {
289 const AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
290 if (new_codec == NULL)
291 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
297 if (sample_rate > 7999)
306 if (original_sample_rate == 0)
308 if (original_channels == 0)
312 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
313 "sample_rate", sample_rate,
314 "channels", channels,
315 "bit_rate", bit_rate);
326 true,
codec, sample_rate, 2,
335 AVCodecContext *c = NULL;
337 std::stringstream convert(value);
356 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
359 const AVOption *option = NULL;
367 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
368 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
369 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp")) {
373 convert >> c->gop_size;
375 else if (name ==
"qmin")
379 else if (name ==
"qmax")
383 else if (name ==
"max_b_frames")
385 convert >> c->max_b_frames;
387 else if (name ==
"mb_decision")
389 convert >> c->mb_decision;
391 else if (name ==
"level")
395 else if (name ==
"profile")
397 convert >> c->profile;
399 else if (name ==
"slices")
401 convert >> c->slices;
403 else if (name ==
"rc_min_rate")
405 convert >> c->rc_min_rate;
407 else if (name ==
"rc_max_rate")
409 convert >> c->rc_max_rate;
411 else if (name ==
"rc_buffer_size")
413 convert >> c->rc_buffer_size;
415 else if (name ==
"cqp") {
421 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
425 switch (c->codec_id) {
426#if (LIBAVCODEC_VERSION_MAJOR >= 58)
428 case AV_CODEC_ID_AV1 :
430 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
433 case AV_CODEC_ID_VP8 :
434 c->bit_rate = 10000000;
435 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
437 case AV_CODEC_ID_VP9 :
439 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
440 if (std::stoi(value) == 0) {
441 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
442 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
445 case AV_CODEC_ID_H264 :
446 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
447 if (std::stoi(value) == 0) {
448 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
452 case AV_CODEC_ID_HEVC :
453 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
454 if (std::stoi(value) == 0) {
455 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
456 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
461 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
465 }
else if (name ==
"crf") {
471 double mbs = 15000000.0;
480 c->bit_rate = (int)(mbs);
484 switch (c->codec_id) {
485#if (LIBAVCODEC_VERSION_MAJOR >= 58)
487 case AV_CODEC_ID_AV1 :
490 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
493 case AV_CODEC_ID_VP8 :
494 c->bit_rate = 10000000;
495 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
497 case AV_CODEC_ID_VP9 :
499 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
500 if (std::stoi(value) == 0) {
501 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
502 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
505 case AV_CODEC_ID_H264 :
506 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
507 if (std::stoi(value) == 0) {
508 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
512 case AV_CODEC_ID_HEVC :
513 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
514 av_opt_set_int(c->priv_data,
"preset", 7, 0);
515 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
516 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
519 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
521 if (std::stoi(value) == 0) {
522 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
523 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
529 double mbs = 15000000.0;
537 c->bit_rate = (int) (mbs);
540 }
else if (name ==
"qp") {
544#if (LIBAVCODEC_VERSION_MAJOR >= 58)
546 switch (c->codec_id) {
547 case AV_CODEC_ID_AV1 :
549 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
550 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
552 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
555 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
557 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
561 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
564 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
566 case AV_CODEC_ID_HEVC :
568 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
569 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
570 av_opt_set_int(c->priv_data,
"preset", 7, 0);
571 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
578 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
582 "FFmpegWriter::SetOption (" + (std::string)name +
")",
587 }
else if (name ==
"muxing_preset") {
588 if (value ==
"mp4_faststart") {
590 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
591 }
else if (value ==
"mp4_fragmented") {
593 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
594 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
597 throw InvalidOptions(
"The option is not valid for this codec.", path);
608 if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
617 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
620 "FFmpegWriter::PrepareStreams [" + path +
"]",
625 initialize_streams();
628 prepare_streams =
true;
634 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
637 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
638 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
639 throw InvalidFile(
"Could not open or write file.", path);
646 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
647 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
651 AVDictionary *dict = NULL;
653 bool is_mp4 = strcmp(oc->oformat->name,
"mp4");
654 bool is_mov = strcmp(oc->oformat->name,
"mov");
656 if (is_mp4 || is_mov)
660 if (avformat_write_header(oc, &dict) != 0) {
662 "FFmpegWriter::WriteHeader (avformat_write_header)");
663 throw InvalidFile(
"Could not write header to file.", path);
667 if (dict) av_dict_free(&dict);
680 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
685 spooled_video_frames.push_back(frame);
688 spooled_audio_frames.push_back(frame);
691 "FFmpegWriter::WriteFrame",
692 "frame->number", frame->number,
693 "spooled_video_frames.size()", spooled_video_frames.size(),
694 "spooled_audio_frames.size()", spooled_audio_frames.size(),
695 "cache_size", cache_size,
696 "is_writing", is_writing);
699 if ((
int)spooled_video_frames.size() == cache_size || (
int)spooled_audio_frames.size() == cache_size) {
701 write_queued_frames();
709void FFmpegWriter::write_queued_frames() {
711 "FFmpegWriter::write_queued_frames",
712 "spooled_video_frames.size()", spooled_video_frames.size(),
713 "spooled_audio_frames.size()", spooled_audio_frames.size());
719 queued_video_frames = spooled_video_frames;
720 queued_audio_frames = spooled_audio_frames;
723 spooled_video_frames.clear();
724 spooled_audio_frames.clear();
727 bool has_error_encoding_video =
false;
730 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
731 write_audio_packets(
false);
734 while (!queued_video_frames.empty()) {
736 std::shared_ptr<Frame> frame = queued_video_frames.front();
739 processed_frames.push_back(frame);
743 process_video_packet(frame);
746 queued_video_frames.pop_front();
752 while (!processed_frames.empty()) {
754 std::shared_ptr<Frame> frame = processed_frames.front();
758 deallocate_frames.push_back(frame);
761 if (av_frames.count(frame)) {
763 AVFrame *frame_final = av_frames[frame];
766 bool success = write_video_packet(frame, frame_final);
768 has_error_encoding_video =
true;
773 processed_frames.pop_front();
777 while (!deallocate_frames.empty()) {
779 std::shared_ptr<Frame> frame = deallocate_frames.front();
782 if (av_frames.count(frame)) {
784 AVFrame *av_frame = av_frames[frame];
787 av_freep(&(av_frame->data[0]));
789 av_frames.erase(frame);
793 deallocate_frames.pop_front();
800 if (has_error_encoding_video)
807 "FFmpegWriter::WriteFrame (from Reader)",
812 for (int64_t number = start; number <= length; number++) {
814 std::shared_ptr<Frame> f = reader->
GetFrame(number);
824 write_queued_frames();
828 write_audio_packets(
true);
837 av_write_trailer(oc);
840 write_trailer =
true;
846void FFmpegWriter::flush_encoders() {
849#if (LIBAVFORMAT_VERSION_MAJOR < 58)
863 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
866 AVPacket* pkt = av_packet_alloc();
880 error_code = avcodec_send_frame(video_codec_ctx, NULL);
882 while (error_code >= 0) {
883 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
884 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
887 avcodec_flush_buffers(video_codec_ctx);
890 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
891 pkt->stream_index = video_st->index;
892 error_code = av_interleaved_write_frame(oc, pkt);
897 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
901 if (error_code < 0) {
903 "FFmpegWriter::flush_encoders ERROR ["
904 + av_err2string(error_code) +
"]",
905 "error_code", error_code);
912 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
913 pkt->stream_index = video_st->index;
916 error_code = av_interleaved_write_frame(oc, pkt);
917 if (error_code < 0) {
919 "FFmpegWriter::flush_encoders ERROR ["
920 + av_err2string(error_code) +
"]",
921 "error_code", error_code);
930 AVPacket* pkt = av_packet_alloc();
937 pkt->pts = pkt->dts = audio_timestamp;
943 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
945 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
947 if (error_code < 0) {
949 "FFmpegWriter::flush_encoders ERROR ["
950 + av_err2string(error_code) +
"]",
951 "error_code", error_code);
959 pkt->pts = pkt->dts = audio_timestamp;
962 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
965 pkt->stream_index = audio_st->index;
966 pkt->flags |= AV_PKT_FLAG_KEY;
969 error_code = av_interleaved_write_frame(oc, pkt);
970 if (error_code < 0) {
972 "FFmpegWriter::flush_encoders ERROR ["
973 + av_err2string(error_code) +
"]",
974 "error_code", error_code);
978 audio_timestamp += pkt->duration;
988void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
993 av_buffer_unref(&hw_device_ctx);
994 hw_device_ctx = NULL;
1000 if (video_codec_ctx !=
nullptr) {
1002 av_free(video_codec_ctx);
1007void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
1011 delete[] audio_outbuf;
1012 delete[] audio_encoder_buffer;
1014 audio_outbuf = NULL;
1015 audio_encoder_buffer = NULL;
1031 if (audio_codec_ctx !=
nullptr) {
1033 av_free(audio_codec_ctx);
1045 close_video(oc, video_st);
1047 close_audio(oc, audio_st);
1050 if (image_rescalers.size() > 0)
1053 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1059 video_timestamp = 0;
1060 audio_timestamp = 0;
1063 avformat_free_context(oc);
1068 prepare_streams =
false;
1069 write_header =
false;
1070 write_trailer =
false;
1076void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1078 if (!av_frames.count(frame)) {
1080 av_frames[frame] = av_frame;
1088AVStream *FFmpegWriter::add_audio_stream() {
1090 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1092 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1095 if (audio_codec_ctx !=
nullptr) {
1100 AVStream* st = avformat_new_stream(oc,
codec);
1102 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1106#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1107 st->codecpar->codec_id =
codec->id;
1109 AVCodecContext* c = audio_codec_ctx;
1111 c->codec_id =
codec->id;
1112 c->codec_type = AVMEDIA_TYPE_AUDIO;
1121 if (
codec->supported_samplerates) {
1123 for (i = 0;
codec->supported_samplerates[i] != 0; i++)
1129 if (
codec->supported_samplerates[i] == 0)
1130 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1138 AVChannelLayout ch_layout;
1140 if (
codec->ch_layouts) {
1142 for (i = 0; av_channel_layout_check(&
codec->ch_layouts[i]); i++)
1143 if (av_channel_layout_compare(&ch_layout, &
codec->ch_layouts[i])) {
1145 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1148 if (!av_channel_layout_check(&
codec->ch_layouts[i]))
1149 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1152 av_channel_layout_copy(&c->ch_layout, &ch_layout);
1156 if (
codec->channel_layouts) {
1158 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1159 if (channel_layout ==
codec->channel_layouts[i]) {
1161 c->channel_layout = channel_layout;
1164 if (
codec->channel_layouts[i] == 0)
1165 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1168 c->channel_layout = channel_layout;
1172 if (
codec->sample_fmts) {
1173 for (
int i = 0;
codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1175 c->sample_fmt =
codec->sample_fmts[i];
1179 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1181 c->sample_fmt = AV_SAMPLE_FMT_S16;
1185 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1186#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1188 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1190 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1196uint64_t channel_layout;
1197const char* nb_channels_label;
1198const char* channel_layout_label;
1201 nb_channels = c->ch_layout.nb_channels;
1202 channel_layout = c->ch_layout.u.mask;
1203 nb_channels_label =
"c->ch_layout.nb_channels";
1204 channel_layout_label =
"c->ch_layout.u.mask";
1206 nb_channels = c->channels;
1207 channel_layout = c->channel_layout;
1208 nb_channels_label =
"c->channels";
1209 channel_layout_label =
"c->channel_layout";
1213 "FFmpegWriter::add_audio_stream",
1214 "c->codec_id", c->codec_id,
1215 "c->bit_rate", c->bit_rate,
1216 nb_channels_label, nb_channels,
1217 "c->sample_fmt", c->sample_fmt,
1218 channel_layout_label, channel_layout,
1219 "c->sample_rate", c->sample_rate);
1225AVStream *FFmpegWriter::add_video_stream() {
1227 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1229 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1232 if (video_codec_ctx !=
nullptr) {
1237 AVStream* st = avformat_new_stream(oc,
codec);
1239 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1243#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1244 st->codecpar->codec_id =
codec->id;
1247 AVCodecContext* c = video_codec_ctx;
1249 c->codec_id =
codec->id;
1250 c->codec_type = AVMEDIA_TYPE_VIDEO;
1258#
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1259 && c->codec_id != AV_CODEC_ID_AV1
1264 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1273 switch (c->codec_id) {
1274#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1276 case AV_CODEC_ID_AV1 :
1280 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1281 int calculated_quality = 35;
1284 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1287 int calculated_quality = 50;
1290 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1294 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1295 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1296 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1298 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1299 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1300 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1301 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1303 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1306 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1307 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1308 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1309 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1313 case AV_CODEC_ID_VP9 :
1314 case AV_CODEC_ID_HEVC :
1315 case AV_CODEC_ID_VP8 :
1316 case AV_CODEC_ID_H264 :
1352#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1353 c->framerate = av_inv_q(c->time_base);
1355 st->avg_frame_rate = av_inv_q(c->time_base);
1360 c->max_b_frames = 10;
1361 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1363 c->max_b_frames = 2;
1364 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1370 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1371#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1373 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1375 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1380 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1383 c->pix_fmt = *supported_pixel_formats;
1384 ++supported_pixel_formats;
1389 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1393#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1395 if (strcmp(oc->oformat->name,
"gif") != 0)
1398 oc->oformat->flags |= AVFMT_RAWPICTURE;
1408 "FFmpegWriter::add_video_stream ("
1409 + (std::string)oc->oformat->name +
" : "
1410 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1411 "c->codec_id", c->codec_id,
1412 "c->bit_rate", c->bit_rate,
1413 "c->pix_fmt", c->pix_fmt,
1414 "oc->oformat->flags", oc->oformat->flags);
1419void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1420 const AVCodec *
codec;
1429 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1434 AVDictionary *
opts = NULL;
1435 av_dict_set(&
opts,
"strict",
"experimental", 0);
1438 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1439 throw InvalidCodec(
"Could not open audio codec", path);
1443 av_dict_free(&
opts);
1447 if (audio_codec_ctx->frame_size <= 1) {
1453 case AV_CODEC_ID_PCM_S16LE:
1454 case AV_CODEC_ID_PCM_S16BE:
1455 case AV_CODEC_ID_PCM_U16LE:
1456 case AV_CODEC_ID_PCM_U16BE:
1457 audio_input_frame_size >>= 1;
1464 audio_input_frame_size = audio_codec_ctx->frame_size;
1468 initial_audio_input_frame_size = audio_input_frame_size;
1475 audio_outbuf =
new uint8_t[audio_outbuf_size];
1479 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1482 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1483 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1487 "FFmpegWriter::open_audio",
1488 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1489 "audio_input_frame_size", audio_input_frame_size,
1494void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1495 const AVCodec *
codec;
1505 char *adapter_ptr = NULL;
1509 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1510 if (adapter_num < 3 && adapter_num >=0) {
1511#if defined(__linux__)
1512 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1514 adapter_ptr = adapter;
1515#elif defined(_WIN32) || defined(__APPLE__)
1523#if defined(__linux__)
1524 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1525#elif defined(_WIN32) || defined(__APPLE__)
1526 if( adapter_ptr != NULL ) {
1529 "Encode Device present using device",
1530 "adapter", adapter_num);
1535 "Encode Device not present, using default");
1537 if (av_hwdevice_ctx_create(&hw_device_ctx,
1541 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1556 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)
1557 video_codec_ctx->max_b_frames = 0;
1561 av_dict_set(&
opts,
"strict",
"experimental", 0);
1575 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1577 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1581 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1585 switch (video_codec_ctx->codec_id) {
1586 case AV_CODEC_ID_H264:
1587 video_codec_ctx->max_b_frames = 0;
1588 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1589 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1590 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1591 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1593 case AV_CODEC_ID_HEVC:
1596 case AV_CODEC_ID_VP9:
1601 "No codec-specific options defined for this codec. HW encoding may fail",
1602 "codec_id", video_codec_ctx->codec_id);
1611 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1614 av_err2string(err), -1);
1621 throw InvalidCodec(
"Could not open video codec", path);
1625 av_dict_free(&
opts);
1629 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1633 "FFmpegWriter::open_video",
1634 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1639void FFmpegWriter::write_audio_packets(
bool is_final) {
1641 int total_frame_samples = 0;
1642 int frame_position = 0;
1643 int channels_in_frame = 0;
1644 int sample_rate_in_frame = 0;
1645 int samples_in_frame = 0;
1650 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1651 int16_t *all_resampled_samples = NULL;
1652 int16_t *final_samples_planar = NULL;
1653 int16_t *final_samples = NULL;
1656 while (!queued_audio_frames.empty()) {
1658 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1661 sample_rate_in_frame = frame->SampleRate();
1662 samples_in_frame = frame->GetAudioSamplesCount();
1663 channels_in_frame = frame->GetAudioChannelsCount();
1664 channel_layout_in_frame = frame->ChannelsLayout();
1667 float *frame_samples_float = NULL;
1669 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1672 total_frame_samples = samples_in_frame * channels_in_frame;
1675 const int16_t max16 = 32767;
1676 const int16_t min16 = -32768;
1677 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1678 float valF = frame_samples_float[s] * (1 << 15);
1682 }
else if (valF < min16) {
1685 conv = int(valF + 32768.5) - 32768;
1689 all_queued_samples[frame_position] = conv;
1693 delete[] frame_samples_float;
1696 queued_audio_frames.pop_front();
1702 total_frame_samples = frame_position;
1703 int remaining_frame_samples = total_frame_samples;
1704 int samples_position = 0;
1708 "FFmpegWriter::write_audio_packets",
1709 "is_final", is_final,
1710 "total_frame_samples", total_frame_samples,
1711 "channel_layout_in_frame", channel_layout_in_frame,
1712 "channels_in_frame", channels_in_frame,
1713 "samples_in_frame", samples_in_frame,
1717 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1719 AVFrame *audio_frame = NULL;
1724 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1727 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);
1728 if (error_code < 0) {
1730 "FFmpegWriter::write_audio_packets ERROR ["
1731 + av_err2string(error_code) +
"]",
1732 "error_code", error_code);
1736 switch (audio_codec_ctx->sample_fmt) {
1737 case AV_SAMPLE_FMT_FLTP: {
1738 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1741 case AV_SAMPLE_FMT_S32P: {
1742 output_sample_fmt = AV_SAMPLE_FMT_S32;
1745 case AV_SAMPLE_FMT_S16P: {
1746 output_sample_fmt = AV_SAMPLE_FMT_S16;
1749 case AV_SAMPLE_FMT_U8P: {
1750 output_sample_fmt = AV_SAMPLE_FMT_U8;
1760 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1761 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1766 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1767 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1770 "FFmpegWriter::write_audio_packets (1st resampling)",
1771 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1772 "out_sample_fmt", output_sample_fmt,
1773 "in_sample_rate", sample_rate_in_frame,
1775 "in_channels", channels_in_frame,
1782 AVChannelLayout in_chlayout;
1783 AVChannelLayout out_chlayout;
1784 av_channel_layout_from_mask(&in_chlayout, channel_layout_in_frame);
1786 av_opt_set_chlayout(avr,
"in_chlayout", &in_chlayout, 0);
1787 av_opt_set_chlayout(avr,
"out_chlayout", &out_chlayout, 0);
1789 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1791 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1794 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1795 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1796 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1803 audio_converted->data,
1804 audio_converted->linesize[0],
1805 audio_converted->nb_samples,
1807 audio_frame->linesize[0],
1808 audio_frame->nb_samples
1812 remaining_frame_samples = total_frame_samples;
1815 all_resampled_samples = (int16_t *) av_malloc(
1817 * (av_get_bytes_per_sample(output_sample_fmt) /
1818 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1822 memcpy(all_resampled_samples, audio_converted->data[0],
1823 static_cast<size_t>(nb_samples)
1825 * av_get_bytes_per_sample(output_sample_fmt));
1828 av_freep(&(audio_frame->data[0]));
1830 av_freep(&audio_converted->data[0]);
1832 all_queued_samples = NULL;
1835 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1836 "nb_samples", nb_samples,
1837 "remaining_frame_samples", remaining_frame_samples);
1841 while (remaining_frame_samples > 0 || is_final) {
1843 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1847 if (remaining_frame_samples >= remaining_packet_samples) {
1848 diff = remaining_packet_samples;
1850 diff = remaining_frame_samples;
1857 samples + (audio_input_position
1858 * (av_get_bytes_per_sample(output_sample_fmt) /
1859 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1861 all_resampled_samples + samples_position,
1862 static_cast<size_t>(diff)
1863 * av_get_bytes_per_sample(output_sample_fmt)
1867 audio_input_position += diff;
1868 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1869 remaining_frame_samples -= diff;
1872 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1879 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1881 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1882 "in_sample_fmt", output_sample_fmt,
1883 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1894 AVChannelLayout layout;
1896 av_opt_set_chlayout(avr_planar,
"in_chlayout", &layout, 0);
1897 av_opt_set_chlayout(avr_planar,
"out_chlayout", &layout, 0);
1901 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1902 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1904 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1905 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1914 audio_frame->nb_samples = audio_input_position /
info.
channels;
1917 final_samples_planar = (int16_t *) av_malloc(
1918 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1919 * (av_get_bytes_per_sample(output_sample_fmt) /
1920 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1924 memcpy(final_samples_planar, samples,
1925 static_cast<size_t>(audio_frame->nb_samples)
1927 * av_get_bytes_per_sample(output_sample_fmt));
1930 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1931 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1934 frame_final->nb_samples = audio_input_frame_size;
1941 frame_final->format = audio_codec_ctx->sample_fmt;
1942 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1943 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1949 frame_final->linesize[0],
1950 frame_final->nb_samples,
1952 audio_frame->linesize[0],
1953 audio_frame->nb_samples
1957 const auto copy_length =
static_cast<size_t>(nb_samples)
1958 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
1962 memcpy(samples, frame_final->data[0], copy_length);
1965 av_freep(&(audio_frame->data[0]));
1967 all_queued_samples = NULL;
1970 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
1971 "nb_samples", nb_samples);
1975 const auto buf_size =
static_cast<size_t>(audio_input_position)
1976 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1977 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
1979 final_samples =
reinterpret_cast<int16_t*
>(
1980 av_malloc(
sizeof(int16_t) * buf_size));
1983 memcpy(final_samples, samples,
1984 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1987 frame_final->nb_samples = audio_input_frame_size;
1991 int nb_channels = audio_codec_ctx->ch_layout.nb_channels;
1993 int nb_channels = audio_codec_ctx->channels;
1995 avcodec_fill_audio_frame(frame_final, nb_channels,
1996 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1997 audio_encoder_buffer_size, 0);
2001 frame_final->pts = audio_timestamp;
2005 AVPacket* pkt = av_packet_alloc();
2008 av_init_packet(pkt);
2010 pkt->data = audio_encoder_buffer;
2011 pkt->size = audio_encoder_buffer_size;
2014 pkt->pts = pkt->dts = audio_timestamp;
2017 int got_packet_ptr = 0;
2023 int frame_finished = 0;
2024 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
2025 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
2026 avcodec_send_frame(audio_codec_ctx, NULL);
2031 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
2034 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
2035 avcodec_flush_buffers(audio_codec_ctx);
2039 ret = frame_finished;
2042 if (!pkt->data && !frame_finished)
2046 got_packet_ptr = ret;
2049 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
2052 if (error_code == 0 && got_packet_ptr) {
2056 pkt->pts = pkt->dts = audio_timestamp;
2059 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2062 pkt->stream_index = audio_st->index;
2063 pkt->flags |= AV_PKT_FLAG_KEY;
2066 error_code = av_interleaved_write_frame(oc, pkt);
2069 if (error_code < 0) {
2071 "FFmpegWriter::write_audio_packets ERROR ["
2072 + av_err2string(error_code) +
"]",
2073 "error_code", error_code);
2077 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2080 av_freep(&(frame_final->data[0]));
2087 audio_input_position = 0;
2092 if (all_resampled_samples) {
2093 av_freep(&all_resampled_samples);
2094 all_resampled_samples = NULL;
2096 if (all_queued_samples) {
2097 av_freep(&all_queued_samples);
2098 all_queued_samples = NULL;
2103AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2105 AVFrame *new_av_frame = NULL;
2109 if (new_av_frame == NULL)
2110 throw OutOfMemory(
"Could not allocate AVFrame", path);
2118 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
2121 new_av_frame->width = width;
2122 new_av_frame->height = height;
2123 new_av_frame->format = pix_fmt;
2127 return new_av_frame;
2131void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2133 int source_image_width = frame->GetWidth();
2134 int source_image_height = frame->GetHeight();
2137 if (source_image_height == 1 && source_image_width == 1)
2141 if (image_rescalers.size() == 0)
2142 InitScalers(source_image_width, source_image_height);
2145 SwsContext *scaler = image_rescalers[rescaler_position];
2146 rescaler_position++;
2147 if (rescaler_position == num_of_rescalers)
2148 rescaler_position = 0;
2151 int bytes_source = 0;
2152 int bytes_final = 0;
2153 AVFrame *frame_source = NULL;
2154 const uchar *pixels = NULL;
2157 pixels = frame->GetPixels();
2160 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
2162 AVFrame *frame_final;
2165 frame_final = allocate_avframe(AV_PIX_FMT_NV12,
info.
width,
info.
height, &bytes_final, NULL);
2169 frame_final = allocate_avframe(
2170 (AVPixelFormat)(video_st->codecpar->format),
2175 AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
2181 "FFmpegWriter::process_video_packet",
2182 "frame->number", frame->number,
2183 "bytes_source", bytes_source,
2184 "bytes_final", bytes_final);
2187 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
2188 source_image_height, frame_final->data, frame_final->linesize);
2191 add_avframe(frame, frame_final);
2198bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2199#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2202 "FFmpegWriter::write_video_packet",
2203 "frame->number", frame->number,
2204 "oc->oformat->flags", oc->oformat->flags);
2212 "FFmpegWriter::write_video_packet",
2213 "frame->number", frame->number,
2214 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2216 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2220 AVPacket* pkt = av_packet_alloc();
2223 av_init_packet(pkt);
2226 av_packet_from_data(
2227 pkt, frame_final->data[0],
2228 frame_final->linesize[0] * frame_final->height);
2230 pkt->flags |= AV_PKT_FLAG_KEY;
2231 pkt->stream_index = video_st->index;
2234 pkt->pts = video_timestamp;
2237 int error_code = av_interleaved_write_frame(oc, pkt);
2238 if (error_code < 0) {
2240 "FFmpegWriter::write_video_packet ERROR ["
2241 + av_err2string(error_code) +
"]",
2242 "error_code", error_code);
2253 AVPacket* pkt = av_packet_alloc();
2256 av_init_packet(pkt);
2260 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2263 frame_final->pts = video_timestamp;
2266 if (!(
hw_frame = av_frame_alloc())) {
2267 std::clog <<
"Error code: av_hwframe_alloc\n";
2269 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2270 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2273 std::clog <<
"Error hw_frames_ctx.\n";
2275 hw_frame->format = AV_PIX_FMT_NV12;
2276 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2277 std::clog <<
"Error while transferring frame data to surface.\n";
2279 av_frame_copy_props(
hw_frame, frame_final);
2283 int got_packet_ptr = 0;
2291 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2295 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2300 "FFmpegWriter::write_video_packet (Frame not sent)");
2301 if (ret == AVERROR(EAGAIN) ) {
2302 std::clog <<
"Frame EAGAIN\n";
2304 if (ret == AVERROR_EOF ) {
2305 std::clog <<
"Frame AVERROR_EOF\n";
2307 avcodec_send_frame(video_codec_ctx, NULL);
2311 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2313 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2314 avcodec_flush_buffers(video_codec_ctx);
2326 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2327 if (error_code != 0) {
2329 "FFmpegWriter::write_video_packet ERROR ["
2330 + av_err2string(error_code) +
"]",
2331 "error_code", error_code);
2333 if (got_packet_ptr == 0) {
2335 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2340 if (error_code == 0 && got_packet_ptr) {
2342 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2343 pkt->stream_index = video_st->index;
2346 int result = av_interleaved_write_frame(oc, pkt);
2349 "FFmpegWriter::write_video_packet ERROR ["
2350 + av_err2string(result) +
"]",
2369 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2378 av_dump_format(oc, 0, path.c_str(), 1);
2382void FFmpegWriter::InitScalers(
int source_width,
int source_height) {
2383 int scale_mode = SWS_FAST_BILINEAR;
2385 scale_mode = SWS_BICUBIC;
2389 for (
int x = 0; x < num_of_rescalers; x++) {
2393 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2398 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2400 scale_mode, NULL, NULL, NULL);
2404 image_rescalers.push_back(img_convert_ctx);
2410 original_sample_rate = sample_rate;
2411 original_channels = channels;
2417 for (
int x = 0; x < num_of_rescalers; x++)
2418 sws_freeContext(image_rescalers[x]);
2421 image_rescalers.clear();
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_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
#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_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 ResampleAudio(int sample_rate, int channels)
Set audio resample options.
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...
void RemoveScalers()
Remove & deallocate all software scalers.
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.