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), fmt(NULL), 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() {
127 fmt = av_guess_format(NULL, path.c_str(), NULL);
129 throw InvalidFormat(
"Could not deduce output format from file extension.", path);
134 throw OutOfMemory(
"Could not allocate memory for AVFormatContext.", path);
142 info.
vcodec = avcodec_find_encoder(fmt->video_codec)->name;
146 info.
acodec = avcodec_find_encoder(fmt->audio_codec)->name;
150 void FFmpegWriter::initialize_streams() {
151 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::initialize_streams",
"fmt->video_codec", fmt->video_codec,
"fmt->audio_codec", fmt->audio_codec,
"AV_CODEC_ID_NONE", AV_CODEC_ID_NONE);
158 video_st = add_video_stream();
162 audio_st = add_audio_stream();
168 if (
codec.length() > 0) {
172 #if defined(__linux__)
173 if (strstr(
codec.c_str(),
"_vaapi") != NULL) {
174 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
179 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
180 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
186 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
190 #elif defined(_WIN32)
191 if (strstr(
codec.c_str(),
"_dxva2") != NULL) {
192 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
197 }
else if (strstr(
codec.c_str(),
"_nvenc") != NULL) {
198 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
204 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
208 #elif defined(__APPLE__)
209 if (strstr(
codec.c_str(),
"_videotoolbox") != NULL) {
210 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
216 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
221 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
224 new_codec = avcodec_find_encoder_by_name(
codec.c_str());
226 if (new_codec == NULL)
227 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
233 fmt->video_codec = new_codec->id;
249 if (pixel_ratio.
num > 0) {
253 if (bit_rate >= 1000)
255 if ((bit_rate >= 0) && (bit_rate < 256))
271 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);
281 true,
codec, fps, width, height,
290 if (
codec.length() > 0) {
291 AVCodec *new_codec = avcodec_find_encoder_by_name(
codec.c_str());
292 if (new_codec == NULL)
293 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
299 fmt->audio_codec = new_codec->id;
302 if (sample_rate > 7999)
311 if (original_sample_rate == 0)
313 if (original_channels == 0)
317 "FFmpegWriter::SetAudioOptions (" +
codec +
")",
318 "sample_rate", sample_rate,
319 "channels", channels,
320 "bit_rate", bit_rate);
331 true,
codec, sample_rate, 2,
340 AVCodecContext *c = NULL;
342 std::stringstream convert(value);
361 throw NoStreamsFound(
"The stream was not found. Be sure to call PrepareStreams() first.", path);
364 const AVOption *option = NULL;
372 if (option || (name ==
"g" || name ==
"qmin" || name ==
"qmax" || name ==
"max_b_frames" || name ==
"mb_decision" ||
373 name ==
"level" || name ==
"profile" || name ==
"slices" || name ==
"rc_min_rate" || name ==
"rc_max_rate" ||
374 name ==
"rc_buffer_size" || name ==
"crf" || name ==
"cqp" || name ==
"qp")) {
378 convert >> c->gop_size;
380 else if (name ==
"qmin")
384 else if (name ==
"qmax")
388 else if (name ==
"max_b_frames")
390 convert >> c->max_b_frames;
392 else if (name ==
"mb_decision")
394 convert >> c->mb_decision;
396 else if (name ==
"level")
400 else if (name ==
"profile")
402 convert >> c->profile;
404 else if (name ==
"slices")
406 convert >> c->slices;
408 else if (name ==
"rc_min_rate")
410 convert >> c->rc_min_rate;
412 else if (name ==
"rc_max_rate")
414 convert >> c->rc_max_rate;
416 else if (name ==
"rc_buffer_size")
418 convert >> c->rc_buffer_size;
420 else if (name ==
"cqp") {
426 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
430 switch (c->codec_id) {
431 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
433 case AV_CODEC_ID_AV1 :
435 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
438 case AV_CODEC_ID_VP8 :
439 c->bit_rate = 10000000;
440 av_opt_set_int(c->priv_data,
"qp", std::max(std::min(std::stoi(value), 63), 4), 0);
442 case AV_CODEC_ID_VP9 :
444 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
445 if (std::stoi(value) == 0) {
446 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
447 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
450 case AV_CODEC_ID_H264 :
451 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
452 if (std::stoi(value) == 0) {
453 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
457 case AV_CODEC_ID_HEVC :
458 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 51), 0);
459 if (std::stoi(value) == 0) {
460 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
461 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
466 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value), 63), 0);
470 }
else if (name ==
"crf") {
476 double mbs = 15000000.0;
485 c->bit_rate = (int)(mbs);
489 switch (c->codec_id) {
490 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
492 case AV_CODEC_ID_AV1 :
495 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
498 case AV_CODEC_ID_VP8 :
499 c->bit_rate = 10000000;
500 av_opt_set_int(c->priv_data,
"crf", std::max(std::min(std::stoi(value), 63), 4), 0);
502 case AV_CODEC_ID_VP9 :
504 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 63), 0);
505 if (std::stoi(value) == 0) {
506 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
507 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
510 case AV_CODEC_ID_H264 :
511 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
512 if (std::stoi(value) == 0) {
513 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
517 case AV_CODEC_ID_HEVC :
518 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
519 av_opt_set_int(c->priv_data,
"preset", 7, 0);
520 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
521 av_opt_set_int(c->priv_data,
"qp",std::min(std::stoi(value), 51),0);
524 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value), 51), 0);
526 if (std::stoi(value) == 0) {
527 av_opt_set(c->priv_data,
"preset",
"veryslow", 0);
528 av_opt_set_int(c->priv_data,
"lossless", 1, 0);
534 double mbs = 15000000.0;
542 c->bit_rate = (int) (mbs);
545 }
else if (name ==
"qp") {
549 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
551 switch (c->codec_id) {
552 case AV_CODEC_ID_AV1 :
554 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
555 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),63), 0);
557 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
560 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),255), 0);
562 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
566 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
569 av_opt_set_int(c->priv_data,
"crf", std::min(std::stoi(value),63), 0);
571 case AV_CODEC_ID_HEVC :
573 if (strstr(
info.
vcodec.c_str(),
"svt_hevc") != NULL) {
574 av_opt_set_int(c->priv_data,
"qp", std::min(std::stoi(value),51), 0);
575 av_opt_set_int(c->priv_data,
"preset", 7, 0);
576 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
583 AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
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);
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 (!(fmt->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 throw InvalidFile(
"Could not write header to file.", path);
666 if (dict) av_dict_free(&dict);
679 throw WriterClosed(
"The FFmpegWriter is closed. Call Open() before calling this method.", path);
684 spooled_video_frames.push_back(frame);
687 spooled_audio_frames.push_back(frame);
689 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);
692 if ((
int)spooled_video_frames.size() == cache_size || (
int)spooled_audio_frames.size() == cache_size) {
694 write_queued_frames();
702 void FFmpegWriter::write_queued_frames() {
703 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_queued_frames",
"spooled_video_frames.size()", spooled_video_frames.size(),
"spooled_audio_frames.size()", spooled_audio_frames.size());
709 queued_video_frames = spooled_video_frames;
710 queued_audio_frames = spooled_audio_frames;
713 spooled_video_frames.clear();
714 spooled_audio_frames.clear();
717 bool has_error_encoding_video =
false;
720 if (
info.
has_audio && audio_st && !queued_audio_frames.empty())
721 write_audio_packets(
false);
724 while (!queued_video_frames.empty()) {
726 std::shared_ptr<Frame> frame = queued_video_frames.front();
729 processed_frames.push_back(frame);
733 process_video_packet(frame);
736 queued_video_frames.pop_front();
742 while (!processed_frames.empty()) {
744 std::shared_ptr<Frame> frame = processed_frames.front();
748 deallocate_frames.push_back(frame);
751 if (av_frames.count(frame)) {
753 AVFrame *frame_final = av_frames[frame];
756 bool success = write_video_packet(frame, frame_final);
758 has_error_encoding_video =
true;
763 processed_frames.pop_front();
767 while (!deallocate_frames.empty()) {
769 std::shared_ptr<Frame> frame = deallocate_frames.front();
772 if (av_frames.count(frame)) {
774 AVFrame *av_frame = av_frames[frame];
777 av_freep(&(av_frame->data[0]));
779 av_frames.erase(frame);
783 deallocate_frames.pop_front();
790 if (has_error_encoding_video)
799 for (int64_t number = start; number <= length; number++) {
801 std::shared_ptr<Frame> f = reader->
GetFrame(number);
811 write_queued_frames();
815 write_audio_packets(
true);
824 av_write_trailer(oc);
827 write_trailer =
true;
833 void FFmpegWriter::flush_encoders() {
836 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
850 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
853 av_init_packet(&pkt);
863 error_code = avcodec_send_frame(video_codec_ctx, NULL);
865 while (error_code >= 0) {
866 error_code = avcodec_receive_packet(video_codec_ctx, &pkt);
867 if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
870 avcodec_flush_buffers(video_codec_ctx);
873 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
874 pkt.stream_index = video_st->index;
875 error_code = av_interleaved_write_frame(oc, &pkt);
880 error_code = avcodec_encode_video2(video_codec_ctx, &pkt, NULL, &got_packet);
884 if (error_code < 0) {
892 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
893 pkt.stream_index = video_st->index;
896 error_code = av_interleaved_write_frame(oc, &pkt);
897 if (error_code < 0) {
906 av_init_packet(&pkt);
909 pkt.pts = pkt.dts = audio_timestamp;
915 error_code = avcodec_send_frame(audio_codec_ctx, NULL);
917 error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, NULL, &got_packet);
919 if (error_code < 0) {
921 "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) +
"]",
922 "error_code", error_code);
930 pkt.pts = pkt.dts = audio_timestamp;
933 av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
936 pkt.stream_index = audio_st->index;
937 pkt.flags |= AV_PKT_FLAG_KEY;
940 error_code = av_interleaved_write_frame(oc, &pkt);
941 if (error_code < 0) {
943 "FFmpegWriter::flush_encoders ERROR [" + av_err2string(error_code) +
"]",
944 "error_code", error_code);
948 audio_timestamp += pkt.duration;
958 void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
963 av_buffer_unref(&hw_device_ctx);
964 hw_device_ctx = NULL;
971 void FFmpegWriter::close_audio(AVFormatContext *oc, AVStream *st)
975 delete[] audio_outbuf;
976 delete[] audio_encoder_buffer;
979 audio_encoder_buffer = NULL;
1003 close_video(oc, video_st);
1005 close_audio(oc, audio_st);
1008 if (image_rescalers.size() > 0)
1011 if (!(fmt->flags & AVFMT_NOFILE)) {
1017 video_timestamp = 0;
1018 audio_timestamp = 0;
1021 avformat_free_context(oc);
1026 prepare_streams =
false;
1027 write_header =
false;
1028 write_trailer =
false;
1034 void FFmpegWriter::add_avframe(std::shared_ptr<Frame> frame, AVFrame *av_frame) {
1036 if (!av_frames.count(frame)) {
1038 av_frames[frame] = av_frame;
1046 AVStream *FFmpegWriter::add_audio_stream() {
1053 throw InvalidCodec(
"A valid audio codec could not be found for this file.", path);
1056 if (audio_codec_ctx != NULL) {
1063 c->codec_id =
codec->id;
1064 c->codec_type = AVMEDIA_TYPE_AUDIO;
1071 if (
codec->supported_samplerates) {
1073 for (i = 0;
codec->supported_samplerates[i] != 0; i++)
1079 if (
codec->supported_samplerates[i] == 0)
1080 throw InvalidSampleRate(
"An invalid sample rate was detected for this codec.", path);
1088 if (
codec->channel_layouts) {
1090 for (i = 0;
codec->channel_layouts[i] != 0; i++)
1091 if (channel_layout ==
codec->channel_layouts[i]) {
1093 c->channel_layout = channel_layout;
1096 if (
codec->channel_layouts[i] == 0)
1097 throw InvalidChannels(
"An invalid channel layout was detected (i.e. MONO / STEREO).", path);
1100 c->channel_layout = channel_layout;
1103 if (
codec->sample_fmts) {
1104 for (
int i = 0;
codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
1106 c->sample_fmt =
codec->sample_fmts[i];
1110 if (c->sample_fmt == AV_SAMPLE_FMT_NONE) {
1112 c->sample_fmt = AV_SAMPLE_FMT_S16;
1116 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1117 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1119 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1121 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1125 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);
1131 AVStream *FFmpegWriter::add_video_stream() {
1138 throw InvalidCodec(
"A valid video codec could not be found for this file.", path);
1143 c->codec_id =
codec->id;
1144 c->codec_type = AVMEDIA_TYPE_VIDEO;
1148 #
if (LIBAVCODEC_VERSION_MAJOR >= 58)
1149 && c->codec_id != AV_CODEC_ID_AV1
1154 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
1163 switch (c->codec_id) {
1164 #if (LIBAVCODEC_VERSION_MAJOR >= 58)
1166 case AV_CODEC_ID_AV1 :
1170 if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1171 int calculated_quality = 35;
1174 av_opt_set_int(c->priv_data,
"crf", calculated_quality, 0);
1177 int calculated_quality = 50;
1180 av_opt_set_int(c->priv_data,
"qp", calculated_quality, 0);
1184 if (strstr(
info.
vcodec.c_str(),
"svtav1") != NULL) {
1185 av_opt_set_int(c->priv_data,
"preset", 6, 0);
1186 av_opt_set_int(c->priv_data,
"forced-idr",1,0);
1188 else if (strstr(
info.
vcodec.c_str(),
"rav1e") != NULL) {
1189 av_opt_set_int(c->priv_data,
"speed", 7, 0);
1190 av_opt_set_int(c->priv_data,
"tile-rows", 2, 0);
1191 av_opt_set_int(c->priv_data,
"tile-columns", 4, 0);
1193 else if (strstr(
info.
vcodec.c_str(),
"aom") != NULL) {
1196 av_opt_set_int(c->priv_data,
"tile-rows", 1, 0);
1197 av_opt_set_int(c->priv_data,
"tile-columns", 2, 0);
1198 av_opt_set_int(c->priv_data,
"row-mt", 1, 0);
1199 av_opt_set_int(c->priv_data,
"cpu-used", 3, 0);
1203 case AV_CODEC_ID_VP9 :
1204 case AV_CODEC_ID_HEVC :
1205 case AV_CODEC_ID_VP8 :
1206 case AV_CODEC_ID_H264 :
1242 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0)
1243 c->framerate = av_inv_q(c->time_base);
1245 st->avg_frame_rate = av_inv_q(c->time_base);
1248 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
1249 #pragma GCC diagnostic push
1250 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1253 #pragma GCC diagnostic pop
1257 c->max_b_frames = 10;
1258 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
1260 c->max_b_frames = 2;
1261 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
1267 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
1268 #if (LIBAVCODEC_VERSION_MAJOR >= 57)
1270 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1272 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1277 while (supported_pixel_formats != NULL && *supported_pixel_formats !=
PIX_FMT_NONE) {
1280 c->pix_fmt = *supported_pixel_formats;
1281 ++supported_pixel_formats;
1286 if (fmt->video_codec == AV_CODEC_ID_RAWVIDEO) {
1290 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1292 if (strcmp(fmt->name,
"gif") != 0)
1295 oc->oformat->flags |= AVFMT_RAWPICTURE;
1304 #if (LIBAVFORMAT_VERSION_MAJOR < 58)
1306 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);
1308 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);
1315 void FFmpegWriter::open_audio(AVFormatContext *oc, AVStream *st) {
1325 codec = avcodec_find_encoder(audio_codec_ctx->codec_id);
1330 AVDictionary *
opts = NULL;
1331 av_dict_set(&
opts,
"strict",
"experimental", 0);
1334 if (avcodec_open2(audio_codec_ctx,
codec, &
opts) < 0)
1335 throw InvalidCodec(
"Could not open audio codec", path);
1339 av_dict_free(&
opts);
1343 if (audio_codec_ctx->frame_size <= 1) {
1349 case AV_CODEC_ID_PCM_S16LE:
1350 case AV_CODEC_ID_PCM_S16BE:
1351 case AV_CODEC_ID_PCM_U16LE:
1352 case AV_CODEC_ID_PCM_U16BE:
1353 audio_input_frame_size >>= 1;
1360 audio_input_frame_size = audio_codec_ctx->frame_size;
1364 initial_audio_input_frame_size = audio_input_frame_size;
1371 audio_outbuf =
new uint8_t[audio_outbuf_size];
1375 audio_encoder_buffer =
new uint8_t[audio_encoder_buffer_size];
1378 for (std::map<std::string, std::string>::iterator iter =
info.
metadata.begin(); iter !=
info.
metadata.end(); ++iter) {
1379 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1386 void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
1397 char *adapter_ptr = NULL;
1401 std::clog <<
"Encoding Device Nr: " << adapter_num <<
"\n";
1402 if (adapter_num < 3 && adapter_num >=0) {
1403 #if defined(__linux__)
1404 snprintf(adapter,
sizeof(adapter),
"/dev/dri/renderD%d", adapter_num+128);
1406 adapter_ptr = adapter;
1407 #elif defined(_WIN32) || defined(__APPLE__)
1415 #if defined(__linux__)
1416 if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) {
1417 #elif defined(_WIN32) || defined(__APPLE__)
1418 if( adapter_ptr != NULL ) {
1427 adapter_ptr, NULL, 0) < 0) {
1442 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)
1443 video_codec_ctx->max_b_frames = 0;
1447 av_dict_set(&
opts,
"strict",
"experimental", 0);
1461 if (av_opt_get_int(video_codec_ctx->priv_data,
"qp", 0, &qp) != 0 || qp == 0) {
1463 av_opt_set(video_codec_ctx->priv_data,
"rc_mode",
"VBR", 0);
1467 video_codec_ctx->rc_max_rate = video_codec_ctx->bit_rate;
1471 switch (video_codec_ctx->codec_id) {
1472 case AV_CODEC_ID_H264:
1473 video_codec_ctx->max_b_frames = 0;
1474 video_codec_ctx->profile = FF_PROFILE_H264_BASELINE | FF_PROFILE_H264_CONSTRAINED;
1475 av_opt_set(video_codec_ctx->priv_data,
"preset",
"slow", 0);
1476 av_opt_set(video_codec_ctx->priv_data,
"tune",
"zerolatency", 0);
1477 av_opt_set(video_codec_ctx->priv_data,
"vprofile",
"baseline", AV_OPT_SEARCH_CHILDREN);
1479 case AV_CODEC_ID_HEVC:
1482 case AV_CODEC_ID_VP9:
1487 "codec_id", video_codec_ctx->codec_id);
1493 if ((err = set_hwframe_ctx(video_codec_ctx, hw_device_ctx,
info.
width,
info.
height)) < 0) {
1502 throw InvalidCodec(
"Could not open video codec", path);
1506 av_dict_free(&
opts);
1510 av_dict_set(&st->metadata, iter->first.c_str(), iter->second.c_str(), 0);
1518 void FFmpegWriter::write_audio_packets(
bool is_final) {
1520 int total_frame_samples = 0;
1521 int frame_position = 0;
1522 int channels_in_frame = 0;
1523 int sample_rate_in_frame = 0;
1524 int samples_in_frame = 0;
1529 int16_t *all_queued_samples = (int16_t *) av_malloc(all_queued_samples_size);
1530 int16_t *all_resampled_samples = NULL;
1531 int16_t *final_samples_planar = NULL;
1532 int16_t *final_samples = NULL;
1535 while (!queued_audio_frames.empty()) {
1537 std::shared_ptr<Frame> frame = queued_audio_frames.front();
1540 sample_rate_in_frame = frame->SampleRate();
1541 samples_in_frame = frame->GetAudioSamplesCount();
1542 channels_in_frame = frame->GetAudioChannelsCount();
1543 channel_layout_in_frame = frame->ChannelsLayout();
1546 float *frame_samples_float = NULL;
1548 frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
1551 total_frame_samples = samples_in_frame * channels_in_frame;
1554 const int16_t max16 = 32767;
1555 const int16_t min16 = -32768;
1556 for (
int s = 0; s < total_frame_samples; s++, frame_position++) {
1557 float valF = frame_samples_float[s] * (1 << 15);
1561 }
else if (valF < min16) {
1564 conv = int(valF + 32768.5) - 32768;
1568 all_queued_samples[frame_position] = conv;
1572 delete[] frame_samples_float;
1575 queued_audio_frames.pop_front();
1581 total_frame_samples = frame_position;
1582 int remaining_frame_samples = total_frame_samples;
1583 int samples_position = 0;
1586 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);
1589 AVSampleFormat output_sample_fmt = audio_codec_ctx->sample_fmt;
1591 AVFrame *audio_frame = NULL;
1596 audio_frame->nb_samples = total_frame_samples / channels_in_frame;
1599 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);
1600 if (error_code < 0) {
1605 switch (audio_codec_ctx->sample_fmt) {
1606 case AV_SAMPLE_FMT_FLTP: {
1607 output_sample_fmt = AV_SAMPLE_FMT_FLT;
1610 case AV_SAMPLE_FMT_S32P: {
1611 output_sample_fmt = AV_SAMPLE_FMT_S32;
1614 case AV_SAMPLE_FMT_S16P: {
1615 output_sample_fmt = AV_SAMPLE_FMT_S16;
1618 case AV_SAMPLE_FMT_U8P: {
1619 output_sample_fmt = AV_SAMPLE_FMT_U8;
1629 total_frame_samples *= (float(
info.
sample_rate) / sample_rate_in_frame);
1630 total_frame_samples *= (float(
info.
channels) / channels_in_frame);
1635 audio_converted->nb_samples = total_frame_samples / channels_in_frame;
1636 av_samples_alloc(audio_converted->data, audio_converted->linesize,
info.
channels, audio_converted->nb_samples, output_sample_fmt, 0);
1638 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);
1643 av_opt_set_int(avr,
"in_channel_layout", channel_layout_in_frame, 0);
1645 av_opt_set_int(avr,
"in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1646 av_opt_set_int(avr,
"out_sample_fmt", output_sample_fmt, 0);
1647 av_opt_set_int(avr,
"in_sample_rate", sample_rate_in_frame, 0);
1649 av_opt_set_int(avr,
"in_channels", channels_in_frame, 0);
1656 audio_converted->data,
1657 audio_converted->linesize[0],
1658 audio_converted->nb_samples,
1660 audio_frame->linesize[0],
1661 audio_frame->nb_samples
1665 remaining_frame_samples = total_frame_samples;
1668 all_resampled_samples = (int16_t *) av_malloc(
1670 * (av_get_bytes_per_sample(output_sample_fmt) /
1671 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1675 memcpy(all_resampled_samples, audio_converted->data[0], nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1678 av_freep(&(audio_frame->data[0]));
1680 av_freep(&audio_converted->data[0]);
1682 all_queued_samples = NULL;
1684 ZmqLogger::Instance()->
AppendDebugMethod(
"FFmpegWriter::write_audio_packets (Successfully completed 1st resampling)",
"nb_samples", nb_samples,
"remaining_frame_samples", remaining_frame_samples);
1688 while (remaining_frame_samples > 0 || is_final) {
1690 int remaining_packet_samples = (audio_input_frame_size *
info.
channels) - audio_input_position;
1694 if (remaining_frame_samples >= remaining_packet_samples) {
1695 diff = remaining_packet_samples;
1697 diff = remaining_frame_samples;
1704 samples + (audio_input_position
1705 * (av_get_bytes_per_sample(output_sample_fmt) /
1706 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1708 all_resampled_samples + samples_position,
1709 diff * av_get_bytes_per_sample(output_sample_fmt)
1713 audio_input_position += diff;
1714 samples_position += diff * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
1715 remaining_frame_samples -= diff;
1718 if (audio_input_position < (audio_input_frame_size *
info.
channels) && !is_final)
1725 if (av_sample_fmt_is_planar(audio_codec_ctx->sample_fmt)) {
1727 "FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)",
1728 "in_sample_fmt", output_sample_fmt,
1729 "out_sample_fmt", audio_codec_ctx->sample_fmt,
1741 av_opt_set_int(avr_planar,
"in_sample_fmt", output_sample_fmt, 0);
1742 av_opt_set_int(avr_planar,
"out_sample_fmt", audio_codec_ctx->sample_fmt, 0);
1745 av_opt_set_int(avr_planar,
"in_channels",
info.
channels, 0);
1746 av_opt_set_int(avr_planar,
"out_channels",
info.
channels, 0);
1753 audio_frame->nb_samples = audio_input_position /
info.
channels;
1756 final_samples_planar = (int16_t *) av_malloc(
1757 sizeof(int16_t) * audio_frame->nb_samples *
info.
channels
1758 * (av_get_bytes_per_sample(output_sample_fmt) /
1759 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1763 memcpy(final_samples_planar, samples, audio_frame->nb_samples *
info.
channels * av_get_bytes_per_sample(output_sample_fmt));
1766 avcodec_fill_audio_frame(audio_frame,
info.
channels, output_sample_fmt,
1767 (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0);
1770 frame_final->nb_samples = audio_input_frame_size;
1772 frame_final->format = audio_codec_ctx->sample_fmt;
1774 av_samples_alloc(frame_final->data, frame_final->linesize,
info.
channels,
1775 frame_final->nb_samples, audio_codec_ctx->sample_fmt, 0);
1781 frame_final->linesize[0],
1782 frame_final->nb_samples,
1784 audio_frame->linesize[0],
1785 audio_frame->nb_samples
1789 if (nb_samples > 0) {
1790 memcpy(samples, frame_final->data[0],
1791 nb_samples * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) *
info.
channels);
1795 av_freep(&(audio_frame->data[0]));
1797 all_queued_samples = NULL;
1803 final_samples = (int16_t *) av_malloc(
1804 sizeof(int16_t) * audio_input_position
1805 * (av_get_bytes_per_sample(audio_codec_ctx->sample_fmt) /
1806 av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) )
1810 memcpy(final_samples, samples,
1811 audio_input_position * av_get_bytes_per_sample(audio_codec_ctx->sample_fmt));
1814 frame_final->nb_samples = audio_input_frame_size;
1817 avcodec_fill_audio_frame(frame_final, audio_codec_ctx->channels,
1818 audio_codec_ctx->sample_fmt, (uint8_t *) final_samples,
1819 audio_encoder_buffer_size, 0);
1823 frame_final->pts = audio_timestamp;
1827 av_init_packet(&pkt);
1828 pkt.data = audio_encoder_buffer;
1829 pkt.size = audio_encoder_buffer_size;
1832 pkt.pts = pkt.dts = audio_timestamp;
1835 int got_packet_ptr = 0;
1841 int frame_finished = 0;
1842 error_code = ret = avcodec_send_frame(audio_codec_ctx, frame_final);
1843 if (ret < 0 && ret != AVERROR(EINVAL) && ret != AVERROR_EOF) {
1844 avcodec_send_frame(audio_codec_ctx, NULL);
1849 ret = avcodec_receive_packet(audio_codec_ctx, &pkt);
1852 if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
1853 avcodec_flush_buffers(audio_codec_ctx);
1857 ret = frame_finished;
1860 if (!pkt.data && !frame_finished)
1864 got_packet_ptr = ret;
1867 int error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, frame_final, &got_packet_ptr);
1870 if (error_code == 0 && got_packet_ptr) {
1874 pkt.pts = pkt.dts = audio_timestamp;
1877 av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base);
1880 pkt.stream_index = audio_st->index;
1881 pkt.flags |= AV_PKT_FLAG_KEY;
1884 error_code = av_interleaved_write_frame(oc, &pkt);
1887 if (error_code < 0) {
1892 audio_timestamp += FFMIN(audio_input_frame_size, audio_input_position);
1895 av_freep(&(frame_final->data[0]));
1902 audio_input_position = 0;
1907 if (all_resampled_samples) {
1908 av_freep(&all_resampled_samples);
1909 all_resampled_samples = NULL;
1911 if (all_queued_samples) {
1912 av_freep(&all_queued_samples);
1913 all_queued_samples = NULL;
1918 AVFrame *FFmpegWriter::allocate_avframe(
PixelFormat pix_fmt,
int width,
int height,
int *buffer_size, uint8_t *new_buffer) {
1920 AVFrame *new_av_frame = NULL;
1924 if (new_av_frame == NULL)
1925 throw OutOfMemory(
"Could not allocate AVFrame", path);
1933 new_buffer = (uint8_t *) av_malloc(*buffer_size *
sizeof(uint8_t));
1936 new_av_frame->width = width;
1937 new_av_frame->height = height;
1938 new_av_frame->format = pix_fmt;
1942 return new_av_frame;
1946 void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
1948 int source_image_width = frame->GetWidth();
1949 int source_image_height = frame->GetHeight();
1952 if (source_image_height == 1 && source_image_width == 1)
1956 if (image_rescalers.size() == 0)
1957 InitScalers(source_image_width, source_image_height);
1960 SwsContext *scaler = image_rescalers[rescaler_position];
1961 rescaler_position++;
1962 if (rescaler_position == num_of_rescalers)
1963 rescaler_position = 0;
1966 int bytes_source = 0;
1967 int bytes_final = 0;
1968 AVFrame *frame_source = NULL;
1969 const uchar *pixels = NULL;
1972 pixels = frame->GetPixels();
1975 frame_source = allocate_avframe(
PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
1977 AVFrame *frame_final;
1980 frame_final = allocate_avframe(AV_PIX_FMT_NV12,
info.
width,
info.
height, &bytes_final, NULL);
1984 frame_final = allocate_avframe(
1985 (AVPixelFormat)(video_st->codecpar->format),
1990 AVFrame *frame_final = allocate_avframe(video_codec_ctx->pix_fmt,
info.
width,
info.
height, &bytes_final, NULL);
1998 sws_scale(scaler, frame_source->data, frame_source->linesize, 0,
1999 source_image_height, frame_final->data, frame_final->linesize);
2002 add_avframe(frame, frame_final);
2009 bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *frame_final) {
2010 #if (LIBAVFORMAT_VERSION_MAJOR >= 58)
2013 "frame->number", frame->number,
"oc->oformat->flags", oc->oformat->flags);
2018 "frame->number", frame->number,
2019 "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE);
2021 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
2025 av_init_packet(&pkt);
2027 pkt.flags |= AV_PKT_FLAG_KEY;
2028 pkt.stream_index = video_st->index;
2029 pkt.data = (uint8_t *) frame_final->data;
2030 pkt.size =
sizeof(AVPicture);
2033 pkt.pts = video_timestamp;
2036 int error_code = av_interleaved_write_frame(oc, &pkt);
2037 if (error_code < 0) {
2049 av_init_packet(&pkt);
2052 pkt.pts = pkt.dts = AV_NOPTS_VALUE;
2055 frame_final->pts = video_timestamp;
2058 if (!(
hw_frame = av_frame_alloc())) {
2059 std::clog <<
"Error code: av_hwframe_alloc\n";
2061 if (av_hwframe_get_buffer(video_codec_ctx->hw_frames_ctx,
hw_frame, 0) < 0) {
2062 std::clog <<
"Error code: av_hwframe_get_buffer\n";
2065 std::clog <<
"Error hw_frames_ctx.\n";
2067 hw_frame->format = AV_PIX_FMT_NV12;
2068 if ( av_hwframe_transfer_data(
hw_frame, frame_final, 0) < 0) {
2069 std::clog <<
"Error while transferring frame data to surface.\n";
2071 av_frame_copy_props(
hw_frame, frame_final);
2075 int got_packet_ptr = 0;
2083 ret = avcodec_send_frame(video_codec_ctx,
hw_frame);
2087 ret = avcodec_send_frame(video_codec_ctx, frame_final);
2092 if (ret == AVERROR(EAGAIN) ) {
2093 std::clog <<
"Frame EAGAIN\n";
2095 if (ret == AVERROR_EOF ) {
2096 std::clog <<
"Frame AVERROR_EOF\n";
2098 avcodec_send_frame(video_codec_ctx, NULL);
2102 ret = avcodec_receive_packet(video_codec_ctx, &pkt);
2104 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2105 avcodec_flush_buffers(video_codec_ctx);
2117 error_code = avcodec_encode_video2(video_codec_ctx, &pkt, frame_final, &got_packet_ptr);
2118 if (error_code != 0) {
2121 if (got_packet_ptr == 0) {
2127 if (error_code == 0 && got_packet_ptr) {
2129 av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
2130 pkt.stream_index = video_st->index;
2133 int result = av_interleaved_write_frame(oc, &pkt);
2153 video_timestamp += av_rescale_q(1, av_make_q(
info.
fps.
den,
info.
fps.
num), video_codec_ctx->time_base);
2162 av_dump_format(oc, 0, path.c_str(), 1);
2166 void FFmpegWriter::InitScalers(
int source_width,
int source_height) {
2167 int scale_mode = SWS_FAST_BILINEAR;
2169 scale_mode = SWS_BICUBIC;
2173 for (
int x = 0; x < num_of_rescalers; x++) {
2177 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2182 img_convert_ctx = sws_getContext(source_width, source_height,
PIX_FMT_RGBA,
2184 scale_mode, NULL, NULL, NULL);
2188 image_rescalers.push_back(img_convert_ctx);
2194 original_sample_rate = sample_rate;
2195 original_channels = channels;
2201 for (
int x = 0; x < num_of_rescalers; x++)
2202 sws_freeContext(image_rescalers[x]);
2205 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 AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context)
#define AV_FIND_DECODER_CODEC_ID(av_stream)
#define AV_FORMAT_NEW_STREAM(oc, st_codec, av_codec, av_st)
#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.