fix(codec): scale DRED duration to frame size instead of hardcoding 2
OPUS_SET_DRED_DURATION was hardcoded to 2 (20 ms), meaning DRED only covered 1/3 of a lost 60 ms frame and was useless above 20 ms channels. Now computed as max(2, ceil(frame_ms/10)) so DRED always embeds enough redundancy to reconstruct one full previous frame regardless of frame size. The floor of 2 preserves two-frame burst-loss coverage at 10 ms channels. Decoder side and server are unaffected (server relays payloads verbatim). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -46,8 +46,13 @@ bool OpusEncoder::init(const OpusParams& p) {
|
|||||||
opus_encoder_ctl(enc_, OPUS_SET_DTX(p.dtx ? 1 : 0));
|
opus_encoder_ctl(enc_, OPUS_SET_DTX(p.dtx ? 1 : 0));
|
||||||
opus_encoder_ctl(enc_, OPUS_SET_PACKET_LOSS_PERC(
|
opus_encoder_ctl(enc_, OPUS_SET_PACKET_LOSS_PERC(
|
||||||
static_cast<opus_int32>(p.expected_packet_loss)));
|
static_cast<opus_int32>(p.expected_packet_loss)));
|
||||||
// DRED: 2 × 10ms frames of redundancy covers one 20ms frame loss with ML reconstruction.
|
// DRED: embed enough redundancy to cover one full previous frame at any frame size.
|
||||||
opus_encoder_ctl(enc_, OPUS_SET_DRED_DURATION(p.dred ? 2 : 0));
|
// OPUS_SET_DRED_DURATION takes units of 10ms; ceil(frame_ms/10) ensures one complete frame
|
||||||
|
// of ML-reconstructed redundancy regardless of whether the channel runs at 10/20/40/60 ms.
|
||||||
|
// At 10ms frames this yields 1 unit (one frame back); a burst-loss floor of 2 ensures
|
||||||
|
// two consecutive 10ms frames can be recovered. Cost: ~800 bps per 10ms unit.
|
||||||
|
uint32_t dred_units = std::max(2u, (p.frame_ms + 9u) / 10u);
|
||||||
|
opus_encoder_ctl(enc_, OPUS_SET_DRED_DURATION(p.dred ? static_cast<opus_int32>(dred_units) : 0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user