Ask Your Question
0

OpenCV: VideoCapture::get(CV_CAP_PROP_POS_MSEC ) returns 0

asked 2016-08-11 10:03:47 -0500

Yasmina gravatar image

updated 2016-08-11 10:20:46 -0500

I'm trying to timestamp the frames when recording video using OpenCV 3.1.0. However, when using VideoCapture::get(CV_CAP_PROP_POS_MSEC) to get the millisecond timestamp of the last frame grabbed the value returned is always 0.

The code I'm using:

int fps = 10;
VideoCapture cap(0); // open the default camera

cap.set(CV_CAP_PROP_FPS, fps);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 1024);

if(!cap.isOpened())  // check if we succeeded
    return -1;

Mat testFrame;
cap >> testFrame;
cap >> testFrame;
cap >> testFrame;

Size outSize = Size(testFrame.cols, testFrame.rows);

VideoWriter writer("video.avi", CV_FOURCC('M','J','P','G'), fps, outSize, true);

for(; ;)
{
    Mat frame;
    cap >> frame; // get a new frame from camera

    long stamp = cap.get( CV_CAP_PROP_POS_MSEC ); // THIS DOESN'T SEEM TO WORK

    std::cout << "Timestamp: " << stamp << std::endl;

    writer.write(frame);
}

As output I always get many lines like the following:

Timestamp: 0

Could you help me understand what I'm doing wrong?

Thanks :)

edit retag flag offensive close merge delete

Comments

A s is missing ?

long stamp = cap.get( CV_CAP_PROP_POS_M?EC ); // THIS DOESN'T SEEM TO WORK
LBerger gravatar imageLBerger ( 2016-08-11 10:17:00 -0500 )edit

Sorry, that was a typo. The property name was correctly spelled in my code. It compiled and I was able to run it. Let me edit my question to fix that.

Yasmina gravatar imageYasmina ( 2016-08-11 10:20:04 -0500 )edit

You should check return value cap.set(CV_CAP_PROP_FPS, fps); If it is false it means camera driver isn't supported. You have to use a timer or a thread to grab images and write video file

LBerger gravatar imageLBerger ( 2016-08-11 10:34:25 -0500 )edit

After executing the code I get a video file and when playing it, it looks good. I think there's no problem with the video capture itself. The problem I have is that I need to know the timestamp of each frame in that video file that is written to disk. I've tried with getting the system time, but that wasn't very accurate. Then, I got across this CV_CAP_PROP_POS_MSEC property, but I get 0 with it. Is there any reason why cap.get( CV_CAP_PROP_POS_MSEC ); might not work?

Yasmina gravatar imageYasmina ( 2016-08-11 10:58:14 -0500 )edit

I think video parameter will be good after video file is closed.You can check it after reopen it. You don't need timestamp when you write to video file because you know timestamp when you grab file.

LBerger gravatar imageLBerger ( 2016-08-11 11:37:49 -0500 )edit

That's not quite right. I need to know the exact time when the frame was capture. If I just get the system time after cap >> frame it can grab a frame from the buffer and that frame might have been capture earlier in time. I need to get as close as real time as possible. Moreover, when using that VideoCapture property from reading a video file instead of from the camera, the value return isn't the timestamp of the frame capture. Sorry, but what you suggested doesn't my problem.

Yasmina gravatar imageYasmina ( 2016-08-12 08:12:12 -0500 )edit

@Yasmina, this property simply is not supported for webcams, only for video files.

you'll have to find another way to get a timestamp.

berak gravatar imageberak ( 2016-08-13 01:42:43 -0500 )edit

@berak, is that so? I thought so when I tested it and it didn't work, but then looking at OpenCV's source code I found this "Added v4l2 support for getting capture property CV_CAP_PROP_POS_MSEC. Returns the millisecond timestamp of the last frame grabbed or 0 if no frames have been grabbed Used to successfully synchonize 2 Logitech C310 USB webcams to within 16 ms of one another". Lines 160-162 of file https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_v4l.cpp

From that I understand that if that property is used to synchronize two webcams, it must work with webcams somehow.

Yasmina gravatar imageYasmina ( 2016-08-15 03:37:57 -0500 )edit

well, you're right, i'm wrong. there is a timestamp taken. just no idea, why it isn't delivered properly.

also note, that there's cap_v4l.cpp and also cap_libv4l.cpp, and it's unclear, which one is used.

berak gravatar imageberak ( 2016-08-15 04:18:44 -0500 )edit

i have the same problem. using OpenCV 3.2. self compiled from git. @berak: its not clear which one is used but the functionality is available in both: cap_v4l.cpp https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_v4l.cpp#L159 (L159) https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_v4l.cpp#L1651 (L1651) and cap_libv4l.cpp https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_libv4l.cpp#L194 (L194) https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_libv4l.cpp#L1414 (L1414).

so this should not make a difference. it seems internally capture->FirstCapture evaluates to true all the time.. from a quick poking around in the code i could not find a cause for this... :-( edit: see my 'answer' for more research..

s-light gravatar images-light ( 2017-02-23 19:48:41 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
0

answered 2017-02-23 21:33:35 -0500

not really an answer.. more the way to eventually one..

i have tested the what happens with some debugging statements in the code: first i added some debug statements in cap_libv4l.cpp#L1414

case CV_CAP_PROP_POS_MSEC:
    if (capture->FirstCapture) {
        fprintf( stderr, "VIDEOIO INFO: V4L: CV_CAP_PROP_POS_MSEC==0 caused by capture->FirstCapture == 1");
        return 0;
    } else {
        //would be maximally numerically stable to cast to convert as bits, but would also be counterintuitive to decode
        return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
    }
    break;

and in cap_v4l.cpp#L1651

if(property_id == CV_CAP_PROP_POS_MSEC) {
    if (capture->FirstCapture) {
        fprintf( stderr, "VIDEOIO INFO: V4L2: CV_CAP_PROP_POS_MSEC==0 caused by capture->FirstCapture == 1\n");
        return 0;
    } else {
        return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
    }
}

recompiled OpenCV and tested with an simple cam viewer. found that with the current setup it is using cap_v4l.cpp - and that only the first time my debugmessage was triggerd.

so i added some some more debug output to cap_v4l.cpp L1651:

if(property_id == CV_CAP_PROP_POS_MSEC) {
    if (capture->FirstCapture) {
        fprintf( stderr, "VIDEOIO INFO: V4L2: CV_CAP_PROP_POS_MSEC==0 caused by capture->FirstCapture == 1\n");
        return 0;
    } else {
        fprintf( stderr, "VIDEOIO INFO: V4L2: CV_CAP_PROP_POS_MSEC:\n");
        fprintf( stderr, "\tcapture->timestamp.tv_sec %ld\n", capture->timestamp.tv_sec);
        fprintf( stderr, "\tcapture->timestamp.tv_usec %ld\n", capture->timestamp.tv_usec);
        return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
    }
}

with this i get

VIDEOIO INFO: V4L2: CV_CAP_PROP_POS_MSEC:
     capture->timestamp.tv_sec 0
     capture->timestamp.tv_usec 0
cv::CAP_PROP_POS_MSEC = 0

the last line comes from my app.. so the capture->timestamp contains 0. it is set in cap_v4l.cpp#L868 directly from the buffer. so it seams OpenCV does not get a timestamp information from the ioctl call back :-(

now at this point i have no idea how to go on... could be a problem in the v4l2 implementation??

edit flag offensive delete link more
0

answered 2017-05-18 09:17:17 -0500

aseyfi gravatar image

This answer seems to be related.

edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2016-08-11 10:03:47 -0500

Seen: 5,007 times

Last updated: Feb 23 '17