This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch release/9.0 in repository ffmpeg.
commit 5ee24ba241f71e05c316291d8b675c5ec4affe81 Author: Lynne <[email protected]> AuthorDate: Wed Sep 23 20:27:47 2026 +0900 Commit: James Almer <[email protected]> CommitDate: Thu Sep 24 23:20:27 2026 -0300 avcodec/opus/enc: signal silence explicitly Silent frames were coded with zero bytes, which decoders take as a lost frame and conceal by extrapolating the preceding audio, rather than outputting silence. A packet of such frames is also only one or two bytes long, and the MPEG-TS muxer rejects packets shorter than two. Code the silence flag in a two byte frame like libopus does, and keep the encoder state in sync with the decoder after it: the decoder predicts the band energies of the next frame from CELT_ENERGY_SILENCE, and the pre-emphasis filter state at the start of the next overlap is zero. As silent frames no longer have a size of zero, leave them out of the rate control explicitly. (cherry picked from commit b726a3b8c48f0945a9fbee9a308e7b22b183db5c) --- libavcodec/opus/enc.c | 11 +++++++++-- libavcodec/opus/enc_psy.c | 7 +++++-- tests/ref/fate/opus-enc-silence | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libavcodec/opus/enc.c b/libavcodec/opus/enc.c index bd48960c5e..e63293b63e 100644 --- a/libavcodec/opus/enc.c +++ b/libavcodec/opus/enc.c @@ -437,8 +437,15 @@ static void celt_encode_frame(OpusEncContext *s, OpusRangeCoder *rc, if (f->silence) { if (f->framebits >= 16) ff_opus_rc_enc_log(rc, 1, 15); /* Silence (if using explicit signalling) */ - for (int ch = 0; ch < s->channels; ch++) - memset(s->last_quantized_energy[ch], 0.0f, sizeof(float)*CELT_MAX_BANDS); + for (int ch = 0; ch < s->channels; ch++) { + /* The decoder sets all band energies to CELT_ENERGY_SILENCE on + * a silence frame, and predicts the next frame's from them. */ + for (int i = 0; i < CELT_MAX_BANDS; i++) + s->last_quantized_energy[ch][i] = CELT_ENERGY_SILENCE; + /* The frame is all zeros, so this is the pre emphasis filter state + * at the point the next frame's overlap starts */ + f->block[ch].emph_coeff = 0.0f; + } return; } diff --git a/libavcodec/opus/enc_psy.c b/libavcodec/opus/enc_psy.c index a7a1f1ff8e..7b44978f19 100644 --- a/libavcodec/opus/enc_psy.c +++ b/libavcodec/opus/enc_psy.c @@ -311,7 +311,10 @@ void ff_opus_psy_celt_frame_init(OpusPsyContext *s, CeltFrame *f, int index) f->silence = silence; if (f->silence) { - f->framebits = 0; /* Otherwise the silence flag eats up 16(!) bits */ + /* Explicitly signal silence in a 2 byte frame, like libopus does. + * A zero length frame would instead signal a lost frame to decoders, + * which conceal it by extrapolating the preceding audio. */ + f->framebits = 16; f->intensity_stereo = f->end_band; /* Read by postencode_update for avg_is_band */ return; } @@ -546,7 +549,7 @@ void ff_opus_psy_postencode_update(OpusPsyContext *s, CeltFrame *f) for (i = 0; i < s->p.frames; i++) { s->avg_is_band += f[i].intensity_stereo; - if (f[i].framebits > 0) + if (!f[i].silence && f[i].framebits > 0) s->lambda *= ideal_fbits / f[i].framebits; } diff --git a/tests/ref/fate/opus-enc-silence b/tests/ref/fate/opus-enc-silence index dd8e02e02d..37f039f1f4 100644 --- a/tests/ref/fate/opus-enc-silence +++ b/tests/ref/fate/opus-enc-silence @@ -4,5 +4,5 @@ #codec_id 0: opus #sample_rate 0: 48000 #channel_layout_name 0: stereo -0, -120, -120, 960, 1, 0x00fc00fc -0, 840, 840, 168, 1, 0x00fc00fc, S=1, Skip Samples, 10, 0x009f001b +0, -120, -120, 960, 3, 0x05f002f9 +0, 840, 840, 168, 3, 0x05f002f9, S=1, Skip Samples, 10, 0x009f001b -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
