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;
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);
567 case AV_CODEC_ID_HEVC :
569 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
570 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
571 av_opt_set_int(c->priv_data,
"preset", 7, 0);
572 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
581 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
585 "FFmpegWriter::SetOption (" + (std::string)name +
")",
590 }
else if (name ==
"muxing_preset") {
591 if (value ==
"mp4_faststart") {
593 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
594 }
else if (value ==
"mp4_fragmented") {
596 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
597 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
600 throw InvalidOptions(
"The option is not valid for this codec.", path);
611 if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
620 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
623 "FFmpegWriter::PrepareStreams [" + path +
"]",
628 initialize_streams();
631 prepare_streams =
true;
637 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
640 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
641 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
642 throw InvalidFile(
"Could not open or write file.", path);
649 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
650 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
654 AVDictionary *dict = NULL;
656 bool is_mp4 = strcmp(oc->oformat->name,
"mp4");
657 bool is_mov = strcmp(oc->oformat->name,
"mov");
659 if (is_mp4 || is_mov)
663 if (avformat_write_header(oc, &dict) != 0) {
665 "FFmpegWriter::WriteHeader (avformat_write_header)");
666 throw InvalidFile(
"Could not write header to file.", path);
670 if (dict) av_dict_free(&dict);
683 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
688 spooled_video_frames.push_back(frame);
691 spooled_audio_frames.push_back(frame);
694 "FFmpegWriter::WriteFrame",
695 "frame->number", frame->number,
696 "spooled_video_frames.size()", spooled_video_frames.size(),
697 "spooled_audio_frames.size()", spooled_audio_frames.size(),
698 "cache_size", cache_size,
699 "is_writing", is_writing);
702 if ((
int)spooled_video_frames.size() == cache_size || (
int)spooled_audio_frames.size() == cache_size) {
704 write_queued_frames();
712void FFmpegWriter::write_queued_frames() {
714 "FFmpegWriter::write_queued_frames",
715 "spooled_video_frames.size()", spooled_video_frames.size(),
716 "spooled_audio_frames.size()", spooled_audio_frames.size());
722 queued_video_frames = spooled_video_frames;
723 queued_audio_frames = spooled_audio_frames;
726 spooled_video_frames.clear();
727 spooled_audio_frames.clear();
730 bool has_error_encoding_video =
false;
733 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
734 write_audio_packets(
false);
737 while (!queued_video_frames.empty()) {
739 std::shared_ptr<Frame> frame = queued_video_frames.front();
742 processed_frames.push_back(frame);
746 process_video_packet(frame);
749 queued_video_frames.pop_front();
755 while (!processed_frames.empty()) {
757 std::shared_ptr<Frame> frame = processed_frames.front();
761 deallocate_frames.push_back(frame);
764 if (av_frames.count(frame)) {
766 AVFrame *frame_final = av_frames[frame];
769 bool success = write_video_packet(frame, frame_final);
771 has_error_encoding_video =
true;
776 processed_frames.pop_front();
780 while (!deallocate_frames.empty()) {
782 std::shared_ptr<Frame> frame = deallocate_frames.front();
785 if (av_frames.count(frame)) {
787 AVFrame *av_frame = av_frames[frame];
790 av_freep(&(av_frame->data[0]));
792 av_frames.erase(frame);
796 deallocate_frames.pop_front();
803 if (has_error_encoding_video)
810 "FFmpegWriter::WriteFrame (from Reader)",
815 for (int64_t number = start; number <= length; number++) {
817 std::shared_ptr<Frame> f = reader->
GetFrame(number);
827 write_queued_frames();
831 write_audio_packets(
true);
840 av_write_trailer(oc);
843 write_trailer =
true;
849void FFmpegWriter::flush_encoders() {
852#if (LIBAVFORMAT_VERSION_MAJOR < 58)
866 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
869 AVPacket* pkt = av_packet_alloc();
883 error_code = avcodec_send_frame(video_codec_ctx, NULL);
885 while (error_code >= 0) {
886 error_code = avcodec_receive_packet(video_codec_ctx, pkt);
887 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
890 avcodec_flush_buffers(video_codec_ctx);
893 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
894 pkt->stream_index = video_st->index;
895 error_code = av_interleaved_write_frame(oc, pkt);
900 error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
904 if (error_code < 0) {
906 "FFmpegWriter::flush_encoders ERROR ["
907 + av_err2string(error_code) +
"]",
908 "error_code", error_code);
915 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
916 pkt->stream_index = video_st->index;
919 error_code = av_interleaved_write_frame(oc, pkt);
920 if (error_code < 0) {
922 "FFmpegWriter::flush_encoders ERROR ["
923 + av_err2string(error_code) +
"]",
924 "error_code", error_code);
933 AVPacket* pkt = av_packet_alloc();
940 pkt->pts = pkt->dts = audio_timestamp;
946 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
948 error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
950 if (error_code < 0) {
952 "FFmpegWriter::flush_encoders ERROR ["
953 + av_err2string(error_code) +
"]",
954 "error_code", error_code);
962 pkt->pts = pkt->dts = audio_timestamp;
965 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
968 pkt->stream_index = audio_st->index;
969 pkt->flags |= AV_PKT_FLAG_KEY;
972 error_code = av_interleaved_write_frame(oc, pkt);
973 if (error_code < 0) {
975 "FFmpegWriter::flush_encoders ERROR ["
976 + av_err2string(error_code) +
"]",
977 "error_code", error_code);
981 audio_timestamp += pkt->duration;
991void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
996 av_buffer_unref(&hw_device_ctx);
997 hw_device_ctx = NULL;
1003 if (video_codec_ctx !=
nullptr) {
1005 av_free(video_codec_ctx);
1010void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
1014 delete[] audio_outbuf;
1015 delete[] audio_encoder_buffer;
1017 audio_outbuf = NULL;
1018 audio_encoder_buffer = NULL;
1034 if (audio_codec_ctx !=
nullptr) {
1036 av_free(audio_codec_ctx);
1048 close_video(oc, video_st);
1050 close_audio(oc, audio_st);
1053 if (image_rescalers.size() > 0)
1056 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1062 video_timestamp = 0;
1063 audio_timestamp = 0;
1066 avformat_free_context(oc);
1071 prepare_streams =
false;
1072 write_header =
false;
1073 write_trailer =
false;
1079void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1081 if (!av_frames.count(frame)) {
1083 av_frames[frame] = av_frame;
1091AVStream *FFmpegWriter::add_audio_stream() {
1093 const AVCodec *codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1095 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1098 if (audio_codec_ctx !=
nullptr) {
1103 AVStream* st = avformat_new_stream(oc, codec);
1105 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1109#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1110 st->codecpar->codec_id = codec->id;
1112 AVCodecContext* c = audio_codec_ctx;
1114 c->codec_id = codec->id;
1115 c->codec_type = AVMEDIA_TYPE_AUDIO;
1122 if (codec->supported_samplerates) {
1124 for (i = 0; codec->supported_samplerates[i] != 0; i++)
1130 if (codec->supported_samplerates[i] == 0)
1131 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1139 if (codec->channel_layouts) {
1141 for (i = 0; codec->channel_layouts[i] != 0; i++)
1142 if (channel_layout == codec->channel_layouts[i]) {
1144 c->channel_layout = channel_layout;
1147 if (codec->channel_layouts[i] == 0)
1148 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1151 c->channel_layout = channel_layout;
1154 if (codec->sample_fmts) {
1155 for (
int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1157 c->sample_fmt = codec->sample_fmts[i];
1161 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1163 c->sample_fmt = AV_SAMPLE_FMT_S16;
1167 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1168#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1170 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1172 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1178 "FFmpegWriter::add_audio_stream",
1179 "c->codec_id", c->codec_id,
1180 "c->bit_rate", c->bit_rate,
1181 "c->channels", c->channels,
1182 "c->sample_fmt", c->sample_fmt,
1183 "c->channel_layout", c->channel_layout,
1184 "c->sample_rate", c->sample_rate);
1190AVStream *FFmpegWriter::add_video_stream() {
1192 const AVCodec *codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1194 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1197 if (video_codec_ctx !=
nullptr) {
1202 AVStream* st = avformat_new_stream(oc, codec);
1204 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1208#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1209 st->codecpar->codec_id = codec->id;
1212 AVCodecContext* c = video_codec_ctx;
1214 c->codec_id = codec->id;
1215 c->codec_type = AVMEDIA_TYPE_VIDEO;
1223#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1224 && c->codec_id != AV_CODEC_ID_AV1
1229 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1238 switch (c->codec_id) {
1239#if (LIBAVCODEC_VERSION_MAJOR >= 58)
1241 case AV_CODEC_ID_AV1 :
1245 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1246 int calculated_quality = 35;
1249 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1252 int calculated_quality = 50;
1255 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1259 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1260 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1261 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1263 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1264 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1265 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1266 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1268 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1271 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1272 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1273 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1274 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1278 case AV_CODEC_ID_VP9 :
1279 case AV_CODEC_ID_HEVC :
1280 case AV_CODEC_ID_VP8 :
1281 case AV_CODEC_ID_H264 :
1317#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1318 c->framerate = av_inv_q(c->time_base);
1320 st->avg_frame_rate = av_inv_q(c->time_base);
1325 c->max_b_frames = 10;
1326 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1328 c->max_b_frames = 2;
1329 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1335 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1336#if (LIBAVCODEC_VERSION_MAJOR >= 57)
1338 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1340 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1344 const PixelFormat *supported_pixel_formats = codec->pix_fmts;
1345 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1348 c->pix_fmt = *supported_pixel_formats;
1349 ++supported_pixel_formats;
1354 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1358#if (LIBAVFORMAT_VERSION_MAJOR < 58)
1360 if (strcmp(oc->oformat->name,
"gif") != 0)
1363 oc->oformat->flags |= AVFMT_RAWPICTURE;
1373 "FFmpegWriter::add_video_stream ("
1374 + (std::string)oc->oformat->name +
" : "
1375 + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
1376 "c->codec_id", c->codec_id,
1377 "c->bit_rate", c->bit_rate,
1378 "c->pix_fmt", c->pix_fmt,
1379 "oc->oformat->flags", oc->oformat->flags);
1384void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1385 const AVCodec *codec;
1392 codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1394 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1399 AVDictionary *opts = NULL;
1400 av_dict_set(&opts,
"strict",
"experimental", 0);
1403 if (avcodec_open2(audio_codec_ctx, codec, &opts) < 0)
1404 throw InvalidCodec(
"Could not open audio codec", path);
1408 av_dict_free(&opts);
1412 if (audio_codec_ctx->frame_size <= 1) {
1418 case AV_CODEC_ID_PCM_S16LE:
1419 case AV_CODEC_ID_PCM_S16BE:
1420 case AV_CODEC_ID_PCM_U16LE:
1421 case AV_CODEC_ID_PCM_U16BE:
1422 audio_input_frame_size >>= 1;
1429 audio_input_frame_size = audio_codec_ctx->frame_size;
1433 initial_audio_input_frame_size = audio_input_frame_size;
1440 audio_outbuf =
new uint8_t[audio_outbuf_size];
1444 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1447 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1448 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1452 "FFmpegWriter::open_audio",
1453 "audio_codec_ctx->thread_count", audio_codec_ctx->thread_count,
1454 "audio_input_frame_size", audio_input_frame_size,
1459void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1460 const AVCodec *codec;
1470 char *adapter_ptr = NULL;
1474 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1475 if (adapter_num < 3 && adapter_num >=0) {
1476#if defined(__unix__)
1477 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1479 adapter_ptr = adapter;
1480#elif defined(_WIN32) || defined(__APPLE__)
1490#if defined(__unix__)
1491 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1492#elif defined(_WIN32) || defined(__APPLE__)
1493 if( adapter_ptr != NULL ) {
1495 if( adapter_ptr != NULL ) {
1498 "Encode Device present using device",
1499 "adapter", adapter_num);
1504 "Encode Device not present, using default");
1506 if (av_hwdevice_ctx_create(&hw_device_ctx,
1510 "FFmpegWriter::open_video ERROR creating hwdevice, Codec name:",
1518 codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1525 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)
1526 video_codec_ctx->max_b_frames = 0;
1529 AVDictionary *opts = NULL;
1530 av_dict_set(&opts,
"strict",
"experimental", 0);
1544 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1546 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1550 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1554 switch (video_codec_ctx->codec_id) {
1555 case AV_CODEC_ID_H264:
1556 video_codec_ctx->max_b_frames = 0;
1557 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1558 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1559 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1560 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1562 case AV_CODEC_ID_HEVC:
1565 case AV_CODEC_ID_VP9:
1570 "No codec-specific options defined for this codec. HW encoding may fail",
1571 "codec_id", video_codec_ctx->codec_id);
1580 "FFmpegWriter::open_video (set_hwframe_ctx) ERROR faled to set hwframe context",
1583 av_err2string(err), -1);
1589 if (avcodec_open2(video_codec_ctx, codec, &opts) < 0)
1590 throw InvalidCodec(
"Could not open video codec", path);
1594 av_dict_free(&opts);
1597 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1598 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1602 "FFmpegWriter::open_video",
1603 "video_codec_ctx->thread_count", video_codec_ctx->thread_count);
1608void FFmpegWriter::write_audio_packets(
bool is_final) {
1610 int total_frame_samples = 0;
1611 int frame_position = 0;
1612 int channels_in_frame = 0;
1613 int sample_rate_in_frame = 0;
1614 int samples_in_frame = 0;
1619 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1620 int16_t *all_resampled_samples = NULL;
1621 int16_t *final_samples_planar = NULL;
1622 int16_t *final_samples = NULL;
1625 while (!queued_audio_frames.empty()) {
1627 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1630 sample_rate_in_frame = frame->SampleRate();
1631 samples_in_frame = frame->GetAudioSamplesCount();
1632 channels_in_frame = frame->GetAudioChannelsCount();
1633 channel_layout_in_frame = frame->ChannelsLayout();
1636 float *frame_samples_float = NULL;
1638 frame_samples_float = frame->GetInterleavedAudioSamples(&samples_in_frame);
1641 total_frame_samples = samples_in_frame * channels_in_frame;
1644 const int16_t max16 = 32767;
1645 const int16_t min16 = -32768;
1646 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1647 float valF = frame_samples_float[s] * (1 << 15);
1651 }
else if (valF < min16) {
1654 conv = int(valF + 32768.5) - 32768;
1658 all_queued_samples[frame_position] = conv;
1662 delete[] frame_samples_float;
1665 queued_audio_frames.pop_front();
1671 total_frame_samples = frame_position;
1672 int remaining_frame_samples = total_frame_samples;
1673 int samples_position = 0;
1677 "FFmpegWriter::write_audio_packets",
1678 "is_final", is_final,
1679 "total_frame_samples", total_frame_samples,
1680 "channel_layout_in_frame", channel_layout_in_frame,
1681 "channels_in_frame", channels_in_frame,
1682 "samples_in_frame", samples_in_frame,
1686 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1688 AVFrame *audio_frame = NULL;
1693 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1696 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);
1697 if (error_code < 0) {
1699 "FFmpegWriter::write_audio_packets ERROR ["
1700 + av_err2string(error_code) +
"]",
1701 "error_code", error_code);
1705 switch (audio_codec_ctx->sample_fmt) {
1706 case AV_SAMPLE_FMT_FLTP: {
1707 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1710 case AV_SAMPLE_FMT_S32P: {
1711 output_sample_fmt = AV_SAMPLE_FMT_S32;
1714 case AV_SAMPLE_FMT_S16P: {
1715 output_sample_fmt = AV_SAMPLE_FMT_S16;
1718 case AV_SAMPLE_FMT_U8P: {
1719 output_sample_fmt = AV_SAMPLE_FMT_U8;
1729 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1730 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1735 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1736 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1739 "FFmpegWriter::write_audio_packets (1st resampling)",
1740 "in_sample_fmt", AV_SAMPLE_FMT_S16,
1741 "out_sample_fmt", output_sample_fmt,
1742 "in_sample_rate", sample_rate_in_frame,
1744 "in_channels", channels_in_frame,
1750 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1752 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1753 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1754 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1756 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1763 audio_converted->data,
1764 audio_converted->linesize[0],
1765 audio_converted->nb_samples,
1767 audio_frame->linesize[0],
1768 audio_frame->nb_samples
1772 remaining_frame_samples = total_frame_samples;
1775 all_resampled_samples = (int16_t *) av_malloc(
1777 * (av_get_bytes_per_sample(output_sample_fmt) /
1778 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1782 memcpy(all_resampled_samples, audio_converted->data[0],
1783 static_cast<size_t>(nb_samples)
1785 * av_get_bytes_per_sample(output_sample_fmt));
1788 av_freep(&(audio_frame->data[0]));
1790 av_freep(&audio_converted->data[0]);
1792 all_queued_samples = NULL;
1795 "FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
1796 "nb_samples", nb_samples,
1797 "remaining_frame_samples", remaining_frame_samples);
1801 while (remaining_frame_samples > 0 || is_final) {
1803 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1807 if (remaining_frame_samples >= remaining_packet_samples) {
1808 diff = remaining_packet_samples;
1810 diff = remaining_frame_samples;
1817 samples + (audio_input_position
1818 * (av_get_bytes_per_sample(output_sample_fmt) /
1819 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1821 all_resampled_samples + samples_position,
1822 static_cast<size_t>(diff)
1823 * av_get_bytes_per_sample(output_sample_fmt)
1827 audio_input_position += diff;
1828 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1829 remaining_frame_samples -= diff;
1832 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1839 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1841 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1842 "in_sample_fmt", output_sample_fmt,
1843 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1855 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1856 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1859 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1860 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1867 audio_frame->nb_samples = audio_input_position /
info.
channels;
1870 final_samples_planar = (int16_t *) av_malloc(
1871 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1872 * (av_get_bytes_per_sample(output_sample_fmt) /
1873 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1877 memcpy(final_samples_planar, samples,
1878 static_cast<size_t>(audio_frame->nb_samples)
1880 * av_get_bytes_per_sample(output_sample_fmt));
1883 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1884 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1887 frame_final->nb_samples = audio_input_frame_size;
1889 frame_final->format = audio_codec_ctx->sample_fmt;
1891 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1892 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1898 frame_final->linesize[0],
1899 frame_final->nb_samples,
1901 audio_frame->linesize[0],
1902 audio_frame->nb_samples
1906 const auto copy_length =
static_cast<size_t>(nb_samples)
1907 * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt)
1911 memcpy(samples, frame_final->data[0], copy_length);
1914 av_freep(&(audio_frame->data[0]));
1916 all_queued_samples = NULL;
1919 "FFmpegWriter::write_audio_packets (Successfully completed 2nd resampling for Planar formats)",
1920 "nb_samples", nb_samples);
1924 const auto buf_size =
static_cast<size_t>(audio_input_position)
1925 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1926 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)
1928 final_samples =
reinterpret_cast<int16_t*
>(
1929 av_malloc(
sizeof(int16_t) * buf_size));
1932 memcpy(final_samples, samples,
1933 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1936 frame_final->nb_samples = audio_input_frame_size;
1939 avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1940 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1941 audio_encoder_buffer_size, 0);
1945 frame_final->pts = audio_timestamp;
1949 AVPacket* pkt = av_packet_alloc();
1952 av_init_packet(pkt);
1954 pkt->data = audio_encoder_buffer;
1955 pkt->size = audio_encoder_buffer_size;
1958 pkt->pts = pkt->dts = audio_timestamp;
1961 int got_packet_ptr = 0;
1967 int frame_finished = 0;
1968 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1969 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1970 avcodec_send_frame(audio_codec_ctx, NULL);
1975 ret = avcodec_receive_packet(audio_codec_ctx, pkt);
1978 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1979 avcodec_flush_buffers(audio_codec_ctx);
1983 ret = frame_finished;
1986 if (!pkt->data && !frame_finished)
1990 got_packet_ptr = ret;
1993 int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
1996 if (error_code == 0 && got_packet_ptr) {
2000 pkt->pts = pkt->dts = audio_timestamp;
2003 av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
2006 pkt->stream_index = audio_st->index;
2007 pkt->flags |= AV_PKT_FLAG_KEY;
2010 error_code = av_interleaved_write_frame(oc, pkt);
2013 if (error_code < 0) {
2015 "FFmpegWriter::write_audio_packets ERROR ["
2016 + av_err2string(error_code) +
"]",
2017 "error_code", error_code);
2021 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
2024 av_freep(&(frame_final->data[0]));
2031 audio_input_position = 0;
2036 if (all_resampled_samples) {
2037 av_freep(&all_resampled_samples);
2038 all_resampled_samples = NULL;
2040 if (all_queued_samples) {
2041 av_freep(&all_queued_samples);
2042 all_queued_samples = NULL;
2047AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
2049 AVFrame *new_av_frame = NULL;
2053 if (new_av_frame == NULL)
2054 throw OutOfMemory(
"Could not allocate AVFrame", path);
2062 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
2065 new_av_frame->width = width;
2066 new_av_frame->height = height;
2067 new_av_frame->format = pix_fmt;
2071 return new_av_frame;
2075void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
2077 int source_image_width = frame->GetWidth();
2078 int source_image_height = frame->GetHeight();
2081 if (source_image_height == 1 && source_image_width == 1)
2085 if (image_rescalers.size() == 0)
2086 InitScalers(source_image_width, source_image_height);
2089 SwsContext *scaler = image_rescalers[rescaler_position];
2090 rescaler_position++;
2091 if (rescaler_position == num_of_rescalers)
2092 rescaler_position = 0;
2095 int bytes_source = 0;
2096 int bytes_final = 0;
2097 AVFrame *frame_source = NULL;
2098 const uchar *pixels = NULL;
2101 pixels = frame->GetPixels();
2104 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
2106 AVFrame *frame_final;
2109 frame_final = allocate_avframe(AV_PIX_FMT_NV12,
info.
width,
info.
height, &bytes_final, NULL);
2113 frame_final = allocate_avframe(
2114 (AVPixelFormat)(video_st->codecpar->format),
2119 AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
2125 "FFmpegWriter::process_video_packet",
2126 "frame->number", frame->number,
2127 "bytes_source", bytes_source,
2128 "bytes_final", bytes_final);
2131 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
2132 source_image_height, frame_final->data, frame_final->linesize);
2135 add_avframe(frame, frame_final);
2142bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2143#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2146 "FFmpegWriter::write_video_packet",
2147 "frame->number", frame->number,
2148 "oc->oformat->flags", oc->oformat->flags);
2156 "FFmpegWriter::write_video_packet",
2157 "frame->number", frame->number,
2158 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2160 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2164 AVPacket* pkt = av_packet_alloc();
2167 av_init_packet(pkt);
2170 av_packet_from_data(
2171 pkt, frame_final->data[0],
2172 frame_final->linesize[0] * frame_final->height);
2174 pkt->flags |= AV_PKT_FLAG_KEY;
2175 pkt->stream_index = video_st->index;
2178 pkt->pts = video_timestamp;
2181 int error_code = av_interleaved_write_frame(oc, pkt);
2182 if (error_code < 0) {
2184 "FFmpegWriter::write_video_packet ERROR ["
2185 + av_err2string(error_code) +
"]",
2186 "error_code", error_code);
2197 AVPacket* pkt = av_packet_alloc();
2200 av_init_packet(pkt);
2204 pkt->pts = pkt->dts = AV_NOPTS_VALUE;
2207 frame_final->pts = video_timestamp;
2210 if (!(
hw_frame = av_frame_alloc())) {
2211 std::clog <<
"Error code: av_hwframe_alloc\n";
2213 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2214 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2217 std::clog <<
"Error hw_frames_ctx.\n";
2219 hw_frame->format = AV_PIX_FMT_NV12;
2220 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2221 std::clog <<
"Error while transferring frame data to surface.\n";
2223 av_frame_copy_props(
hw_frame, frame_final);
2227 int got_packet_ptr = 0;
2235 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2239 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2244 "FFmpegWriter::write_video_packet (Frame not sent)");
2245 if (ret == AVERROR(EAGAIN) ) {
2246 std::clog <<
"Frame EAGAIN\n";
2248 if (ret == AVERROR_EOF ) {
2249 std::clog <<
"Frame AVERROR_EOF\n";
2251 avcodec_send_frame(video_codec_ctx, NULL);
2255 ret = avcodec_receive_packet(video_codec_ctx, pkt);
2257 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2258 avcodec_flush_buffers(video_codec_ctx);
2270 error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
2271 if (error_code != 0) {
2273 "FFmpegWriter::write_video_packet ERROR ["
2274 + av_err2string(error_code) +
"]",
2275 "error_code", error_code);
2277 if (got_packet_ptr == 0) {
2279 "FFmpegWriter::write_video_packet (Frame gotpacket error)");
2284 if (error_code == 0 && got_packet_ptr) {
2286 av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
2287 pkt->stream_index = video_st->index;
2290 int result = av_interleaved_write_frame(oc, pkt);
2293 "FFmpegWriter::write_video_packet ERROR ["
2294 + av_err2string(result) +
"]",
2313 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2322 av_dump_format(oc, 0, path.c_str(), 1);
2326void FFmpegWriter::InitScalers(
int source_width,
int source_height) {
2327 int scale_mode = SWS_FAST_BILINEAR;
2329 scale_mode = SWS_BICUBIC;
2333 for (
int x = 0; x < num_of_rescalers; x++) {
2337 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2342 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2344 scale_mode, NULL, NULL, NULL);
2348 image_rescalers.push_back(img_convert_ctx);
2354 original_sample_rate = sample_rate;
2355 original_channels = channels;
2361 for (
int x = 0; x < num_of_rescalers; x++)
2362 sws_freeContext(image_rescalers[x]);
2365 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
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.