CvCapture_FFMPEG::seek() seeds the seek target with the stream start_time
without checking for AV_NOPTS_VALUE, while dts_to_sec() right above it does
perform that check.
Some containers do not let FFmpeg establish a start time (for instance
Matroska files whose H.264 track is declared through the legacy VfW wrapper,
V_MS/VFW/FOURCC with a BITMAPINFOHEADER, instead of V_MPEG4/ISO/AVC with an
avcC record). For those, start_time is AV_NOPTS_VALUE, the computed target
becomes INT64_MIN plus an offset, and av_seek_frame() with AVSEEK_FLAG_BACKWARD
lands at position 0. The refinement loop below then decodes every single frame
up to the requested one, so every seek degrades to a linear scan. The returned
frame is correct, which makes the failure silent.
Measured on a 15 h H.264 recording (1628443 frames) with OpenCV 5.1.0-dev:
target before after
10 s 0.247 s 0.137 s
60 s 1.488 s 0.047 s
300 s 7.559 s 0.068 s
54000 s ~22 min 0.051 s
Seek cost grew strictly linearly with the target position, at roughly 25 ms
per second of video.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>