Skip to content

Commit 0587ada

Browse files
authored
Integrate Constant Rate Factor (CRF) for FFmpegWriter (#186)
* First implementation of CRF (Constant Rate Factor) * Include AV1 in the codecs that can use crf * First version that uses SetOption to set crf quality * Clarify comments * Delete setting the bitrate for crf in SetVideoOption because it is not needed, it is set later with SetOptions.
1 parent c4321f3 commit 0587ada

File tree

1 file changed

+39
-3
lines changed

1 file changed

+39
-3
lines changed

src/FFmpegWriter.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, string codec, Fraction fps, i
146146
info.pixel_ratio.num = pixel_ratio.num;
147147
info.pixel_ratio.den = pixel_ratio.den;
148148
}
149-
if (bit_rate >= 1000)
149+
if (bit_rate >= 1000) // bit_rate is the bitrate in b/s
150150
info.video_bit_rate = bit_rate;
151151

152152
info.interlaced_frame = interlaced;
@@ -237,7 +237,8 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value)
237237

238238
// Was option found?
239239
if (option || (name == "g" || name == "qmin" || name == "qmax" || name == "max_b_frames" || name == "mb_decision" ||
240-
name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate"))
240+
name == "level" || name == "profile" || name == "slices" || name == "rc_min_rate" || name == "rc_max_rate" ||
241+
name == "crf"))
241242
{
242243
// Check for specific named options
243244
if (name == "g")
@@ -284,6 +285,39 @@ void FFmpegWriter::SetOption(StreamType stream, string name, string value)
284285
// Buffer size
285286
convert >> c->rc_buffer_size;
286287

288+
else if (name == "crf") {
289+
// encode quality and special settings like lossless
290+
// This might be better in an extra methods as more options
291+
// and way to set quality are possible
292+
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101)
293+
switch (c->codec_id) {
294+
case AV_CODEC_ID_VP8 :
295+
av_opt_set_int(c->priv_data, "crf", min(stoi(value),63), 0);
296+
break;
297+
case AV_CODEC_ID_VP9 :
298+
av_opt_set_int(c->priv_data, "crf", min(stoi(value),63), 0);
299+
if (stoi(value) == 0) {
300+
av_opt_set_int(c->priv_data, "lossless", 1, 0);
301+
}
302+
break;
303+
case AV_CODEC_ID_H264 :
304+
av_opt_set_int(c->priv_data, "crf", min(stoi(value),51), 0);
305+
break;
306+
case AV_CODEC_ID_H265 :
307+
av_opt_set_int(c->priv_data, "crf", min(stoi(value),51), 0);
308+
if (stoi(value) == 0) {
309+
av_opt_set_int(c->priv_data, "lossless", 1, 0);
310+
}
311+
break;
312+
#ifdef AV_CODEC_ID_AV1
313+
case AV_CODEC_ID_AV1 :
314+
av_opt_set_int(c->priv_data, "crf", min(stoi(value),63), 0);
315+
break;
316+
#endif
317+
}
318+
#endif
319+
}
320+
287321
else
288322
// Set AVOption
289323
AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c);
@@ -934,7 +968,9 @@ AVStream* FFmpegWriter::add_video_stream()
934968
#endif
935969

936970
/* Init video encoder options */
937-
c->bit_rate = info.video_bit_rate;
971+
if (info.video_bit_rate > 1000) {
972+
c->bit_rate = info.video_bit_rate;
973+
}
938974

939975
//TODO: Implement variable bitrate feature (which actually works). This implementation throws
940976
//invalid bitrate errors and rc buffer underflow errors, etc...

0 commit comments

Comments
 (0)