--- a/libavcodec/parser.c 2026-07-08 19:57:50.741008542 +0000 +++ b/libavcodec/parser.c 2026-07-08 19:58:15.847310863 +0000 @@ -200,9 +200,34 @@ } } +/* yauiclient/NextPVR: 512KiB is comfortably above the ~200-350KB + * high-water-marks observed during ordinary playback (so normal + * legitimate peaks aren't churned every time), and well below the + * 8MiB catastrophic-case resync valve in + * mpegvideo_parser_resync_valve.patch. See ff_combine_frame() below + * for full rationale. */ +#define YAUI_MPV_PARSER_SHRINK_THRESHOLD (512 * 1024) + int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) { + /* yauiclient/NextPVR: proactively shrink pc->buffer's high-water-mark + * capacity if it's grown unreasonably large. av_fast_realloc() only + * ever grows a buffer, never shrinks it - by design, to avoid realloc + * churn on the common case of similar-sized calls. But on a live + * MPEG-2 stream where mpeg1_find_frame_end()'s state machine + * occasionally needs several calls to resolve a frame boundary, each + * such episode ratchets buffer_size up a step and it never comes back + * down on its own. Only safe here, at the top of the function, when + * pc->index == 0: that means no partial-frame accumulation is + * currently in flight, so pc->buffer isn't about to be handed back + * to the caller via *buf this call. + */ + if (pc->index == 0 && pc->buffer_size > YAUI_MPV_PARSER_SHRINK_THRESHOLD) { + av_freep(&pc->buffer); + pc->buffer_size = 0; + } + if (pc->overread) { ff_dlog(NULL, "overread %d, state:%"PRIX32" next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index);