1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

avcodec/opus/enc_psy: don't make the last frame silent at EOF

816d74e0bb made frames without psy analysis at EOF silent. The frame
that follows the last input frame to flush its MDCT overlap is always
such a frame, so the last CELT_OVERLAP samples of the stream were lost
whenever it was needed, i.e. when the length of the stream is a
multiple of frame_size or less than CELT_OVERLAP samples short of one.
It was also coded as a one byte packet, which the MPEG-TS muxer
rejects.

Encode it like any other frame instead. Its psy analysis data is
zeroed, which leaves it with the default frame parameters.

Fixes: #24196
(cherry picked from commit 2e0a770b8e)
This commit is contained in:
Lynne
2026-09-23 20:28:01 +09:00
committed by James Almer
parent 5ee24ba241
commit b135b25c19

View File

@@ -300,15 +300,6 @@ void ff_opus_psy_celt_frame_init(OpusPsyContext *s, CeltFrame *f, int index)
for (i = 0; i < steps_per_frame; i++)
silence &= s->steps[index * steps_per_frame + i]->silence;
/* If we reach EOF with fewer collected psy steps than this packet wants
* to encode, the slots beyond buffered_steps were zeroed by the previous
* postencode_update and contain no valid analysis data. Encoding garbage
* with the full rate budget can overrun the range coder buffer (rng_bytes
* exceeds the per-frame size passed to ff_opus_rc_enc_end), so force a
* silent packet instead. */
if (s->eof && step_offset >= s->buffered_steps)
silence = 1;
f->silence = silence;
if (f->silence) {
/* Explicitly signal silence in a 2 byte frame, like libopus does.
@@ -556,7 +547,9 @@ void ff_opus_psy_postencode_update(OpusPsyContext *s, CeltFrame *f)
s->avg_is_band /= (s->p.frames + 1);
s->steps_to_process = 0;
s->buffered_steps -= steps_out;
/* At EOF, one more frame than there are psy steps is encoded to flush
* the last frame's MDCT overlap */
s->buffered_steps = FFMAX(s->buffered_steps - steps_out, 0);
s->total_packets_out += s->p.frames;
s->inflection_points_count = 0;
}