Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is random video seeks with OpenCV slow?

Seeking to random points in a video file with OpenCV seems to be much slower than in media players like Windows Media Player or VLC. I am trying to seek to different positions on a video file encoded in H264 (or MPEG-4 AVC (part10)) using VideoCapture and the time taken to seek to the position seems to be proportional to the frame number queried. Here's a small code example of what I'm trying to do:

import cv2

cap = cv2.VideoCapture('example_file')   

frame_positions = [200, 400, 8000, 200000]
for frame_position in frame_positions:
   cap.set(cv2.cv.CV_CAP_PROP_FRAMES, frame_position)
   img = cap.read()
   cv2.imshow('window', img)
   cv2.waitKey(0)

The perceived times for when the images are displayed from above are proportional to the frame number. That is, frame number 200 and 400, barely have any delay, 8000 some noticeable lag, but 200000 would take almost half a minute.

Why isn't OpenCV able to seek as "quickly" as say Windows Media Player? Could it be that OpenCV is not using the FFMPEG codecs correctly while seeking? Would building OpenCV from sources with some alternate configuration for codecs help? If so, could someone tell me what the configuration could be?

I have only tested this on Windows 7 and 10 PCs, with OpenCV binaries as is, with relevant FFMPEG DLLs in system path.

Another observation: With OpenCV (binaries) versions greater than 2.4.9 (Example 2.4.11, 3.3.0), the first seek works, but not the subsequent ones. That is, it can seek to frame 200 from above example, but not to 400 and the rest; the video just jumps back to frame 0. But since it works for me with 2.4.9, I'm happy for now.

like image 535
Aravind Battaje Avatar asked Feb 16 '18 16:02

Aravind Battaje


People also ask

How do you speed up videos on OpenCV?

To change the playback speed you need to declare variable and use it as a parameter in waitKey function. Alternatively, as frame decoding is the most time consuming task you can move it to the second thread and use a queue of decoded frames.

How much delay we need to insert into a video based on the frames per second of the video?

At 60 frames per second, each frame lasts 1/60 of a second, which equals ~16.7 milliseconds, meaning 1.5 frames of latency at 60 fps is ~25ms.


2 Answers

GPU acceleration should not matter for seeking, because you are not decoding frames. In addition, even if you were decoding frames, doing so on the GPU would be slower than on the CPU, because your CPU nowadays has video codecs "soldered" into the chip, which makes video decoding very fast, and there would have to be some book-keeping to shovel data from main memory into the GPU.

It sounds like OpenCV implements a "safe" way of seeking: Video files can contain stream offsets. For example, your audio stream may be set off against your video stream. As another example, you might have cut away the beginning of a video and saved the result. If your cut did not happen precisely at a key frame, video editing software like ffmpeg will include a small number of frames before your cut in the output file, in order to allow the frame at which your cut happened to be decoded properly (for which the previous frames might be necessary). In this case, too, there will be a stream offset.

In order to make sure that such offsets are interpreted the right way, that is, to really hit exactly the desired frame relative to "time 0", the only "easy", but expensive way is to really eat and decode all the video frames. And that's apparently what openCV is doing here. Your video players do not bother about this, because everyday users don't notice and the controls in the GUI are anyway much to imprecise.

I might be wrong about this. But answers to other questions and some experiments I conducted to evaluate them showed that only the "slow" way of counting the frames in a video gave accurate results.

like image 67
Gereon Fox Avatar answered Oct 12 '22 09:10

Gereon Fox


It's likely because that is a very basic code example and the mentioned applications are doing something more clever.

A few points:

  • Windows Media Player has hardware acceleration
  • Windows Media Player almost definitly uses your GPU, you could try disabling this to see what difference it makes
  • VLC is an open source project so you could check out it's code to see how it does video seeking
  • VLC probably also uses your GPU
  • OpenCV provides GPU functions that will most likely make your code much quicker

If speed for seeking is important, you almost definitly want to work with the GPU when doing video operations:

https://github.com/opencv/opencv/blob/master/samples/gpu/video_reader.cpp

like image 37
GPPK Avatar answered Oct 12 '22 08:10

GPPK