process video stream from memory buffer

前端 未结 2 818
被撕碎了的回忆
被撕碎了的回忆 2020-12-01 03:47

I need to parse a video stream (mpeg ts) from proprietary network protocol (which I already know how to do) and then I would like to use OpenCV to process the video stream i

相关标签:
2条回答
  • 2020-12-01 04:23

    Code to do similar to the above, for opencv 4.2.0 is on: https://github.com/jcdutton/opencv Branch: 4.2.0-jcd1

    Load the entire file into RAM pointed to by buffer, of size buffer_size. Sample code:

    VideoCapture d_reader1;
    d_reader1.open_buffer(buffer, buffer_size);
    d_reader1.read(input1);
    

    The above code reads the first frame of video.

    0 讨论(0)
  • 2020-12-01 04:38

    I had a similar need recently. I was looking for a way in OpenCV to play a video that was already in memory, but without ever having to write the video file to disk. I found out that the FFMPEG interface already supports this through av_open_input_stream. There is just a little more prep work required compared to the av_open_input_file call used in OpenCV to open a file.

    Between the following two websites I was able to piece together a working solution using the ffmpeg calls. Please refer to the information on these websites for more details:

    http://ffmpeg.arrozcru.org/forum/viewtopic.php?f=8&t=1170

    http://cdry.wordpress.com/2009/09/09/using-custom-io-callbacks-with-ffmpeg/

    To get it working in OpenCV, I ended up adding a new function to the CvCapture_FFMPEG class:

    virtual bool openBuffer( unsigned char* pBuffer, unsigned int bufLen );
    

    I provided access to it through a new API call in the highgui DLL, similar to cvCreateFileCapture. The new openBuffer function is basically the same as the open( const char* _filename ) function with the following difference:

    err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
    

    is replaced by:

    ic = avformat_alloc_context();
    ic->pb = avio_alloc_context(pBuffer, bufLen, 0, pBuffer, read_buffer, NULL, NULL);
    
    if(!ic->pb) {
        // handle error
    }
    
    // Need to probe buffer for input format unless you already know it
    AVProbeData probe_data;
    probe_data.buf_size = (bufLen < 4096) ? bufLen : 4096;
    probe_data.filename = "stream";
    probe_data.buf = (unsigned char *) malloc(probe_data.buf_size);
    memcpy(probe_data.buf, pBuffer, probe_data.buf_size);
    
    AVInputFormat *pAVInputFormat = av_probe_input_format(&probe_data, 1);
    
    if(!pAVInputFormat)
        pAVInputFormat = av_probe_input_format(&probe_data, 0);
    
    // cleanup
    free(probe_data.buf);
    probe_data.buf = NULL;
    
    if(!pAVInputFormat) {
        // handle error
    }
    
    pAVInputFormat->flags |= AVFMT_NOFILE;
    
    err = av_open_input_stream(&ic , ic->pb, "stream", pAVInputFormat, NULL);
    

    Also, make sure to call av_close_input_stream in the CvCapture_FFMPEG::close() function instead of av_close_input_file in this situation.

    Now the read_buffer callback function that is passed in to avio_alloc_context I defined as:

    static int read_buffer(void *opaque, uint8_t *buf, int buf_size)
    {
        // This function must fill the buffer with data and return number of bytes copied.
        // opaque is the pointer to private_data in the call to avio_alloc_context (4th param)
        
        memcpy(buf, opaque, buf_size);
        return buf_size;
    }
    

    This solution assumes the entire video is contained in a memory buffer and would probably have to be tweaked to work with streaming data.

    So that's it! Btw, I'm using OpenCV version 2.1 so YMMV.

    0 讨论(0)
提交回复
热议问题