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;
1119 if (
codec->supported_samplerates) {
1121 for (i = 0;
codec->supported_samplerates[i] != 0; i++)
1127 if (
codec->supported_samplerates[i] == 0)
1128 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1136 if (
codec->channel_layouts) {
1138 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1139 if (channel_layout ==
codec->channel_layouts[i]) {
1141 c->channel_layout = channel_layout;
1144 if (
codec->channel_layouts[i] == 0)
1145 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1148 c->channel_layout = channel_layout;
1151 if (
codec->sample_fmts) {
1152 for (
int i = 0;
codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1154 c->sample_fmt =
codec->sample_fmts[i];
1158 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1160 c->sample_fmt = AV_SAMPLE_FMT_S16;
1164 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1165#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1167 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1169 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1175 "FFmpegWriter::add_audio_stream",
1176 "c->codec_id", c->codec_id,
1177 "c->bit_rate", c->bit_rate,
1178 "c->channels", c->channels,
1179 "c->sample_fmt", c->sample_fmt,
1180 "c->channel_layout", c->channel_layout,
1181 "c->sample_rate", c->sample_rate);
1187AVStream *FFmpegWriter::add_video_stream() {
1189 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1191 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1194 if (video_codec_ctx !=
nullptr) {
1199 AVStream* st = avformat_new_stream(oc,
codec);
1201 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1205#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1206 st->codecpar->codec_id =
codec->id;
1209 AVCodecContext* c = video_codec_ctx;
1211 c->codec_id =
codec->id;
1212 c->codec_type = AVMEDIA_TYPE_VIDEO;
1220#
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1221 && c->codec_id != AV_CODEC_ID_AV1
1226 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1235 switch (c->codec_id) {
1236#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1238 case AV_CODEC_ID_AV1 :
1242 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1243 int calculated_quality = 35;
1246 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1249 int calculated_quality = 50;
1252 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1256 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1257 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1258 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1260 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1261 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1262 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1263 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1265 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1268 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1269 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1270 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1271 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1275 case AV_CODEC_ID_VP9 :
1276 case AV_CODEC_ID_HEVC :
1277 case AV_CODEC_ID_VP8 :
1278 case AV_CODEC_ID_H264 :
1314#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1315 c->framerate = av_inv_q(c->time_base);
1317 st->avg_frame_rate = av_inv_q(c->time_base);
1322 c->max_b_frames = 10;
1323 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1325 c->max_b_frames = 2;
1326 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1332 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1333#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1335 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1337 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1342 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1345 c->pix_fmt = *supported_pixel_formats;
1346 ++supported_pixel_formats;
1351 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1355#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1357 if (strcmp(oc->oformat->name,
"gif") != 0)
1360 oc->oformat->flags |= AVFMT_RAWPICTURE;
1370 "FFmpegWriter::add_video_stream ("
1371 + (std::string)oc->oformat->name +
" : "
1372 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1373 "c->codec_id", c->codec_id,
1374 "c->bit_rate", c->bit_rate,
1375 "c->pix_fmt", c->pix_fmt,
1376 "oc->oformat->flags", oc->oformat->flags);
1381void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1382 const AVCodec *
codec;
1391 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1396 AVDictionary *
opts = NULL;
1397 av_dict_set(&
opts,
"strict",
"experimental", 0);
1400 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1401 throw InvalidCodec(
"Could not open audio codec", path);
1405 av_dict_free(&
opts);
1409 if (audio_codec_ctx->frame_size <= 1) {
1415 case AV_CODEC_ID_PCM_S16LE:
1416 case AV_CODEC_ID_PCM_S16BE:
1417 case AV_CODEC_ID_PCM_U16LE:
1418 case AV_CODEC_ID_PCM_U16BE:
1419 audio_input_frame_size >>= 1;
1426 audio_input_frame_size = audio_codec_ctx->frame_size;
1430 initial_audio_input_frame_size = audio_input_frame_size;
1437 audio_outbuf =
new uint8_t[audio_outbuf_size];
1441 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1444 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1445 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1449 "FFmpegWriter::open_audio",
1450 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1451 "audio_input_frame_size", audio_input_frame_size,
1456void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1457 const AVCodec *
codec;
1467 char *adapter_ptr = NULL;
1471 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1472 if (adapter_num < 3 && adapter_num >=0) {
1473#if defined(__linux__)
1474 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1476 adapter_ptr = adapter;
1477#elif defined(_WIN32) || defined(__APPLE__)
1485#if defined(__linux__)
1486 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1487#elif defined(_WIN32) || defined(__APPLE__)
1488 if( adapter_ptr != NULL ) {
1491 "Encode Device present using device",
1492 "adapter", adapter_num);
1497 "Encode Device not present, using default");
1499 if (av_hwdevice_ctx_create(&hw_device_ctx,
1503 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1518 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)
1519 video_codec_ctx->max_b_frames = 0;
1523 av_dict_set(&
opts,
"strict",
"experimental", 0);
1537 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1539 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1543 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1547 switch (video_codec_ctx->codec_id) {
1548 case AV_CODEC_ID_H264:
1549 video_codec_ctx->max_b_frames = 0;
1550 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1551 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1552 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1553 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1555 case AV_CODEC_ID_HEVC:
1558 case AV_CODEC_ID_VP9:
1563 "No codec-specific options defined for this codec. HW encoding may fail",
1564 "codec_id", video_codec_ctx->codec_id);
1573 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1576 av_err2string(err), -1);
1583 throw InvalidCodec(
"Could not open video codec", path);
1587 av_dict_free(&
opts);
1591 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1595 "FFmpegWriter::open_video",
1596 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1601void FFmpegWriter::write_audio_packets(
bool is_final) {
1603 int total_frame_samples = 0;
1604 int frame_position = 0;
1605 int channels_in_frame = 0;
1606 int sample_rate_in_frame = 0;
1607 int samples_in_frame = 0;
1612 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1613 int16_t *all_resampled_samples = NULL;
1614 int16_t *final_samples_planar = NULL;
1615 int16_t *final_samples = NULL;
1618 while (!queued_audio_frames.empty()) {
1620 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1623 sample_rate_in_frame = frame->SampleRate();
1624 samples_in_frame = frame->GetAudioSamplesCount();
1625 channels_in_frame = frame->GetAudioChannelsCount();
1626 channel_layout_in_frame = frame->ChannelsLayout();
1629 float *frame_samples_float = NULL;
1631 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1634 total_frame_samples = samples_in_frame * channels_in_frame;
1637 const int16_t max16 = 32767;
1638 const int16_t min16 = -32768;
1639 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1640 float valF = frame_samples_float[s] * (1 << 15);
1644 }
else if (valF < min16) {
1647 conv = int(valF + 32768.5) - 32768;
1651 all_queued_samples[frame_position] = conv;
1655 delete[] frame_samples_float;
1658 queued_audio_frames.pop_front();
1664 total_frame_samples = frame_position;
1665 int remaining_frame_samples = total_frame_samples;
1666 int samples_position = 0;
1670 "FFmpegWriter::write_audio_packets",
1671 "is_final", is_final,
1672 "total_frame_samples", total_frame_samples,
1673 "channel_layout_in_frame", channel_layout_in_frame,
1674 "channels_in_frame", channels_in_frame,
1675 "samples_in_frame", samples_in_frame,
1679 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1681 AVFrame *audio_frame = NULL;
1686 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1689 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);
1690 if (error_code < 0) {
1692 "FFmpegWriter::write_audio_packets ERROR ["
1693 + av_err2string(error_code) +
"]",
1694 "error_code", error_code);
1698 switch (audio_codec_ctx->sample_fmt) {
1699 case AV_SAMPLE_FMT_FLTP: {
1700 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1703 case AV_SAMPLE_FMT_S32P: {
1704 output_sample_fmt = AV_SAMPLE_FMT_S32;
1707 case AV_SAMPLE_FMT_S16P: {
1708 output_sample_fmt = AV_SAMPLE_FMT_S16;
1711 case AV_SAMPLE_FMT_U8P: {
1712 output_sample_fmt = AV_SAMPLE_FMT_U8;
1722 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1723 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1728 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1729 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1732 "FFmpegWriter::write_audio_packets (1st resampling)",
1733 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1734 "out_sample_fmt", output_sample_fmt,
1735 "in_sample_rate", sample_rate_in_frame,
1737 "in_channels", channels_in_frame,
1743 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1745 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1746 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1747 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1749 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1756 audio_converted->data,
1757 audio_converted->linesize[0],
1758 audio_converted->nb_samples,
1760 audio_frame->linesize[0],
1761 audio_frame->nb_samples
1765 remaining_frame_samples = total_frame_samples;
1768 all_resampled_samples = (int16_t *) av_malloc(
1770 * (av_get_bytes_per_sample(output_sample_fmt) /
1771 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1775 memcpy(all_resampled_samples, audio_converted->data[0],
1776 static_cast<size_t>(nb_samples)
1778 * av_get_bytes_per_sample(output_sample_fmt));
1781 av_freep(&(audio_frame->data[0]));
1783 av_freep(&audio_converted->data[0]);
1785 all_queued_samples = NULL;
1788 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1789 "nb_samples", nb_samples,
1790 "remaining_frame_samples", remaining_frame_samples);
1794 while (remaining_frame_samples > 0 || is_final) {
1796 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1800 if (remaining_frame_samples >= remaining_packet_samples) {
1801 diff = remaining_packet_samples;
1803 diff = remaining_frame_samples;
1810 samples + (audio_input_position
1811 * (av_get_bytes_per_sample(output_sample_fmt) /
1812 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1814 all_resampled_samples + samples_position,
1815 static_cast<size_t>(diff)
1816 * av_get_bytes_per_sample(output_sample_fmt)
1820 audio_input_position += diff;
1821 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1822 remaining_frame_samples -= diff;
1825 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1832 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1834 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1835 "in_sample_fmt", output_sample_fmt,
1836 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1848 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1849 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1852 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1853 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1860 audio_frame->nb_samples = audio_input_position /
info.
channels;
1863 final_samples_planar = (int16_t *) av_malloc(
1864 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1865 * (av_get_bytes_per_sample(output_sample_fmt) /
1866 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1870 memcpy(final_samples_planar, samples,
1871 static_cast<size_t>(audio_frame->nb_samples)
1873 * av_get_bytes_per_sample(output_sample_fmt));
1876 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1877 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1880 frame_final->nb_samples = audio_input_frame_size;
1882 frame_final->format = audio_codec_ctx->sample_fmt;
1884 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1885 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1891 frame_final->linesize[0],
1892 frame_final->nb_samples,
1894 audio_frame->linesize[0],
1895 audio_frame->nb_samples
1899 const auto copy_length =
static_cast<size_t>(nb_samples)
1900 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
1904 memcpy(samples, frame_final->data[0], copy_length);
1907 av_freep(&(audio_frame->data[0]));
1909 all_queued_samples = NULL;
1912 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
1913 "nb_samples", nb_samples);
1917 const auto buf_size =
static_cast<size_t>(audio_input_position)
1918 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1919 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
1921 final_samples =
reinterpret_cast<int16_t*
>(
1922 av_malloc(
sizeof(int16_t) * buf_size));
1925 memcpy(final_samples, samples,
1926 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1929 frame_final->nb_samples = audio_input_frame_size;
1932 avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1933 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1934 audio_encoder_buffer_size, 0);
1938 frame_final->pts = audio_timestamp;
1942 AVPacket* pkt = av_packet_alloc();
1945 av_init_packet(pkt);
1947 pkt->data = audio_encoder_buffer;
1948 pkt->size = audio_encoder_buffer_size;
1951 pkt->pts = pkt->dts = audio_timestamp;
1954 int got_packet_ptr = 0;
1960 int frame_finished = 0;
1961 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1962 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1963 avcodec_send_frame(audio_codec_ctx, NULL);
1968 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
1971 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1972 avcodec_flush_buffers(audio_codec_ctx);
1976 ret = frame_finished;
1979 if (!pkt->data && !frame_finished)
1983 got_packet_ptr = ret;
1986 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
1989 if (error_code == 0 && got_packet_ptr) {
1993 pkt->pts = pkt->dts = audio_timestamp;
1996 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
1999 pkt->stream_index = audio_st->index;
2000 pkt->flags |= AV_PKT_FLAG_KEY;
2003 error_code = av_interleaved_write_frame(oc, pkt);
2006 if (error_code < 0) {
2008 "FFmpegWriter::write_audio_packets ERROR ["
2009 + av_err2string(error_code) +
"]",
2010 "error_code", error_code);
2014 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2017 av_freep(&(frame_final->data[0]));
2024 audio_input_position = 0;
2029 if (all_resampled_samples) {
2030 av_freep(&all_resampled_samples);
2031 all_resampled_samples = NULL;
2033 if (all_queued_samples) {
2034 av_freep(&all_queued_samples);
2035 all_queued_samples = NULL;
2040AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2042 AVFrame *new_av_frame = NULL;
2046 if (new_av_frame == NULL)
2047 throw OutOfMemory(
"Could not allocate AVFrame", path);
2055 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
2058 new_av_frame->width = width;
2059 new_av_frame->height = height;
2060 new_av_frame->format = pix_fmt;
2064 return new_av_frame;
2068void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2070 int source_image_width = frame->GetWidth();
2071 int source_image_height = frame->GetHeight();
2074 if (source_image_height == 1 && source_image_width == 1)
2078 if (image_rescalers.size() == 0)
2079 InitScalers(source_image_width, source_image_height);
2082 SwsContext *scaler = image_rescalers[rescaler_position];
2083 rescaler_position++;
2084 if (rescaler_position == num_of_rescalers)
2085 rescaler_position = 0;
2088 int bytes_source = 0;
2089 int bytes_final = 0;
2090 AVFrame *frame_source = NULL;
2091 const uchar *pixels = NULL;
2094 pixels = frame->GetPixels();
2097 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
2099 AVFrame *frame_final;
2102 frame_final = allocate_avframe(AV_PIX_FMT_NV12,
info.
width,
info.
height, &bytes_final, NULL);
2106 frame_final = allocate_avframe(
2107 (AVPixelFormat)(video_st->codecpar->format),
2112 AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
2118 "FFmpegWriter::process_video_packet",
2119 "frame->number", frame->number,
2120 "bytes_source", bytes_source,
2121 "bytes_final", bytes_final);
2124 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
2125 source_image_height, frame_final->data, frame_final->linesize);
2128 add_avframe(frame, frame_final);
2135bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2136#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2139 "FFmpegWriter::write_video_packet",
2140 "frame->number", frame->number,
2141 "oc->oformat->flags", oc->oformat->flags);
2149 "FFmpegWriter::write_video_packet",
2150 "frame->number", frame->number,
2151 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2153 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2157 AVPacket* pkt = av_packet_alloc();
2160 av_init_packet(pkt);
2163 av_packet_from_data(
2164 pkt, frame_final->data[0],
2165 frame_final->linesize[0] * frame_final->height);
2167 pkt->flags |= AV_PKT_FLAG_KEY;
2168 pkt->stream_index = video_st->index;
2171 pkt->pts = video_timestamp;
2174 int error_code = av_interleaved_write_frame(oc, pkt);
2175 if (error_code < 0) {
2177 "FFmpegWriter::write_video_packet ERROR ["
2178 + av_err2string(error_code) +
"]",
2179 "error_code", error_code);
2190 AVPacket* pkt = av_packet_alloc();
2193 av_init_packet(pkt);
2197 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2200 frame_final->pts = video_timestamp;
2203 if (!(
hw_frame = av_frame_alloc())) {
2204 std::clog <<
"Error code: av_hwframe_alloc\n";
2206 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2207 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2210 std::clog <<
"Error hw_frames_ctx.\n";
2212 hw_frame->format = AV_PIX_FMT_NV12;
2213 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2214 std::clog <<
"Error while transferring frame data to surface.\n";
2216 av_frame_copy_props(
hw_frame, frame_final);
2220 int got_packet_ptr = 0;
2228 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2232 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2237 "FFmpegWriter::write_video_packet (Frame not sent)");
2238 if (ret == AVERROR(EAGAIN) ) {
2239 std::clog <<
"Frame EAGAIN\n";
2241 if (ret == AVERROR_EOF ) {
2242 std::clog <<
"Frame AVERROR_EOF\n";
2244 avcodec_send_frame(video_codec_ctx, NULL);
2248 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2250 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2251 avcodec_flush_buffers(video_codec_ctx);
2263 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2264 if (error_code != 0) {
2266 "FFmpegWriter::write_video_packet ERROR ["
2267 + av_err2string(error_code) +
"]",
2268 "error_code", error_code);
2270 if (got_packet_ptr == 0) {
2272 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2277 if (error_code == 0 && got_packet_ptr) {
2279 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2280 pkt->stream_index = video_st->index;
2283 int result = av_interleaved_write_frame(oc, pkt);
2286 "FFmpegWriter::write_video_packet ERROR ["
2287 + av_err2string(result) +
"]",
2306 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2315 av_dump_format(oc, 0, path.c_str(), 1);
2319void FFmpegWriter::InitScalers(
int source_width,
int source_height) {
2320 int scale_mode = SWS_FAST_BILINEAR;
2322 scale_mode = SWS_BICUBIC;
2326 for (
int x = 0; x < num_of_rescalers; x++) {
2330 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2335 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2337 scale_mode, NULL, NULL, NULL);
2341 image_rescalers.push_back(img_convert_ctx);
2347 original_sample_rate = sample_rate;
2348 original_channels = channels;
2354 for (
int x = 0; x < num_of_rescalers; x++)
2355 sws_freeContext(image_rescalers[x]);
2358 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.