Jetson TK1: OpenCV VideoWriter Not Capturing Video Frames at All

Hello,

[My Environment]

  • Jetson TK1
  • Jetpack 3.1 (Linux 4 Tegra 21.8 = Ubuntu 14.04)
  • OpenCV4Tegra 2.4.13
  • ZED SDK 1.1.1

[My Problem]
I’m encountering an issue similar to the one described here: Cannot write video frame using OpenCV VideoWriter. My code is supposed to record video, but it only outputs a 5.7KB avi file, indicating that the frames are not being captured correctly.

[My Pseudo Code]
I’ve trimmed the unnecessary code and simplified it for clarity.

// Standard includes
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>

// ZED includes
#include <zed/Mat.hpp>
#include <zed/Camera.hpp>
#include <zed/utils/GlobalDefine.hpp>

// OpenCV includes
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <ctime> // For time functions

// CUDA functions include
#include "kernel.cuh"

using namespace sl::zed;
using namespace std;

int main(int argc, char **argv) {
    // Initialize ZED camera
    Camera* zed = new Camera(HD720, 15);
    InitParams parameters;
    parameters.unit = UNIT::METER;
    ERRCODE err = zed->init(parameters);
    if (err != SUCCESS) {
        std::cerr << "Error initializing ZED camera: " << errcode2str(err) << std::endl;
        delete zed;
        return 1;
    }

    // Initialize CUDA memory
    CPU_obstacleCounts = (int*)malloc(sizeof(int) * 3);
    *CPU_obstacleCounts = 0;
    *(CPU_obstacleCounts + 1) = 0;
    *(CPU_obstacleCounts + 2) = 0;
    int* GPU_obstacleCounts;
    cudaMalloc((void**)&GPU_obstacleCounts, 3 * sizeof(int));
    cudaMemcpy(GPU_obstacleCounts, CPU_obstacleCounts, 3 * sizeof(int), cudaMemcpyHostToDevice);

    // ZED OpenCV Variables
    int width = zed->getImageSize().width;
    int height = zed->getImageSize().height;
    
    // Create and allocate GPU memory for the image matrix
    Mat imageCropp;
    imageCropp.data = (unsigned char*)nppiMalloc_8u_C4(width, height, &imageCropp.step);
    imageCropp.setUp(width, height, 4, sl::zed::UCHAR, GPU);
    
    // Create and allocate GPU memory for the mask matrix
    Mat imageCheckerboard;
    imageCheckerboard.data = (unsigned char*)nppiMalloc_8u_C4(width, height, &imageCheckerboard.step);
    imageCheckerboard.setUp(width, height, 4, sl::zed::UCHAR, GPU);
    
    // Compute the checkerboard only once; it will be used to mask the invalid area
    cuCreateCheckerboard(imageCheckerboard);

    // Create a CPU image for display purposes
    cv::Mat imDisplay(height, width, CV_8UC4);

    // Initialize VideoWriter to record video
    std::string outputVideo = "output_" + getCurrentDateTime() + ".avi"; // Output file name
    int codec = CV_FOURCC('M', 'J', 'P', 'G'); // Codec MJPEG = .avi
    int fps = 15;
    cv::VideoWriter videoWriter(outputVideo, codec, fps, cv::Size(width, height));

    if (!videoWriter.isOpened()) {
        std::cout << "Could not open the output video file for writing." << std::endl;
        return -1;
    }

    float distCut = 1.0;

    // Main processing loop
    while (true) {
        bool res = zed->grab(STANDARD);
        Mat imageLeftGPU = zed->retrieveImage_gpu(LEFT);
        Mat depthGPU = zed->retrieveMeasure_gpu(DEPTH);
        cuDetectObstacleByDepth(depthGPU, imageLeftGPU, imageCropp, imageCheckerboard, distCut, GPU_obstacleCounts);

        // Copy processed image from GPU to CPU
        cudaMemcpy2D((uchar*)imDisplay.data, imDisplay.step, (Npp8u*)imageCropp.data, imageCropp.step, imageCropp.getWidthByte(), imageCropp.height, cudaMemcpyDeviceToHost);
        cudaMemcpy(CPU_obstacleCounts, GPU_obstacleCounts, 3 * sizeof(int), cudaMemcpyDeviceToHost);

        videoWriter.write(imDisplay); // Video recording
        cv::imshow("Obstacle Display", imDisplay);
        char key = cv::waitKey(1);

        if (key == 'q' || key == 'Q') {
            std::cout << "q pressed. Breaking." << std::endl;
            break;
        }
        cudaMemset(GPU_obstacleCounts, 0, 3 * sizeof(int)); // Clear GPU data
    }
    
    std::cout << "[1] Loop exited." << std::endl;
    
    // Cleanup
    videoWriter.release(); // Release the video writer
    free(CPU_obstacleCounts);
    cudaFree(GPU_obstacleCounts);
    std::cout << "[2] Obstacle counts memory freed." << std::endl;
    imDisplay.release();
    std::cout << "[3] OpenCV Image Display released." << std::endl;
    imageCropp.deallocate();
    imageCheckerboard.deallocate();
    delete zed;
    std::cout << "[4] All dynamic memory deallocated successfully." << std::endl;
    
    return 0;
}

[What I’ve Tried]
In the code, I’ve set the codec to CV_FOURCC('M','J','P','G'). I’ve also tried other codecs like ‘XVID’, ‘DIVX’, ‘H264’, and ‘MP4V’, but they didn’t work. I installed VLC media player and the issue persisted. Additionally, I installed FFmpeg codecs using the command:

sudo apt-get install libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavl-dev libavresample-dev libavutil-dev

as suggested in this link: How to install FFmpeg on Jetson TX1, but it didn’t resolve the issue.

“sudo apt-get install ffmpeg” didn’t work.

If I could install ‘ffmpeg,’ it would solve the problem, but ‘sudo apt-get install ffmpeg’ doesn’t work. I heard that it works on other Linux distributions with ‘sudo apt-get install ffmpeg.’

Hi,
Please check if you can run gstreamer pipeline in cv2.VideoWriter(). If yes, you can try to run:

    gst_out = "appsrc ! video/x-raw, format=BGR ! queue ! videoconvert ! video/x-raw,format=I420 ! x264enc ! h264parse ! matroskamux ! filesink location=test.mkv "
cv::Mat convertedFrame;
cv::cvtColor(imDisplay, convertedFrame, cv::COLOR_BGRA2BGR); // Convert from BGRA (4 channels) to BGR (3 channels)
videoWriter.write(convertedFrame);

This codes solved the problem.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.