Commit Graph
3 Commits
Author SHA1 Message Date
Isaac ConnorandClaude Opus 5.5 81fd23bdb3 fix: wait for a keyframe after flushing a full decoder_queue
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>
2026-10-31 11:14:36 -04:00
Isaac ConnorandClaude Opus 5.5 08673d0629 fix: allow for the codec's delay in the decoder_queue limit
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>
2026-10-31 11:14:10 -04:00
Nic BoetandClaude Opus 5.5 98cb2d95a7 fix: pair decoded frames with their packet by pts in Monitor::Decode()
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>
2026-10-28 20:10:37 -05:00