(cfg: crate::codec::EncoderCfg, i444: bool)
| 49 | |
| 50 | impl EncoderApi for VpxEncoder { |
| 51 | fn new(cfg: crate::codec::EncoderCfg, i444: bool) -> ResultType<Self> |
| 52 | where |
| 53 | Self: Sized, |
| 54 | { |
| 55 | match cfg { |
| 56 | crate::codec::EncoderCfg::VPX(config) => { |
| 57 | let i = match config.codec { |
| 58 | VpxVideoCodecId::VP8 => call_vpx_ptr!(vpx_codec_vp8_cx()), |
| 59 | VpxVideoCodecId::VP9 => call_vpx_ptr!(vpx_codec_vp9_cx()), |
| 60 | }; |
| 61 | let mut c = unsafe { std::mem::MaybeUninit::zeroed().assume_init() }; |
| 62 | call_vpx!(vpx_codec_enc_config_default(i, &mut c, 0)); |
| 63 | |
| 64 | // https://www.webmproject.org/docs/encoder-parameters/ |
| 65 | // default: c.rc_min_quantizer = 0, c.rc_max_quantizer = 63 |
| 66 | // try rc_resize_allowed later |
| 67 | |
| 68 | c.g_w = config.width; |
| 69 | c.g_h = config.height; |
| 70 | c.g_timebase.num = 1; |
| 71 | c.g_timebase.den = 1000; // Output timestamp precision |
| 72 | c.rc_undershoot_pct = 95; |
| 73 | // When the data buffer falls below this percentage of fullness, a dropped frame is indicated. Set the threshold to zero (0) to disable this feature. |
| 74 | // In dynamic scenes, low bitrate gets low fps while high bitrate gets high fps. |
| 75 | c.rc_dropframe_thresh = 25; |
| 76 | c.g_threads = codec_thread_num(64) as _; |
| 77 | c.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; |
| 78 | // https://developers.google.com/media/vp9/bitrate-modes/ |
| 79 | // Constant Bitrate mode (CBR) is recommended for live streaming with VP9. |
| 80 | c.rc_end_usage = vpx_rc_mode::VPX_CBR; |
| 81 | if let Some(keyframe_interval) = config.keyframe_interval { |
| 82 | c.kf_min_dist = 0; |
| 83 | c.kf_max_dist = keyframe_interval as _; |
| 84 | } else { |
| 85 | c.kf_mode = vpx_kf_mode::VPX_KF_DISABLED; // reduce bandwidth a lot |
| 86 | } |
| 87 | |
| 88 | let (q_min, q_max, b) = Self::convert_quality(config.quality); |
| 89 | if q_min > 0 && q_min < q_max && q_max < 64 { |
| 90 | c.rc_min_quantizer = q_min; |
| 91 | c.rc_max_quantizer = q_max; |
| 92 | } else { |
| 93 | c.rc_min_quantizer = DEFAULT_QP_MIN; |
| 94 | c.rc_max_quantizer = DEFAULT_QP_MAX; |
| 95 | } |
| 96 | let base_bitrate = base_bitrate(config.width as _, config.height as _); |
| 97 | let bitrate = base_bitrate * b / 100; |
| 98 | if bitrate > 0 { |
| 99 | c.rc_target_bitrate = bitrate; |
| 100 | } else { |
| 101 | c.rc_target_bitrate = base_bitrate; |
| 102 | } |
| 103 | // https://chromium.googlesource.com/webm/libvpx/+/refs/heads/main/vp9/common/vp9_enums.h#29 |
| 104 | // https://chromium.googlesource.com/webm/libvpx/+/refs/heads/main/vp8/vp8_cx_iface.c#282 |
| 105 | c.g_profile = if i444 && config.codec == VpxVideoCodecId::VP9 { |
| 106 | 1 |
| 107 | } else { |
| 108 | 0 |
nothing calls this directly
no test coverage detected