When Decode() flushes the codec because decoder_queue is full (#5363),
the next packet it sent was usually not a keyframe. The flushed codec has
no reference frames to decode it against, so until the next keyframe it
returned errors or smeared pictures, which motion detection can score as
an alarm.
After the flush, hold packets back from the codec until a keyframe, as
the KEYFRAMES decoding modes already do. The held packets take the
existing path for packets that are not decoded, so last_write_time keeps
moving and zmwatch does not restart zmc.
refs #5362
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decode() flushes the codec once decoder_queue holds more than 2 x the
keyframe interval while the codec still wants input (#5363). The codec
legitimately holds frames back before returning one: has_b_frames for
reordering, and one per extra thread with frame threading. For an
all-intra stream (keyframe interval 1, so a limit of 2) decoded with a
raised thread_count that delay alone passes the limit, and the codec was
flushed every few frames with a Warning each time.
Add the delay to the limit in DecoderQueueLimit().
refs #5362
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The codec can consume packets without returning a frame for them; H.264
does after lost or corrupt slices (RTSP over UDP). Decode() paired each
frame with the oldest decoder_queue entry, so those entries stayed queued
for good: every later frame went to an older packet, and once the queue
passed 2 x the keyframe interval the throttle stopped sending while the
codec waited for input, so decoding stopped until zmwatch restarted zmc.
Match the frame to the entry with its pts and release the entries before
it with an earlier pts (decoded, no image), as the flush paths do. A frame
older than every entry is dropped; without a usable pts the oldest entry
is used, as before.
refs #4860
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>