diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 5b57218f9..e6a7e5ef3 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -255,7 +255,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f } if (bit_rate >= 1000) // bit_rate is the bitrate in b/s info.video_bit_rate = bit_rate; - if ((bit_rate >= 0) && (bit_rate < 64)) // bit_rate is the bitrate in crf + if ((bit_rate >= 0) && (bit_rate < 256)) // bit_rate is the bitrate in crf info.video_bit_rate = bit_rate; info.interlaced_frame = interlaced; @@ -358,7 +358,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va // Was option found? if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" || name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" || - name == "rc_buffer_size" || name == "crf" || name == "cqp")) { + name == "rc_buffer_size" || name == "crf" || name == "cqp" || name == "qp")) { // Check for specific named options if (name == "g") // Set gop_size @@ -479,6 +479,15 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va case AV_CODEC_ID_AV1 : c->bit_rate = 0; av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); + } break; #endif case AV_CODEC_ID_VP8 : @@ -500,7 +509,14 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va } break; case AV_CODEC_ID_HEVC : - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) { + av_opt_set_int(c->priv_data, "preset", 7, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + av_opt_set_int(c->priv_data, "qp",std::min(std::stoi(value), 51),0); + } + else { + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + } if (std::stoi(value) == 0) { av_opt_set(c->priv_data, "preset", "veryslow", 0); av_opt_set_int(c->priv_data, "lossless", 1, 0); @@ -520,6 +536,48 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va c->bit_rate = (int) (mbs); } } +#endif + } else if (name == "qp") { + // encode quality and special settings like lossless + // This might be better in an extra methods as more options + // and way to set quality are possible +#if (LIBAVCODEC_VERSION_MAJOR >= 58) + switch (c->codec_id) { + case AV_CODEC_ID_AV1 : + c->bit_rate = 0; + if (strstr(info.vcodec.c_str(), "svt_av1") != NULL) { + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); + av_opt_set_int(c->priv_data, "preset", 6, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { + // Set number of tiles to a fixed value + // TODO Let user choose number of tiles + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); + av_opt_set_int(c->priv_data, "speed", 7, 0); + av_opt_set_int(c->priv_data, "tile-rows", 2, 0); // number of rows + av_opt_set_int(c->priv_data, "tile-columns", 4, 0); // number of columns + } + else if (strstr(info.vcodec.c_str(), "aom") != NULL) { + // Set number of tiles to a fixed value + // TODO Let user choose number of tiles + // libaom doesn't have qp only crf + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows + av_opt_set_int(c->priv_data, "tile-columns", 2, 0); // log2 of number of columns + } + else { + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + } + case AV_CODEC_ID_HEVC : + c->bit_rate = 0; + if (strstr(info.vcodec.c_str(), "svt_hevc") != NULL) { + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),51), 0); + av_opt_set_int(c->priv_data, "preset", 7, 0); + av_opt_set_int(c->priv_data, "forced-idr",1,0); + } + break; + } #endif } else { // Set AVOption @@ -801,6 +859,9 @@ void FFmpegWriter::flush_encoders() { #if (LIBAVFORMAT_VERSION_MAJOR < 58) if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) return; +#else + if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) + return; #endif int error_code = 0; @@ -1969,10 +2030,13 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) { bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *frame_final) { #if (LIBAVFORMAT_VERSION_MAJOR >= 58) ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags); + + if (AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) { #else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE); if (oc->oformat->flags & AVFMT_RAWPICTURE) { +#endif // Raw video case. AVPacket pkt; av_init_packet(&pkt); @@ -1997,7 +2061,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra AV_FREE_PACKET(&pkt); } else -#endif { AVPacket pkt;