Why does cv::VideoWriter close with corrupt avi indices?

asked 2019-11-12 12:03:58 -0500

Vizer gravatar image

I have a thread that runs as video recorder from a capture device that produces images as cv::Mat1fon 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.

edit retag flag offensive close merge delete