49 static AVBufferRef *hw_device_ctx = NULL;
52 static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int64_t width, int64_t height)
54 AVBufferRef *hw_frames_ref;
55 AVHWFramesContext *frames_ctx = NULL;
58 if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) {
59 std::clog <<
"Failed to create HW frame context.\n";
62 frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
64 frames_ctx->sw_format = AV_PIX_FMT_NV12;
65 frames_ctx->width = width;
66 frames_ctx->height = height;
67 frames_ctx->initial_pool_size = 20;
68 if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) {
69 std::clog <<
"Failed to initialize HW frame context. " <<
70 "Error code: " << av_err2string(err) <<
"\n";
71 av_buffer_unref(&hw_frames_ref);
74 ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
75 if (!ctx->hw_frames_ctx)
76 err = AVERROR(ENOMEM);
78 av_buffer_unref(&hw_frames_ref);
84 path(
path), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL),
85 audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),
86 initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32),
87 rescaler_position(0), video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0),
88 original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false),
89 write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) {
109 if (!prepare_streams)
114 open_video(oc, video_st);
116 open_audio(oc, audio_st);
125 void FFmpegWriter::auto_detect_format() {
131 "Could not allocate memory for AVFormatContext.", path);
135 oc->oformat = av_guess_format(NULL, path.c_str(), NULL);
136 if (oc->oformat ==
nullptr) {
138 "Could not deduce output format from file extension.", path);
142 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
143 info.
vcodec = avcodec_find_encoder(oc->oformat->video_codec)->name;
146 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
147 info.
acodec = avcodec_find_encoder(oc->oformat->audio_codec)->name;
151 void FFmpegWriter::initialize_streams() {
153 "FFmpegWriter::initialize_streams",
154 "oc->oformat->video_codec", oc->oformat->video_codec,
155 "oc->oformat->audio_codec", oc->oformat->audio_codec,
156 "AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
161 if (oc->oformat->video_codec != AV_CODEC_ID_NONE &&
info.
has_video)
163 video_st = add_video_stream();
165 if (oc->oformat->audio_codec != AV_CODEC_ID_NONE &&
info.
has_audio)
167 audio_st = add_audio_stream();
173 if (
codec.length() > 0) {
174 const AVCodec *new_codec;
177 #if defined(__linux__)
178 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
179 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
184 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
185 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
191 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
195 #elif defined(_WIN32)
196 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
197 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
202 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
203 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
209 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
213 #elif defined(__APPLE__)
214 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
215 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
221 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
226 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
229 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
231 if (new_codec == NULL)
232 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
251 if (pixel_ratio.
num > 0) {
255 if (bit_rate >= 1000)
257 if ((bit_rate >= 0) && (bit_rate < 256))
273 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::SetVideoOptions (" +
codec +
")",
"width", width,
"height", height,
"size.num", size.
num,
"size.den", size.
den,
"fps.num", fps.
num,
"fps.den", fps.
den);
283 true,
codec, fps, width, height,
292 if (
codec.length() > 0) {
293 const AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
294 if (new_codec == NULL)
295 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
301 if (sample_rate > 7999)
310 if (original_sample_rate == 0)
312 if (original_channels == 0)
316 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
317 "sample_rate", sample_rate,
318 "channels", channels,
319 "bit_rate", bit_rate);
330 true,
codec, sample_rate, 2,
339 AVCodecContext *c = NULL;
341 std::stringstream convert(value);
360 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
363 const AVOption *option = NULL;
371 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
372 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
373 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp")) {
377 convert >> c->gop_size;
379 else if (name ==
"qmin")
383 else if (name ==
"qmax")
387 else if (name ==
"max_b_frames")
389 convert >> c->max_b_frames;
391 else if (name ==
"mb_decision")
393 convert >> c->mb_decision;
395 else if (name ==
"level")
399 else if (name ==
"profile")
401 convert >> c->profile;
403 else if (name ==
"slices")
405 convert >> c->slices;
407 else if (name ==
"rc_min_rate")
409 convert >> c->rc_min_rate;
411 else if (name ==
"rc_max_rate")
413 convert >> c->rc_max_rate;
415 else if (name ==
"rc_buffer_size")
417 convert >> c->rc_buffer_size;
419 else if (name ==
"cqp") {
425 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
429 switch (c->codec_id) {
430 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
432 case AV_CODEC_ID_AV1 :
434 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
437 case AV_CODEC_ID_VP8 :
438 c->bit_rate = 10000000;
439 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
441 case AV_CODEC_ID_VP9 :
443 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
444 if (std::stoi(value) == 0) {
445 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
446 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
449 case AV_CODEC_ID_H264 :
450 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
451 if (std::stoi(value) == 0) {
452 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
456 case AV_CODEC_ID_HEVC :
457 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
458 if (std::stoi(value) == 0) {
459 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
460 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
465 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
469 }
else if (name ==
"crf") {
475 double mbs = 15000000.0;
484 c->bit_rate = (int)(mbs);
488 switch (c->codec_id) {
489 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
491 case AV_CODEC_ID_AV1 :
494 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
497 case AV_CODEC_ID_VP8 :
498 c->bit_rate = 10000000;
499 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
501 case AV_CODEC_ID_VP9 :
503 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
504 if (std::stoi(value) == 0) {
505 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
506 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
509 case AV_CODEC_ID_H264 :
510 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
511 if (std::stoi(value) == 0) {
512 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
516 case AV_CODEC_ID_HEVC :
517 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
518 av_opt_set_int(c->priv_data,
"preset", 7, 0);
519 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
520 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
523 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
525 if (std::stoi(value) == 0) {
526 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
527 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
533 double mbs = 15000000.0;
541 c->bit_rate = (int) (mbs);
544 }
else if (name ==
"qp") {
548 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
550 switch (c->codec_id) {
551 case AV_CODEC_ID_AV1 :
553 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
554 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
556 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
559 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
561 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
565 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
568 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
570 case AV_CODEC_ID_HEVC :
572 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
573 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
574 av_opt_set_int(c->priv_data,
"preset", 7, 0);
575 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
582 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
589 }
else if (name ==
"muxing_preset") {
590 if (value ==
"mp4_faststart") {
592 av_dict_set(&
mux_dict,
"movflags",
"faststart", 0);
593 }
else if (value ==
"mp4_fragmented") {
595 av_dict_set(&
mux_dict,
"movflags",
"frag_keyframe", 0);
596 av_dict_set(&
mux_dict,
"min_frag_duration",
"8000000", 0);
599 throw InvalidOptions(
"The option is not valid for this codec.", path);
610 if (avcodec_find_encoder_by_name(codec_name.c_str()) == NULL)
619 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
624 initialize_streams();
627 prepare_streams =
true;
633 throw InvalidOptions(
"No video or audio options have been set. You must set has_video or has_audio (or both).", path);
636 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
637 if (avio_open(&oc->pb, path.c_str(), AVIO_FLAG_WRITE) < 0)
638 throw InvalidFile(
"Could not open or write file.", path);
645 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
646 av_dict_set(&oc->metadata, iter->first.c_str(), iter->second.c_str(), 0);
650 AVDictionary *dict = NULL;
652 bool is_mp4 = strcmp(oc->oformat->name,
"mp4");
653 bool is_mov = strcmp(oc->oformat->name,
"mov");
655 if (is_mp4 || is_mov)
659 if (avformat_write_header(oc, &dict) != 0) {
661 throw InvalidFile(
"Could not write header to file.", path);
665 if (dict) av_dict_free(&dict);
678 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
683 spooled_video_frames.push_back(frame);
686 spooled_audio_frames.push_back(frame);
688 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::WriteFrame",
"frame->number", frame->number,
"spooled_video_frames.size()", spooled_video_frames.size(),
"spooled_audio_frames.size()", spooled_audio_frames.size(),
"cache_size", cache_size,
"is_writing", is_writing);
691 if ((
int)spooled_video_frames.size() == cache_size || (
int)spooled_audio_frames.size() == cache_size) {
693 write_queued_frames();
701 void FFmpegWriter::write_queued_frames() {
702 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_queued_frames",
"spooled_video_frames.size()", spooled_video_frames.size(),
"spooled_audio_frames.size()", spooled_audio_frames.size());
708 queued_video_frames = spooled_video_frames;
709 queued_audio_frames = spooled_audio_frames;
712 spooled_video_frames.clear();
713 spooled_audio_frames.clear();
716 bool has_error_encoding_video =
false;
719 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
720 write_audio_packets(
false);
723 while (!queued_video_frames.empty()) {
725 std::shared_ptr<Frame> frame = queued_video_frames.front();
728 processed_frames.push_back(frame);
732 process_video_packet(frame);
735 queued_video_frames.pop_front();
741 while (!processed_frames.empty()) {
743 std::shared_ptr<Frame> frame = processed_frames.front();
747 deallocate_frames.push_back(frame);
750 if (av_frames.count(frame)) {
752 AVFrame *frame_final = av_frames[frame];
755 bool success = write_video_packet(frame, frame_final);
757 has_error_encoding_video =
true;
762 processed_frames.pop_front();
766 while (!deallocate_frames.empty()) {
768 std::shared_ptr<Frame> frame = deallocate_frames.front();
771 if (av_frames.count(frame)) {
773 AVFrame *av_frame = av_frames[frame];
776 av_freep(&(av_frame->data[0]));
778 av_frames.erase(frame);
782 deallocate_frames.pop_front();
789 if (has_error_encoding_video)
798 for (int64_t number = start; number <= length; number++) {
800 std::shared_ptr<Frame> f = reader->
GetFrame(number);
810 write_queued_frames();
814 write_audio_packets(
true);
823 av_write_trailer(oc);
826 write_trailer =
true;
832 void FFmpegWriter::flush_encoders() {
835 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
849 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
852 av_init_packet(&pkt);
862 error_code = avcodec_send_frame(video_codec_ctx, NULL);
864 while (error_code >= 0) {
865 error_code = avcodec_receive_packet(video_codec_ctx, &pkt);
866 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
869 avcodec_flush_buffers(video_codec_ctx);
872 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
873 pkt.stream_index = video_st->index;
874 error_code = av_interleaved_write_frame(oc, &pkt);
879 error_code = avcodec_encode_video2(video_codec_ctx, &pkt, NULL, &got_packet);
883 if (error_code < 0) {
891 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
892 pkt.stream_index = video_st->index;
895 error_code = av_interleaved_write_frame(oc, &pkt);
896 if (error_code < 0) {
905 av_init_packet(&pkt);
908 pkt.pts = pkt.dts = audio_timestamp;
914 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
916 error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, NULL, &got_packet);
918 if (error_code < 0) {
920 "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) +
"]",
921 "error_code", error_code);
929 pkt.pts = pkt.dts = audio_timestamp;
932 av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
935 pkt.stream_index = audio_st->index;
936 pkt.flags |= AV_PKT_FLAG_KEY;
939 error_code = av_interleaved_write_frame(oc, &pkt);
940 if (error_code < 0) {
942 "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) +
"]",
943 "error_code", error_code);
947 audio_timestamp += pkt.duration;
957 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
962 av_buffer_unref(&hw_device_ctx);
963 hw_device_ctx = NULL;
970 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
974 delete[] audio_outbuf;
975 delete[] audio_encoder_buffer;
978 audio_encoder_buffer = NULL;
1002 close_video(oc, video_st);
1004 close_audio(oc, audio_st);
1007 if (image_rescalers.size() > 0)
1010 if (!(oc->oformat->flags & AVFMT_NOFILE)) {
1016 video_timestamp = 0;
1017 audio_timestamp = 0;
1020 avformat_free_context(oc);
1025 prepare_streams =
false;
1026 write_header =
false;
1027 write_trailer =
false;
1033 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1035 if (!av_frames.count(frame)) {
1037 av_frames[frame] = av_frame;
1045 AVStream *FFmpegWriter::add_audio_stream() {
1047 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
acodec.c_str());
1049 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1052 if (audio_codec_ctx !=
nullptr) {
1057 AVStream* st = avformat_new_stream(oc,
codec);
1059 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1063 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1064 st->codecpar->codec_id =
codec->id;
1066 AVCodecContext* c = audio_codec_ctx;
1068 c->codec_id =
codec->id;
1069 c->codec_type = AVMEDIA_TYPE_AUDIO;
1076 if (
codec->supported_samplerates) {
1078 for (i = 0;
codec->supported_samplerates[i] != 0; i++)
1084 if (
codec->supported_samplerates[i] == 0)
1085 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1093 if (
codec->channel_layouts) {
1095 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1096 if (channel_layout ==
codec->channel_layouts[i]) {
1098 c->channel_layout = channel_layout;
1101 if (
codec->channel_layouts[i] == 0)
1102 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1105 c->channel_layout = channel_layout;
1108 if (
codec->sample_fmts) {
1109 for (
int i = 0;
codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1111 c->sample_fmt =
codec->sample_fmts[i];
1115 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1117 c->sample_fmt = AV_SAMPLE_FMT_S16;
1121 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1122 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1124 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1126 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1130 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_audio_stream",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->channels", c->channels,
"c->sample_fmt", c->sample_fmt,
"c->channel_layout", c->channel_layout,
"c->sample_rate", c->sample_rate);
1136 AVStream *FFmpegWriter::add_video_stream() {
1138 const AVCodec *
codec = avcodec_find_encoder_by_name(
info.
vcodec.c_str());
1140 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1143 if (video_codec_ctx !=
nullptr) {
1148 AVStream* st = avformat_new_stream(oc,
codec);
1150 throw OutOfMemory(
"Could not allocate memory for the video stream.", path);
1154 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1155 st->codecpar->codec_id =
codec->id;
1158 AVCodecContext* c = video_codec_ctx;
1160 c->codec_id =
codec->id;
1161 c->codec_type = AVMEDIA_TYPE_VIDEO;
1169 #
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1170 && c->codec_id != AV_CODEC_ID_AV1
1175 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1184 switch (c->codec_id) {
1185 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
1187 case AV_CODEC_ID_AV1 :
1191 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1192 int calculated_quality = 35;
1195 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1198 int calculated_quality = 50;
1201 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1205 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1206 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1207 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1209 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1210 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1211 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1212 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1214 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1217 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1218 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1219 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1220 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1224 case AV_CODEC_ID_VP9 :
1225 case AV_CODEC_ID_HEVC :
1226 case AV_CODEC_ID_VP8 :
1227 case AV_CODEC_ID_H264 :
1263 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1264 c->framerate = av_inv_q(c->time_base);
1266 st->avg_frame_rate = av_inv_q(c->time_base);
1271 c->max_b_frames = 10;
1272 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1274 c->max_b_frames = 2;
1275 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1281 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1282 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1284 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1286 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1291 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1294 c->pix_fmt = *supported_pixel_formats;
1295 ++supported_pixel_formats;
1300 if (oc->oformat->video_codec == AV_CODEC_ID_RAWVIDEO) {
1304 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1306 if (strcmp(oc->oformat->name,
"gif") != 0)
1309 oc->oformat->flags |= AVFMT_RAWPICTURE;
1318 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1320 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_video_stream (" + (std::string)fmt->name +
" : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->pix_fmt", c->pix_fmt,
"oc->oformat->flags", oc->oformat->flags,
"AVFMT_RAWPICTURE", AVFMT_RAWPICTURE);
1322 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::add_video_stream (" + (std::string)oc->oformat->name +
" : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) +
")",
"c->codec_id", c->codec_id,
"c->bit_rate", c->bit_rate,
"c->pix_fmt", c->pix_fmt,
"oc->oformat->flags", oc->oformat->flags);
1329 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1330 const AVCodec *
codec;
1339 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1344 AVDictionary *
opts = NULL;
1345 av_dict_set(&
opts,
"strict",
"experimental", 0);
1348 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1349 throw InvalidCodec(
"Could not open audio codec", path);
1353 av_dict_free(&
opts);
1357 if (audio_codec_ctx->frame_size <= 1) {
1363 case AV_CODEC_ID_PCM_S16LE:
1364 case AV_CODEC_ID_PCM_S16BE:
1365 case AV_CODEC_ID_PCM_U16LE:
1366 case AV_CODEC_ID_PCM_U16BE:
1367 audio_input_frame_size >>= 1;
1374 audio_input_frame_size = audio_codec_ctx->frame_size;
1378 initial_audio_input_frame_size = audio_input_frame_size;
1385 audio_outbuf =
new uint8_t[audio_outbuf_size];
1389 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1392 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1393 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1400 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1401 const AVCodec *
codec;
1411 char *adapter_ptr = NULL;
1415 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1416 if (adapter_num < 3 && adapter_num >=0) {
1417 #if defined(__linux__)
1418 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1420 adapter_ptr = adapter;
1421 #elif defined(_WIN32) || defined(__APPLE__)
1429 #if defined(__linux__)
1430 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1431 #elif defined(_WIN32) || defined(__APPLE__)
1432 if( adapter_ptr != NULL ) {
1441 adapter_ptr, NULL, 0) < 0) {
1456 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)
1457 video_codec_ctx->max_b_frames = 0;
1461 av_dict_set(&
opts,
"strict",
"experimental", 0);
1475 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1477 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1481 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1485 switch (video_codec_ctx->codec_id) {
1486 case AV_CODEC_ID_H264:
1487 video_codec_ctx->max_b_frames = 0;
1488 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1489 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1490 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1491 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1493 case AV_CODEC_ID_HEVC:
1496 case AV_CODEC_ID_VP9:
1501 "codec_id", video_codec_ctx->codec_id);
1507 if ((err = set_hwframe_ctx(video_codec_ctx, hw_device_ctx,
info.
width,
info.
height)) < 0) {
1516 throw InvalidCodec(
"Could not open video codec", path);
1520 av_dict_free(&
opts);
1524 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1532 void FFmpegWriter::write_audio_packets(
bool is_final) {
1534 int total_frame_samples = 0;
1535 int frame_position = 0;
1536 int channels_in_frame = 0;
1537 int sample_rate_in_frame = 0;
1538 int samples_in_frame = 0;
1543 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1544 int16_t *all_resampled_samples = NULL;
1545 int16_t *final_samples_planar = NULL;
1546 int16_t *final_samples = NULL;
1549 while (!queued_audio_frames.empty()) {
1551 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1554 sample_rate_in_frame = frame->SampleRate();
1555 samples_in_frame = frame->GetAudioSamplesCount();
1556 channels_in_frame = frame->GetAudioChannelsCount();
1557 channel_layout_in_frame = frame->ChannelsLayout();
1560 float *frame_samples_float = NULL;
1562 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1565 total_frame_samples = samples_in_frame * channels_in_frame;
1568 const int16_t max16 = 32767;
1569 const int16_t min16 = -32768;
1570 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1571 float valF = frame_samples_float[s] * (1 << 15);
1575 }
else if (valF < min16) {
1578 conv = int(valF + 32768.5) - 32768;
1582 all_queued_samples[frame_position] = conv;
1586 delete[] frame_samples_float;
1589 queued_audio_frames.pop_front();
1595 total_frame_samples = frame_position;
1596 int remaining_frame_samples = total_frame_samples;
1597 int samples_position = 0;
1600 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets",
"is_final", is_final,
"total_frame_samples", total_frame_samples,
"channel_layout_in_frame", channel_layout_in_frame,
"channels_in_frame", channels_in_frame,
"samples_in_frame", samples_in_frame,
"LAYOUT_MONO",
LAYOUT_MONO);
1603 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1605 AVFrame *audio_frame = NULL;
1610 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1613 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);
1614 if (error_code < 0) {
1619 switch (audio_codec_ctx->sample_fmt) {
1620 case AV_SAMPLE_FMT_FLTP: {
1621 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1624 case AV_SAMPLE_FMT_S32P: {
1625 output_sample_fmt = AV_SAMPLE_FMT_S32;
1628 case AV_SAMPLE_FMT_S16P: {
1629 output_sample_fmt = AV_SAMPLE_FMT_S16;
1632 case AV_SAMPLE_FMT_U8P: {
1633 output_sample_fmt = AV_SAMPLE_FMT_U8;
1643 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1644 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1649 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1650 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1652 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (1st resampling)",
"in_sample_fmt", AV_SAMPLE_FMT_S16,
"out_sample_fmt", output_sample_fmt,
"in_sample_rate", sample_rate_in_frame,
"out_sample_rate",
info.
sample_rate,
"in_channels", channels_in_frame,
"out_channels",
info.
channels);
1657 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1659 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1660 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1661 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1663 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1670 audio_converted->data,
1671 audio_converted->linesize[0],
1672 audio_converted->nb_samples,
1674 audio_frame->linesize[0],
1675 audio_frame->nb_samples
1679 remaining_frame_samples = total_frame_samples;
1682 all_resampled_samples = (int16_t *) av_malloc(
1684 * (av_get_bytes_per_sample(output_sample_fmt) /
1685 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1689 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1692 av_freep(&(audio_frame->data[0]));
1694 av_freep(&audio_converted->data[0]);
1696 all_queued_samples = NULL;
1698 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
"nb_samples", nb_samples,
"remaining_frame_samples", remaining_frame_samples);
1702 while (remaining_frame_samples > 0 || is_final) {
1704 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1708 if (remaining_frame_samples >= remaining_packet_samples) {
1709 diff = remaining_packet_samples;
1711 diff = remaining_frame_samples;
1718 samples + (audio_input_position
1719 * (av_get_bytes_per_sample(output_sample_fmt) /
1720 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1722 all_resampled_samples + samples_position,
1723 diff * av_get_bytes_per_sample(output_sample_fmt)
1727 audio_input_position += diff;
1728 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1729 remaining_frame_samples -= diff;
1732 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1739 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1741 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1742 "in_sample_fmt", output_sample_fmt,
1743 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1755 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1756 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1759 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1760 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1767 audio_frame->nb_samples = audio_input_position /
info.
channels;
1770 final_samples_planar = (int16_t *) av_malloc(
1771 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1772 * (av_get_bytes_per_sample(output_sample_fmt) /
1773 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1777 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1780 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1781 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1784 frame_final->nb_samples = audio_input_frame_size;
1786 frame_final->format = audio_codec_ctx->sample_fmt;
1788 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1789 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1795 frame_final->linesize[0],
1796 frame_final->nb_samples,
1798 audio_frame->linesize[0],
1799 audio_frame->nb_samples
1803 if (nb_samples > 0) {
1804 memcpy(samples, frame_final->data[0],
1805 nb_samples * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) *
info.
channels);
1809 av_freep(&(audio_frame->data[0]));
1811 all_queued_samples = NULL;
1817 final_samples = (int16_t *) av_malloc(
1818 sizeof(int16_t) * audio_input_position
1819 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1820 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1824 memcpy(final_samples, samples,
1825 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1828 frame_final->nb_samples = audio_input_frame_size;
1831 avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1832 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1833 audio_encoder_buffer_size, 0);
1837 frame_final->pts = audio_timestamp;
1841 av_init_packet(&pkt);
1842 pkt.data = audio_encoder_buffer;
1843 pkt.size = audio_encoder_buffer_size;
1846 pkt.pts = pkt.dts = audio_timestamp;
1849 int got_packet_ptr = 0;
1855 int frame_finished = 0;
1856 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1857 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1858 avcodec_send_frame(audio_codec_ctx, NULL);
1863 ret = avcodec_receive_packet(audio_codec_ctx, &pkt);
1866 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1867 avcodec_flush_buffers(audio_codec_ctx);
1871 ret = frame_finished;
1874 if (!pkt.data && !frame_finished)
1878 got_packet_ptr = ret;
1881 int error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, frame_final, &got_packet_ptr);
1884 if (error_code == 0 && got_packet_ptr) {
1888 pkt.pts = pkt.dts = audio_timestamp;
1891 av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
1894 pkt.stream_index = audio_st->index;
1895 pkt.flags |= AV_PKT_FLAG_KEY;
1898 error_code = av_interleaved_write_frame(oc, &pkt);
1901 if (error_code < 0) {
1906 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
1909 av_freep(&(frame_final->data[0]));
1916 audio_input_position = 0;
1921 if (all_resampled_samples) {
1922 av_freep(&all_resampled_samples);
1923 all_resampled_samples = NULL;
1925 if (all_queued_samples) {
1926 av_freep(&all_queued_samples);
1927 all_queued_samples = NULL;
1932 AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
1934 AVFrame *new_av_frame = NULL;
1938 if (new_av_frame == NULL)
1939 throw OutOfMemory(
"Could not allocate AVFrame", path);
1947 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
1950 new_av_frame->width = width;
1951 new_av_frame->height = height;
1952 new_av_frame->format = pix_fmt;
1956 return new_av_frame;
1960 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
1962 int source_image_width = frame->GetWidth();
1963 int source_image_height = frame->GetHeight();
1966 if (source_image_height == 1 && source_image_width == 1)
1970 if (image_rescalers.size() == 0)
1971 InitScalers(source_image_width, source_image_height);
1974 SwsContext *scaler = image_rescalers[rescaler_position];
1975 rescaler_position++;
1976 if (rescaler_position == num_of_rescalers)
1977 rescaler_position = 0;
1980 int bytes_source = 0;
1981 int bytes_final = 0;
1982 AVFrame *frame_source = NULL;
1983 const uchar *pixels = NULL;
1986 pixels = frame->GetPixels();
1989 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
1991 AVFrame *frame_final;
1994 frame_final = allocate_avframe(AV_PIX_FMT_NV12,
info.
width,
info.
height, &bytes_final, NULL);
1998 frame_final = allocate_avframe(
1999 (AVPixelFormat)(video_st->codecpar->format),
2004 AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
2012 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
2013 source_image_height, frame_final->data, frame_final->linesize);
2016 add_avframe(frame, frame_final);
2023 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2024 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2027 "frame->number", frame->number,
"oc->oformat->flags", oc->oformat->flags);
2032 "frame->number", frame->number,
2033 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2035 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2039 av_packet_from_data(
2040 pkt, frame_final->data[0],
2041 frame_final->linesize[0] * frame_final->height);
2043 pkt->flags |= AV_PKT_FLAG_KEY;
2044 pkt->stream_index = video_st->index;
2047 pkt->pts = video_timestamp;
2050 int error_code = av_interleaved_write_frame(oc, pkt);
2051 if (error_code < 0) {
2063 av_init_packet(&pkt);
2066 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
2069 frame_final->pts = video_timestamp;
2072 if (!(
hw_frame = av_frame_alloc())) {
2073 std::clog <<
"Error code: av_hwframe_alloc\n";
2075 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2076 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2079 std::clog <<
"Error hw_frames_ctx.\n";
2081 hw_frame->format = AV_PIX_FMT_NV12;
2082 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2083 std::clog <<
"Error while transferring frame data to surface.\n";
2085 av_frame_copy_props(
hw_frame, frame_final);
2089 int got_packet_ptr = 0;
2097 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2101 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2106 if (ret == AVERROR(EAGAIN) ) {
2107 std::clog <<
"Frame EAGAIN\n";
2109 if (ret == AVERROR_EOF ) {
2110 std::clog <<
"Frame AVERROR_EOF\n";
2112 avcodec_send_frame(video_codec_ctx, NULL);
2116 ret = avcodec_receive_packet(video_codec_ctx, &pkt);
2118 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2119 avcodec_flush_buffers(video_codec_ctx);
2131 error_code = avcodec_encode_video2(video_codec_ctx, &pkt, frame_final, &got_packet_ptr);
2132 if (error_code != 0) {
2135 if (got_packet_ptr == 0) {
2141 if (error_code == 0 && got_packet_ptr) {
2143 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
2144 pkt.stream_index = video_st->index;
2147 int result = av_interleaved_write_frame(oc, &pkt);
2167 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2176 av_dump_format(oc, 0, path.c_str(), 1);
2180 void FFmpegWriter::InitScalers(
int source_width,
int source_height) {
2181 int scale_mode = SWS_FAST_BILINEAR;
2183 scale_mode = SWS_BICUBIC;
2187 for (
int x = 0; x < num_of_rescalers; x++) {
2191 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2196 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2198 scale_mode, NULL, NULL, NULL);
2202 image_rescalers.push_back(img_convert_ctx);
2208 original_sample_rate = sample_rate;
2209 original_channels = channels;
2215 for (
int x = 0; x < num_of_rescalers; x++)
2216 sws_freeContext(image_rescalers[x]);
2219 image_rescalers.clear();
Header file for all Exception classes.
#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_FIND_DECODER_CODEC_ID(av_stream)
#define AV_ALLOCATE_FRAME()
#define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec)
#define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height)
#define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec)
#define AV_FREE_PACKET(av_packet)
#define AVCODEC_MAX_AUDIO_FRAME_SIZE
#define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context)
#define MY_INPUT_BUFFER_PADDING_SIZE
#define AV_RESET_FRAME(av_frame)
AVPixelFormat hw_en_av_pix_fmt
AV_COPY_PARAMS_FROM_CONTEXT(st, video_codec_ctx)
AVHWDeviceType hw_en_av_device_type
Header file for FFmpegWriter class.
#define FF_NUM_PROCESSORS
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 too many seek attempts happen.
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.