Moving from OpenCV 2.4 to 3.4 cvCreateFileCapture returns null

I am migrating from VS2013 to VS2017 and from OpenCV 2.4 to 3.4.
C++ MFC.
I have run the CMake on OpenCV 3.4.14 to compile with VS2017.
I have built the resulting OpenCV solution in VS2017.
I have modified the old VS2013/OpenCV project with all of the new OpenCV library and include directories and Linker Input Additional Dependencies.
I have copied all necessary OpenCV dll files to the proper places.
I have #included the new OpenCV 3.4 modules such as <opencv2/imgcodecs.hpp
I have #included the “C” files in the module sub-directories such as opencv2/videoio/videoio_c.h>
I have checked and double checked that everything is as it should be based on what it was previously but with the new references to VS2017, OpenCV 3.4.14, and to the Windows10 SDK

It compiles without problem. However when I run the code that always worked in the previous version I can’t get past getting a CvCapture for the opening .avi video in either Debug or Release mode

In the code sample below:
FILENAME is a char
capture is a CvCapture
The video file OpeningVideo.avi is in the the main directory, the \Debug, and the \Release directories. (just in case) and it is a valid video.

When I run the code below the “catch” never hits but the capture returns NULL.

try {
	// No error to catch just that capture is NULL
	capture = cvCreateFileCapture((const char*)FILENAME);
}catch (...) {
	std::string strMessage = GetLastErrorAsString();
	// Convert string to CString / Convert std::string to CString
	CString csMessage(strMessage.c_str());
	AfxMessageBox( csMessage, MB_ICONERROR);
}

I have hard coded the video file name in every configuration possible such as capture = cvCreateFileCapture("OpeningVideo.avi"); and all the way up to the full path.
As a test I did the C++ version with the code

cv::Mat frameCPP;
cv::VideoCapture captureCPP;
captureCPP.open((const char*)FILENAME);
bool bOpen = captureCPP.isOpened();  // returns true
captureCPP.read(frameCPP); // captureCPP remains NULL

Anyone have any clues? Like I said this was all running fine for a long time with VS2013 and OpenCV 2.4.7 but something that I can’t figure out has changed.

Thanks in advance.
Ed

welcome.

you really should stop using the C API. it was already “old” in OpenCV v2.x, which is no longer supported. it’s barely still there in the 3.x branch and was removed completely in 4.x.

I’m also not aware that C API should throw C++ exceptions… so your try-catch with the C API strikes me as futile.

I had to reformat your post. it was impossible to tell the code from the text.

“remains NULL”? captureCPP is the VideoCapture object. it can’t be null because there’s no pointer. it’s stack-allocated like that.

frameCPP might be .empty() but that would mean the video file was valid but empty. if it couldn’t open the video file at all, .isOpened() would have been false, but you said it is true.

you should drop the (const char*) cast.

please show how you use a full absolute path in this situation.

it would also be useful to know exactly what’s in that file, i.e. is it a real avi file or some other video container format that just accidentally has a “.avi” extension? what codecs do all the streams in the file use?

This is existing code that has a lot of the C API in it. One of the reasons that I am migrating to 3.4 instead of 4.x is that, once I have everything working in 3.4, I can slowly start editing the code to the C++ API. Once that is done then I will make the final migration to 4.x

On the try…catch, that was an exasperated attempt to try and find out what was happening. The debugger output to say that it was a “Microsoft C++ exception: cv::Exception at memory location 0x044FCE84.” but what does that mean when this is code that worked fine for years with OCV 2.4?

The captureCPP, on instantiation, says owner=NULL, stored=NULL etc. After captureCPP.open() the open() returns true.
After captureCPP.read() the captureCPP remains owner=NULL, stored=NULL etc.
Here is the whole debug Watch line for captureCPP after the read()

|▶|captureCPP|{cap={owner=0x00000000 stored=0x00000000 } icap={owner=0x03eba6d0 {owned=0x03e9e798 {ffmpegCapture=…} …} …} }|cv::VideoCapture {opencv_videoio3414d.dll!cv::VideoCapture}|

I’m not familiar with the cv::VideoCapture to know what all of the references are. For instance does icap owner indicate that everything is fine regardless of cap owner being NULL?

After captureCPP.read() the frameCPP is correct with dims=2, rows=1080 etc.

Dropping the (const char*) from the captureCPP,open() I still get a return of true and, after read() I get the captureCPP in the debugger Watch as

captureCPP = {cap={owner=0x00000000 stored=0x00000000 } icap={owner=0x0a589970 {owned=0x0a594320 {ffmpegCapture=…} …} …} }

In my C code I check for capture being NULL after the cvCreateFileCapture (actually if (!capture)). This captureCPP is different so I don’t go beyond that. The CPP was only a check and I assumed that with cap=NULL the check had failed just like the C code.

The full path that has always been used in the cvCreateFileCapture was an escaped string with a terminating NULL so it would be, in this case.
“C:\VSDTV\MDI_VSDPV\MDI_VSDPV\OpeningVideo.avi\0”
This has been the path for years and it always worked in OCV 2.4

The OpeningVideo.avi is a real video. The cvCreateVideoWriter is for CV_FOURCC(‘D’, ‘I’, ‘V’, ‘X’).

Again, this is old code that has always worked until my attempt to migrate to OCV 3.4 and VS2017. My only thought is that somewhere I missed a new library or library reassignment that happened between 2.4 and 3.4 but I have re-read the transition instructions several times and have double checked my code’s includes and project’s properties against the OCV 3.4 build and I just can’t see anything that I have missed.

The CPP code was just a test. My real concern is for the C code because the app is filled with C code and, if I can figure out what is happening here, I can possibly fix the problems that will come up once I am past this line of code. If I have to start changing everything to CPP I might as well migrate to 4.x and I don’t want to do that all at once on a project of this size.

Thanks for any help because I am lost.

PS…Before starting the transition I had copied the entire directory that contained the project and all of it’s files and put a VS2013 after the name. That left the original project open to be modified with the change in OCV includes, libraries, etc. and the VS2017 references. Other than that the only other thing that was done was the install of the Windows 10 SDK. The original project was referencing the Win 8 SDK.

I renamed the current VS2017 project directory with the VS2017 extension and renamed the original directory back to it’s original name and opened the project with VS2013. Nothing had changed here since 6/21 when I started playing with the transition other than the Win 10 SDK. Well…now the VS2013 / OCV 2.4 code comes up with the exact same capture == NULL.

Jeeeeze. It be something in the Win 10 SDK because literally nothing else (other than the installation of VS2017) has changed in the last week.

I’ll have to go back to scratch and see what happens.

PPS…Had to do a system restore to before I had installed the Win 10 SDK.
That fixed the problem with the VS2013 / OCV 2.4 version.
Re-installed Win 10 SDK 10.0.17763.0 and VS2013 / OCV 2.4 still worked but VS2017 / OCV 3.4 would still not do a cvCreateFileCapture or a C++ captureCPP.read.

So I am back where I started but at least now my original VS2013 / OCV 2.4 version is working again.

Just in case it had anything to do with Win 10 SDK 10.0.17763.0 I uninstalled that and installed Win 10 SDK 10.0.15063.468 and went into Project Properties → General and changed it there. VS2013 still works; VS2017 still does not.

So I guess I am back to asking if anyone has any clue or off the wall suggestion as to why this may be?

Thanks.

PPPS, Apparently everything works in the C++ API code even though the captureCPP returns

{cap={owner=0x00000000 stored=0x00000000 } icap={owner=0x0a589970 {owned=0x0a594320 {ffmpegCapture=…} …} …} }

I was thrown off by the owner=0x00000000 stored=0x00000000. I ran this code to verify that it was indeed working

// C++ API code
cv::Mat frameCPP;
cv::VideoCapture captureCPP;
captureCPP.open(“OpeningVideo.avi”);
bool bOpen = captureCPP.isOpened(); // true
captureCPP.read(frameCPP);

int frame_width = captureCPP.get(CV_CAP_PROP_FRAME_WIDTH); // 1920
int frame_height = captureCPP.get(CV_CAP_PROP_FRAME_HEIGHT); // 1080
int frame_rate = captureCPP.get(CV_CAP_PROP_FPS); // 23
bool success = captureCPP.retrieve(frameCPP); // true so worked;

However, the C API code still does not work.

CvCapture captureC = NULL;
captureC = cvCreateFileCapture((const char
)FILENAME); // captureC is NULL

CvCapture* captureCAVI = NULL;
captureCAVI = cvCaptureFromAVI(“OpeningVideo.avi”); // captureCAVI is NULL

I have included all of the _c.h header files>

#include <opencv2/calib3d/calib3d_c.h>
#include <opencv2/core/core_c.h>
#include <opencv2/core/types_c.h>
// no features2d_c .h file
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/imgcodecs/imgcodecs_c.h>
#include <opencv2/imgproc/imgproc_c.h>
// no video_c .h file
#include <opencv2/videoio/videoio_c.h> //

Does anyone have VS2017 or above with OpenCV 3.4.nn that they could cut and paste in these C API lines above to see if it fails for them as well. I cannot find anything that I am doing wrong or not including and yet the capture will not work with the C style call.

Thanks for any help.

Sorry, one more additional thing to add. If I follow the cvCreateFileCapture command in the Debugger all the way it finally hits the return NULL in
OpenCV_3414\opencv\sources\modules\videoio\src\videoio_c.cpp(37):
with the error

CV_LOG_WARNING(NULL, “cvCreateFileCaptureWithPreference: backend " << info.name << " doesn’t support legacy API anymore.”)

This seems to insinuate that OCV does not support C API (or at least this function) and I thought that it did. Should I try 3.0 instead? How would I know which version still supports the C API calls?

you can use git blame (github’s website also has a blame function right on there) to figure out when that warning was introduced.

or you can try specific versions and see if they still do what you need.

Trying to use git blame and, no matter what file I point it to either on my hard drive ie
c:\VSDTV\OpenCV_3414\opencv\sources\modules\videoio\src\videoio_c.cpp
or on-line ie

opencv/videoio_c.cpp at master · opencv/opencv · GitHub

I get the git blame return
fatal: not a git repository (or any of the parent directories): .git

Other than downloading files from git I am not familiare enough to know where to find the “repository” for this file. Where should I point git blame?

this does not look, like you installed it via git, and there might be no .git folder with version history in it.

but you can still use the online github version – just press b in the browser window :wink:

don’t spend too much on this. it’s a distraction anyway.

try v3.0.0 and if that doesn’t work, you’ll have to go back to v2.4.

Thanks. I tried 3.1 but it was for VS 14 (2015) only and wouldn’t CMake.
One of my main goals was the Transparent OpenCL and the notes mention that this finalized in 3.4.0 so it looks like I am stuck porting all of the OCV 2.4 code in a project that has tens of thousands of line to OCV 3.4.14.

My assumption is that if I jump to OCV 4.x, not having any C-API in it, my project wouldn’t even build until I had every line ported over. So 3.4.14 it is.

Thanks for your help.