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;