Ask Your Question
0

VideoCapture.retrieve() memory access violation

asked 2013-03-26 18:53:37 -0500

Aggieboy gravatar image

updated 2013-03-27 03:38:19 -0500

I am attempting to store all of the frames of a video in a "std::vector<\cv::Mat>" (a very common goal across many forums I've found). The issue is that when I call VideoCapture::read(), or more specifically VideoCapture::retrieve(), I get a memory access violation. Here's my attempt so far:

#pragma once
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

class Video : public std::vector<cv::Mat>{
public:
    //Constructors
    Video(std::string name){ open(name); }
    Video(){}

    //OpenCV C++ version, BROKEN
    size_t open(std::string name){ 
        cv::VideoCapture source(name);
        clear();
        if(source.isOpened()){
            cv::Mat grabbed;
            //while(source.read(grabbed)){
            while(source.grab()){
                source.retrieve(grabbed); // <------ BROKEN LINE
                std::cout << "Frame Parsed: " << source.get(CV_CAP_PROP_POS_FRAMES) << std::endl;
                push_back(grabbed);
            }
            source.release();
        }
        return size(); 
    }
};

In my frustration, I've also tried the C implementation, which has the same exception at cvQueryFrame().

//OpenCV C version, BROKEN
size_t open(std::string name){
    clear();
    CvCapture* capture = cvCaptureFromAVI((char*)name.c_str()); // read AVI video
    if(capture){
        IplImage* img;
        int frameNum=0;
        while(true){
            img=cvQueryFrame( capture ); // <------- BROKEN LINE: 
            if(!img) break;
            std::cout << "Frame Parsed: " << frameNum++ << std::endl;
            cv::Mat m(img);
            push_back(m);
        }
    }
    return size();
}

I assume the C++ implementation uses C commands, so I guess it's to be expected. I was just hoping that this may provide more debug information. The closest issue that I've found is here, however his solution was a linkage problem; I've already made sure to provide opencv_**243d.dll in the project properties.

Additional information: 64-bit Windows, Visual Studio C++ 2010 Express (Compiling Win32 Debug mode, don't care about Release), OpenCV2.4.3 (as noted from the dlls). The actual exception is:

An unhandled exception of type 'System.AccessViolationException' occurred in MyProject.exe Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Finally, you just need this to test the code itself (of course, replace "HeadDemo.avi with whatever video you want that's in the same directory):

#include "video.h"

using namespace cv;
using namespace std;

int main(){
    Video v("HeadDemo.avi");
    return 1;
}

Edit: Forgot to mention that if you comment out the problem lines, the code works fine but the vector is filled with empty cv::Mat for each frame since the data was only grabbed and never retrieved.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2013-03-27 03:02:27 -0500

berak gravatar image

updated 2013-03-27 03:03:24 -0500

the frames you retrieve from VideoCapture point to device driver memory. if you want to store them in a vector , you need to clone() them, else they will get overwritten/corrupted.

it does not matter if you use cvQueryFrame() , capture.read(), or capture >> mat, they are all calling the same code internally.

vector<Mat> vec;
while(cap.isOpened())
{
    cap >> frame;
    vec.push_back( frame.clone() );
}

also see the note here

edit flag offensive delete link more

Comments

But I'm getting the memory access violation during the read, not during the push_back(). I can comment out the push_back() and still get the exception. Additionally, push_back() should run a copy constructor with "const Mat&" type as the input, although I'd have to double check (might be different depending on how they implemented it, but they should have the copy construction run clone()).

Aggieboy gravatar imageAggieboy ( 2013-03-27 03:20:41 -0500 )edit
1

1.: it doesn't matter, where it's crashing. if you don't clone(), you get undefined behaviour

2.: the copy constructor won't save you, as it's doing a shallow copy only ( they still share the pixels ) again : clone() or crash!

berak gravatar imageberak ( 2013-03-27 03:38:43 -0500 )edit

Here is an example of the code that I'm using. Am I misunderstanding your solution?

Aggieboy gravatar imageAggieboy ( 2013-03-27 13:46:14 -0500 )edit
1

don't think so. but 0xc0000005 is likely to happen when mixing debug/release exe/libs, or 64bit/32bit, please check that as well ( though it sounds paranoid .. )

berak gravatar imageberak ( 2013-03-27 14:49:54 -0500 )edit
1

Well I figured out the answer, but this website won't let me answer my own question. If you post this for me, I can choose it as an answer. I wanted to test your hypothesis concerning the 0xc0000005 exception. I compiled my OpenCV library natively (I was using a prebuilt solution perviuosly) and found that the problem was caused by this. One way to fix the project is to downgrade to OpenCV2.1, but a workaround can be found with this using VirtualDub to re-compress your video using a native windows dll rather than OpenCV's ffmpeg (or at least that's how I understand it).

Aggieboy gravatar imageAggieboy ( 2013-03-27 16:36:11 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2013-03-26 18:53:37 -0500

Seen: 4,180 times

Last updated: Apr 11 '13