Is the Nx Cloud up? Visit our Status Page for the current health and performance of the Nx Cloud.

Status Page

Video Frame Data Is Too Small Or Null

Answered

Comments

10 comments

  • Permanently deleted user

    Hi Anton Babinov, Hi Andrey Terentyev

    Any help on this would be greatly appreciated. Sending valid JPEG images to the remote server is the most critical part of an integration that I'm working on.

    Thank you. 

    0
  • Anton Babinov
    • Network Optix team

    Hi Usama,

    diagnostic event from your screenshot indicates that the execution of function pushUncompressedVideoFrame was stoped due to the timeout. If the execution of pushUncompressedVideoFrame takes longer than 5 seconds, server generates "Method execution took too long" exception. You should try to find out what's causing this timeout in your code.

    As for the size of string_image parameter, I'm going to need some time to analyze your code sample.

    0
  • Permanently deleted user

    Hi Anton Babinov

    Thanks so much for the reply. I've actually gotten rid of the timeout issue by just pushing frame data to a queue and moving frame processing over to a different thread (which reads from the queue one-by-one).
    The data(0) problem is still there unfortunately.

    Right now I'm thinking of all the various factors that might be responsible for this problem i.e. fps, frame format, decoding etc.

    Btw, I've read that data(0) returns binary data. How would you suggest converting this binary data (stored in char*) to a base64 string without losing any bytes/data?

    Again, my objective is to send JPEG images to a remote server over HTTP and have them be properly viewable as JPEGS on the remote server.
    The remote server is written in Node.js btw, I'm using Express and Multer.

    0
  • Anton Babinov
    • Network Optix team

    I did some experiments and data() function seems to return the correct char* data. Base64 encodes 3 bytes of real data into 4 encoded bytes. As a result, the Base64 string should be longer than the original binary data. Do you see that data is cut in your remote server or inside of the plugin? I'm guessing it's possible that you're using the original datasize from the video frame and apply it to base64 encoding string, which could lead to losing about 30% of ending bytes.

    0
  • Permanently deleted user

    Hey Anton Babinov

    So I saved the file as described in this comment:
    https://support.networkoptix.com/hc/en-us/community/posts/360049554894/comments/360012722114

    It's an invalid JPEG file, can't be opened.
    I also tried saving raw YUV files with .yuv extension. We've been trying a lot to convert that to JPEG using ffmpeg, ImageMagick etc but still not luck. For example with ffmpeg we tried many different commands with different switches and parameters, for example:

    ffmpeg -y -s 640x360 -pix_fmt yuv420p -f rawvideo -vcodec rawvideo -i 3.yuv 3result1.jpeg


    Keep getting errors like this:

    [rawvideo @ 0x7fe0d900c800] Invalid buffer size, packet size 921600 < expected frame_size 1382400
    Error while decoding stream #0:0: Invalid argument
    [swscaler @ 0x7fe0d8f13000] deprecated pixel format used, make sure you did set range correctly


    But, using this website I was able to at least view the image. So the .yuv file is definitely valid.

    Again, our ultimate objective is just to get JPEG images...regardless of whether we listen for YUV420, RGB, BGR etc as defined in the engine manifest.

    Thanks.



    0
  • Anton Babinov
    • Network Optix team
    [rawvideo @ 0x7fe0d900c800] Invalid buffer size, packet size 921600 < expected frame_size 1382400

    This error usually indicate that either resolution or pixel format is wrong. Also, I can see that you're using "-vcodec rawvideo". -vcodec option sets codec for output file, so you should use either "-vcode mjpeg" or don't specify this option.

    Check this post which explains how it is possible to convert raw frame received from server via API into jpeg - https://support.networkoptix.com/hc/en-us/community/posts/1500000035622/comments/1500000028321

     

     

    0
  • Permanently deleted user

    I have used the following command but the output is not correct.
    what is the wrong with the command ?

    ffmpeg -f rawvideo -pixel_format yuvj420p -s 640x360 -i 4.yuv -frames:v 1 -c mjpeg -b:v 230400 output.jpeg

    YUV file: https://easyupload.io/braxu2
    I am getting output: 

    0
  • Anton Babinov
    • Network Optix team

    Could you please show your code that you used to save .yuv file and tell me video parameters from the original stream(codec, bitrate, resolution)? 

    0
  • Permanently deleted user

    Hey Anton Babinov

    The engine manifest defined in engine.cpp is:

    std::string Engine::manifestString() const

    {

    // Ask the Server to supply uncompressed video frames in YUV420 format (see

    // https://en.wikipedia.org/wiki/YUV).

    //

    // Note that this format is used internally by the Server, therefore requires minimum

    // resources for decoding, thus it is the recommended format.

    return /*suppress newline*/ 1 + R"json(

    {

        "capabilities": "needUncompressedVideoFrames_yuv420,

        "preferredStream" : "primary",

    "eventTypes": [

    {

    "id": ")json"+ kCalipsaEventType + R"json(",

    "name": "Calipsa Alarm"

    }

    ],

    "objectTypes": [

            {

                "id": ")json" + kCalipsaAlarmObjectType + R"json(",

                "name": "Calipsa Alarm Object"

            }

        ]

    }

    )json";

    }



    In device_agent.cpp within pushUncompressedVideoFrame(const IUncompressedVideoFrame* videoFrame) to save a file like 640x360.yuv I've written:

    const std::string outFile = "C:/" + std::to_string(videoFrame->width()) + "x" + std::to_string(videoFrame->height()) + ".yuv";
    std::ofstream frameFile;
    frameFile.open(outFile, std::ios::out);
    frameFile.write(videoFrame->data(0), videoFrame->dataSize(0));
    frameFile.close();


    We've tried with quite a few videos. Some of the parameters are:

    .mp4 video,  640x360, 23.98 fps, 609 kbps total bitrate, 483 kbps data rate, 8 seconds long
    .mp4 video, 1272x720, 24.93 fps, 5523 kbps total bitrate, 5522 kbps data rate, 6 seconds long
    .mov video, 1280x720, 30 fps, 10830 kbps total bitrate, 10612 kbps data rate, 7 seconds long
    two .mkv videos with no meta information available.

    Here are all these files zipped and uploaded:
    https://drive.google.com/file/d/1nwXJE7asNePUuFBttMfWyie3hL0Aobge/view?usp=sharing

    This is the command I execute to stream these videos to the server.
    ./testcamera.exe -I=127.0.0.1 files="hi.mkv"


    I've also tried

    needUncompressedVideoFrames_rgb
    needUncompressedVideoFrames_bgr
    needUncompressedVideoFrames_rgba

    and tried saving them with the respective extensions (.rgb, .bgr, .rgba), but no luck,

    We've kind of hit a roadblock because of this issue of JPEG conversion :)
    I would really appreciate it you could please go through these files and help us use ffmpeg (or any other tool) to do this YUV to JPEG conversion (in Node.js code actually, where we're using the fluent-ffmpeg npm package).

    I've been trying to follow the answers here as well:
    https://support.networkoptix.com/hc/en-us/community/posts/360049554894-Viewing-the-saved-frame

    0
  • Anton Babinov
    • Network Optix team

    Hi Usama,

    It's not enough to save only pixel data to the file. For example, YUV format consist of multiple planes and you need to save all of then according to the YUV specification. As a most simple example, you can use rgb frames, check my example bellow:

    1. I used your hi.mkv file and used testcamera :

     .\testcamera.exe --camera-for-file --no-secondary files="hi.mkv" --local-interface=127.0.0.1

    2. I modified Engine::manifestString() and DeviceAgent::pushUncompressedVideoFrame in sample_analytics_plugin like this:


    std::string Engine::manifestString() const
    {
    // Ask the Server to supply uncompressed video frames in YUV420 format (see
    // https://en.wikipedia.org/wiki/YUV).
    //
    // Note that this format is used internally by the Server, therefore requires minimum
    // resources for decoding, thus it is the recommended format.
    return /*suppress newline*/ 1 + (const char*) R"json(
    {
    "capabilities": "needUncompressedVideoFrames_rgb"
    }
    )json";
    }

     

    bool DeviceAgent::pushUncompressedVideoFrame(const IUncompressedVideoFrame* videoFrame)
    {
    ++m_frameIndex;
    m_lastVideoFrameTimestampUs = videoFrame->timestampUs();

    if (m_frameIndex % 60 == 0) {
    const char* outFile1 = "F:/Frames/image.rgb";
    FILE* fout = fopen(outFile1, "wb");
    fprintf(fout, "P6\n%d %d\n255\n", videoFrame->width(), videoFrame->height());
    fwrite(videoFrame->data(0), 1, videoFrame->width() * videoFrame->height() * 3, fout);
    fclose(fout);
    }

    auto eventMetadataPacket = generateEventMetadataPacket();
    if (eventMetadataPacket)
    {
    // Send generated metadata packet to the Server.
    pushMetadataPacket(eventMetadataPacket.releasePtr());
    }

    return true; //< There were no errors while processing the video frame.
    }

    As you can see, before wring frame pixel data, it is required to add rgb header, which would specify frame resolution.

    3. This allows me to store every 60th frame as rgb frame and resulted file can be converted to jpeg by any online file converter.

    0

Please sign in to leave a comment.