用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中的字符串表示。

时间: 2024-08-12 03:27:51

用libvlc 播放指定缓冲区中的视频流的相关文章

使用AppleScript播放指定时间的电影片段

要在公司中分享一个电影,为了能够简单的播放一些电影的片段,使用AppleScript和MPlayerX的seekto功能来播放指定时间段的电影. tell application "Finder" open document file "xxx.mkv" of folder "Movies" of folder "vector" of folder "Users" of startup disk using

MATLAB检查指定路径中的子文件夹中的文件名中是否带有空格

测试文件夹为: clear;close all;clc; %% %程序实现的功能 %检查指定路径中的子文件夹中的文件名中是否带有空格,并去掉文件名中的空格 %% %程序中用到的之前不清楚的函数如下 %1)strfind(a,b):即找a中是否有b,如果a中有b,则输出b的位置序号.没有输出空数组 %2)isempty(a):判断数组是否为空 %3)strrep(a,b,c):就是把a中所有出现的b换为c %4)movefile(a,b):a移动为b,如C:\test1.jpg移动为C\test2

Python 可视化Twitter中指定话题中Tweet的词汇频率

CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-7-8 @author: guaguastd @name: plot_frequencies_words.py ''' if __name__ == '__main__': #import json # import Counter from collections import Counter # import search from search impor

php遍历指定目录中的内容2

输出文件是否可读写,可执行,并同时输出创建时间,修改时间,访问时间 //2.遍历指定目录中的内容 if ($arr['file']) {     $arrbyte = array("Byte","KB","MB","GB","TB","EB");     foreach ($arr['file'] as $val) {         //filetype函数返回指定文件或目录的类型  

根据包名,在指定空间中创建对象

输入描述: namespace({a: {test: 1, b: 2}}, 'a.b.c.d') 输出描述: {a: {test: 1, b: {c: {d: {}}}}} function namespace(oNamespace, sPackage) { var packageArr = sPackage.split('.'); var curObj = oNamespace; // 保留对原始对象的引用 for(var i=0, len=packageArr.length; i<len;

oracle中从指定日期中获取月份或者部分数据

从指定日期中获取部分数据: 如月份: select to_CHAR(sysdate,'MM') FROM DUAL; 或者: select extract(month from sysdate) from dual; 又或者最笨的方法.用to_char()先把日期转化为指定格式的字符串,在通过substr()这个取到想要的数据. select substr(to_char(sysdate,'yyyy-mm-dd'),6,2) from dual; 获取日期其他部分数据和上方法一样.

java统计一个子串在指定字符串中出现的次数

今天查着用了用String类里的几个方法,分享下代码 题目要求:统计一个子串在指定字符串中出现的次数( 提示java字串出现了6次) 1 public class SearchSameString { 2 3 public static void main(String[] args) { 4 // 定义俩个字符串 5 String shortStr = "java"; 6 String longStr = "javasdfjavawerjavavsswetjavadfgdf

数据库中导出表中相应字段到指定文件中

数据库中导出某一个表中需要的字段到文件中是公司中经常要做到的事,那怎么实现呢? 比如你要查询enterpriseaics中的所有字段的值到d盘的aa.txt中去,注:aa.txt不能存在,否则会报错. <span style="font-size:18px;">select * from enterpriseaics into outfile 'd:\\aa.txt' ;</span> 当然如果你想规范一下格式,例如:每个字段的值之间以逗号分开,每一行换行,每个

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(5): 返回指定表格中的所有键(key):table.keys

这里的函数主要用来做:返回指定表格中所有的键.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 返回指定表格中的所有键(key) -- example: local t = ( a = 1, b = 2, c = 3 ) local keys = table.keys( t ) -- keys = { "a", "b", "c" } -- @param t 要检查的表格(t表示是table) -- @param table