I have a thread that runs as video recorder from a capture device that produces images as cv::Mat1f
on a Windows 10 64 bit system using OpenCV 3.4.3. The recorder should capture frames at a specified interval which we verify by also stamping a text file with a timestamp for each frame recorded so that we can see if we are meeting our target framerate.
The problem is that although I'll generate a video file with 120 frames which is verified by both the timestamp file and the size of the avi produced (videos are saved as raw uncompressed), all video players (vlc, ImageJ, ffmpeg) will see, for example, 56 frames. The last frame of the video's lower half or quarter is always black.
My question is does anyone know what could be causing the corruption?
The header of the avi looks a little like this:
RIFF▒S$AVI LISTl>hdrlavih8P▒▒ ▒LIST=strlstrh8vidsY800▒▒▒▒▒strf(Y800JUNK▒<00dcJUNKodmldmlh▒LISTINFOISFTLavf57.83.100JUNK▒LIST▒$movi00dc
The code for recording is this:
auto task = [this, videofilename, stampfilename, interval_ms]()
{
SetThreadPriority(GetCurrentThread(), REALTIME_PRIORITY_CLASS);
std::ofstream data(stampfilename.toStdString(), ios_base::out | ios_base::trunc);
auto fourcc = 0; // fourcc = 0 == RAW video
auto size = m_currentFrame->size();
auto fps = 1000 / interval_ms;
cv::VideoWriter video(videofilename.toStdString(), fourcc, fps, size, false);
auto lastframestamp = -DBL_MAX;
auto currentstamp = DBL_MAX;
while (m_running)
{
currentstamp = getTimeStamp();
while (currentstamp - lastframestamp < interval_ms)
{
this_thread::yield();
currentstamp = getTimeStamp();
}
lastframestamp = currentstamp;
snapCamera();
cv::Mat frame = (*m_currentFrame).clone();
frame.convertTo(frame, CV_8U, 255);
data << std::fixed << currentstamp << "\n";
video << frame;
}
video.release();
data.close();
};
snapCamera()
has a mutex, is not threaded, and uses a double Mat1f
buffer for holding the images with an iterator pointing to the current frame called m_currentFrame.