用libvlc 播放指定緩沖區中的視頻流


有時候,我們需要播放別的模塊傳輸過來的視頻流,VLC提供了這樣的機制,但一般很少這樣用,下面的例子實現了這樣的功能。

其中用到一個關鍵的模塊 imem.  vlc提供多種創建媒體的方式,如要從指定緩存中數據,可以如下方式指定

// Create a media item from file
    m = libvlc_media_new_location (inst, "imem://");   /*##use memory as input*/

下面是完整的示例

// vlcTest.cpp : 定義控制台應用程序的入口點。
//

#include "stdafx.h"
#include <Windows.h>  
#include "vlc/vlc.h"  
#include <vector>
#include <qmutex>
#include <sstream>
#include <qimage>

QMutex g_mutex;
bool   g_isInit = false;
int    IMG_WIDTH = 640;  
int    IMG_HEIGHT = 480; 
char   in_buffer[640*480*4];
char   out_buffer[640*480*4];
FILE   *local;
int    frameNum = 0;

const char*  TestFile = "b040_20170106.dat";

//////////////////////////////////////////////////////////////////////////


/**
    \brief Callback method triggered by VLC to get image data from
    a custom memory source. This is used to tell VLC where the 
    data is and to allocate buffers as needed.

    To set this callback, use the "--imem-get=<memory_address>" 
    option, with memory_address the address of this function in memory.

    When using IMEM, be sure to indicate the format for your data
    using "--imem-cat=2" where 2 is video. Other options for categories are
    0 = Unknown,
    1 = Audio,
    2 = Video,
    3 = Subtitle,
    4 = Data

    When creating your media instance, use libvlc_media_new_location and
    set the location to "imem:/" and then play.

    \param[in] data Pointer to user-defined data, this is your data that
    you set by passing the "--imem-data=<memory_address>" option when
    initializing VLC instance.
    \param[in] cookie A user defined string. This works the same way as
    data, but for string. You set it by adding the "--imem-cookie=<your_string>"
    option when you initialize VLC. Use this when multiple VLC instances are
    running.
    \param[out] dts The decode timestamp, value is in microseconds. This value
    is the time when the frame was decoded/generated. For example, 30 fps 
    video would be every 33 ms, so values would be 0, 33333, 66666, 99999, etc.
    \param[out] pts The presentation timestamp, value is in microseconds. This
    value tells the receiver when to present the frame. For example, 30 fps 
    video would be every 33 ms, so values would be 0, 33333, 66666, 99999, etc.
    \param[out] flags Unused,ignore.
    \param[out] bufferSize Use this to set the size of the buffer in bytes.
    \param[out] buffer Change to point to your encoded frame/audio/video data. 
        The codec format of the frame is user defined and set using the
        "--imem-codec=<four_letter>," where 4 letter is the code for your
        codec of your source data.
*/
int MyImemGetCallback (void *data, 
                       const char *cookie, 
                       int64_t *dts, 
                       int64_t *pts, 
                       unsigned *flags, 
                       size_t * bufferSize,
                       void ** buffer)
{
    static int64_t _dts = 0, _pts = 0;
    if (!g_isInit){
        /*load local file*/
        local = fopen(TestFile,"rb");
        if (!local){
            return true;
        }
        size_t count = fread(in_buffer,1,IMG_WIDTH*IMG_HEIGHT*4,local);
        *bufferSize = count;
        *buffer = in_buffer;
        g_isInit = true;
        *dts = _dts; *pts = _pts;
        _dts+=30; _pts+=30;
        return 0 ;
    }
    size_t count = fread(in_buffer,1,IMG_WIDTH*IMG_HEIGHT*4,local);
    *bufferSize = count;
    *buffer = in_buffer;
    *dts = _dts; *pts = _pts;
    _dts+=30; _pts+=30;
        if(count>0)   {
        printf("read %d bytes\n",count);
        return 0;
    }else{
        return true; /*eof*/
    }
}


/**
    \brief Callback method triggered by VLC to release memory allocated
    during the GET callback.

    To set this callback, use the "--imem-release=<memory_address>" 
    option, with memory_address the address of this function in memory.

    \param[in] data Pointer to user-defined data, this is your data that
    you set by passing the "--imem-data=<memory_address>" option when
    initializing VLC instance.
    \param[in] cookie A user defined string. This works the same way as
    data, but for string. You set it by adding the "--imem-cookie=<your_string>"
    option when you initialize VLC. Use this when multiple VLC instances are
    running.
    \param[int] bufferSize The size of the buffer in bytes.
    \param[out] buffer Pointer to data you allocated or set during the GET
    callback to handle  or delete as needed.
*/
int MyImemReleaseCallback (void *data, 
                           const char *cookie, 
                           size_t bufferSize, 
                           void * buffer)
{
    // Since I did not allocate any new memory, I don't need
    // to delete it here. However, if you did in your get method, you
    // should delete/free it here.
    return 0;
}

//////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])  
{  
    libvlc_instance_t * inst;  
    libvlc_media_player_t *mp;  
    libvlc_media_t *m;  

    libvlc_time_t length;   
    int wait_time=5000;  

    std::vector<const char*> options;
    std::vector<const char*>::iterator option;
    options.push_back("--no-video-title-show");

    char imemDataArg[256];
    sprintf(imemDataArg, "--imem-data=%#p", in_buffer);
    options.push_back(imemDataArg);

    char imemGetArg[256];
    sprintf(imemGetArg, "--imem-get=%#p", MyImemGetCallback);
    options.push_back(imemGetArg);

    char imemReleaseArg[256];
    sprintf(imemReleaseArg, "--imem-release=%#p", MyImemReleaseCallback);

    options.push_back(imemReleaseArg);
    options.push_back("--imem-cookie=\"IMEM\"");
    
    options.push_back("--imem-codec=H264");
    // Video data.
    options.push_back("--imem-cat=2");

    /* Load the VLC engine */  
    inst = libvlc_new (int(options.size()), options.data());  

    
    // Configure any transcoding or streaming
    // options for the media source.
    options.clear();
    

    // Create a media item from file
    m = libvlc_media_new_location (inst, "imem://");   /*##use memory as input*/

    // Set media options
    for(option = options.begin(); option != options.end(); option++){
        libvlc_media_add_option(m, *option);
    }

    /* Create a media player playing environment */  
    mp = libvlc_media_player_new_from_media (m);  


    /* No need to keep the media now */  
    libvlc_media_release (m);  
    
    
    // play the media_player  
    libvlc_media_player_play (mp);  

    //wait until the tracks are created  
    _sleep (wait_time);  
    length = libvlc_media_player_get_length(mp);  
    IMG_WIDTH = libvlc_video_get_width(mp);  
    IMG_HEIGHT = libvlc_video_get_height(mp);  
    printf("Stream Duration: %ds\n",length/1000);  
    printf("Resolution: %d x %d\n",IMG_WIDTH,IMG_HEIGHT);  
    
    //Let it play   
    _sleep (length-wait_time);

    // Stop playing  
    libvlc_media_player_stop (mp);  

    // Free the media_player  
    libvlc_media_player_release (mp);  

    libvlc_release (inst);  

    return 0;  
} 

以上代碼要注意的是: 用OPTIONS 告訴VLC , 要使用imem作為輸入,還要告訴vlc 其中用到哪些回調函數, 這個與直接設置回調的方式不一樣, 它用options中的字符串表示。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM