mirror of
https://github.com/opencv/opencv.git
synced 2026-09-25 04:09:57 +03:00
videoio(ffmpeg): guard seek() against AV_NOPTS_VALUE start_time
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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e0cb212451
commit
7de7f882d3
@@ -2321,6 +2321,8 @@ void CvCapture_FFMPEG::seek(int64_t _frame_number)
|
||||
|
||||
AVStream* st = ic->streams[video_stream];
|
||||
int64_t time_stamp = st->start_time;
|
||||
if (time_stamp == AV_NOPTS_VALUE_) // same guard as dts_to_sec(): without it the target is INT64_MIN + offset,
|
||||
time_stamp = 0; // av_seek_frame() lands at position 0 and the loop below decodes every frame
|
||||
double time_base = r2d(st->time_base);
|
||||
int64_t ts_norm = (int64_t)(sec / time_base + 0.5);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user