@@ -36,6 +36,14 @@ static int fill_ms_unlocked(const struct audio_buffer *buf)
3636 return (int )(samples * 1000 / buf -> sample_rate );
3737}
3838
39+ static size_t max_fill_bytes_unlocked (const struct audio_buffer * buf )
40+ {
41+ size_t max_fill = ms_to_bytes (buf , buf -> max_ms );
42+ if (max_fill == 0 || max_fill > buf -> capacity )
43+ max_fill = buf -> capacity ;
44+ return max_fill ;
45+ }
46+
3947/* Write raw bytes to the ring buffer (no PTS tracking). */
4048static size_t ring_write (struct audio_buffer * buf , const uint8_t * samples ,
4149 size_t bytes )
@@ -100,6 +108,53 @@ static void skip_oldest_chunk_locked(struct audio_buffer *buf)
100108 buf -> chunk_count -- ;
101109}
102110
111+ static void drop_oldest_bytes_locked (struct audio_buffer * buf , size_t bytes )
112+ {
113+ if (!buf -> data || bytes == 0 || buf -> fill == 0 )
114+ return ;
115+
116+ if (bytes > buf -> fill )
117+ bytes = buf -> fill ;
118+
119+ buf -> tail = (buf -> tail + bytes ) % buf -> capacity ;
120+ buf -> fill -= bytes ;
121+ }
122+
123+ static size_t trim_incoming_to_max_fill_locked (struct audio_buffer * buf ,
124+ const uint8_t * * samples ,
125+ size_t bytes ,
126+ int64_t * pts_ns )
127+ {
128+ size_t max_fill = max_fill_bytes_unlocked (buf );
129+ if (max_fill == 0 )
130+ return bytes ;
131+
132+ /* If a single decoded chunk is larger than the configured max,
133+ * keep only the newest tail so buffered mode does not start
134+ * several hundred milliseconds behind by construction. */
135+ if (bytes > max_fill ) {
136+ size_t skip_bytes = bytes - max_fill ;
137+ if (pts_ns && buf -> sample_rate > 0 && buf -> frame_size > 0 ) {
138+ int64_t skipped_frames =
139+ (int64_t )(skip_bytes / buf -> frame_size );
140+ * pts_ns += skipped_frames * 1000000000LL /
141+ buf -> sample_rate ;
142+ }
143+ * samples += skip_bytes ;
144+ bytes = max_fill ;
145+ }
146+
147+ while (buf -> fill + bytes > max_fill && buf -> chunk_count > 0 )
148+ skip_oldest_chunk_locked (buf );
149+
150+ if (buf -> fill + bytes > max_fill ) {
151+ size_t excess = buf -> fill + bytes - max_fill ;
152+ drop_oldest_bytes_locked (buf , excess );
153+ }
154+
155+ return bytes ;
156+ }
157+
103158/* Retire PTS chunks as data is consumed. */
104159static void pts_consume (struct audio_buffer * buf , size_t bytes_consumed )
105160{
@@ -228,6 +283,13 @@ size_t audio_buffer_write_pts(struct audio_buffer *buf, const uint8_t *samples,
228283 while (buf -> chunk_count >= AUDIO_PTS_MAX_CHUNKS )
229284 skip_oldest_chunk_locked (buf );
230285
286+ bytes = trim_incoming_to_max_fill_locked (buf , & samples , bytes ,
287+ & pts_ns );
288+ if (bytes == 0 ) {
289+ pthread_mutex_unlock (& buf -> lock );
290+ return 0 ;
291+ }
292+
231293 size_t written = ring_write (buf , samples , bytes );
232294
233295 /* Record PTS chunk metadata for every successful write. */
@@ -253,6 +315,11 @@ size_t audio_buffer_write(struct audio_buffer *buf, const uint8_t *samples,
253315 return 0 ;
254316
255317 pthread_mutex_lock (& buf -> lock );
318+ bytes = trim_incoming_to_max_fill_locked (buf , & samples , bytes , NULL );
319+ if (bytes == 0 ) {
320+ pthread_mutex_unlock (& buf -> lock );
321+ return 0 ;
322+ }
256323 size_t written = ring_write (buf , samples , bytes );
257324 pthread_mutex_unlock (& buf -> lock );
258325 return written ;
0 commit comments