微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用VLC imem从内存中播放h264video文件,但接收错误“主stream错误:不能预先填充缓冲区”

我有一个加载到内存中的h264video文件,我尝试用imem参数“imem-cat = 4”播放它,这样vlc将使用访问模块来解复用video,而vlc启动并接收我的imem成功参数:

[0x7f38a0000e28] access_imem demux debug: Using get(0x404e1d),release(0x404e91),data(0x7fff5b4a9430),cookie("IMEM")

这个类别也意味着我不必提供DTS和PTS。 用于VLC的imem模块没有很好的文档logging,但是我已经在几个地方发现了提示,例如

https://forum.videolan.org/viewtopic.PHP?t=111917

https://forum.videolan.org/viewtopic.PHP?f=32&t=93842

如何从C#中的工作线程发布UI消息

我正在C / Linux中实现printf函数

c ++:让用户进程写入LOCAL_SYstem命名pipe道 – 自定义安全描述符

CFileDialog在debugging器窗口中发布“第一次机会exception”

检测到域的连接

在python中使用内存中的libVLC播放video

我的imem-get函数只是简单地将缓冲区指针设置为第一次调用时的video数据,返回0,任何进一步的调用返回1表示没有更多的数据:

int MyImemGetCallback (void *data,const char *cookie,int64_t *dts,int64_t *pts,unsigned *flags,size_t * bufferSize,void ** buffer) { ImemData* imem = (ImemData*)data; cookie = imem->cookieString; if(imem == NULL || imem->allBuffered==true) //indicate all data has been get()ted return 1; *buffer = (void*) imem->video; bufferSize = (size_t*) &(imem->bytes); imem->allBuffered=true; return 0; }

不幸的是,在第一次通话后,我收到以下错误

[0x189cb18] main input debug: Creating an input for 'imem://' [0x189cb18] main input debug: using timeshift granularity of 50 MiB,in path '/tmp' [0x189cb18] main input debug: `imem://' gives access `imem' demux `' path `' [0x189cb18] main input debug: creating demux: access='imem' demux='' location='' file='(null)' [0x7f2808000e28] main demux debug: looking for access_demux module matching "imem": 20 candidates [0x7f2808000e28] access_imem demux debug: Using get(0x404e1d),data(0x7ffe0da3b940),cookie("h264") [0x7f2808000e28] main demux debug: no access_demux modules matched [0x189cb18] main input debug: creating access 'imem' location='',path='(null)' [0x7f2808001958] main access debug: looking for access module matching "imem": 25 candidates [0x7f2808001958] access_imem access debug: Using get(0x404e1d),cookie("h264") [0x7f2808001958] main access debug: using access module "access_imem" [0x7f2808000e28] main stream debug: Using block method for AStream* [0x7f2808000e28] main stream debug: starting pre-buffering [0x7f2808000e28] main stream error: cannot pre fill buffer [0x7f2808001958] main access debug: removing module "access_imem" [0x189cb18] main input warning: cannot create a stream_t from access [0x17d7298] main libvlc debug: removing all interfaces [0x17d7298] main libvlc debug: exiting [0x17d7298] main libvlc debug: no exit handler [0x17d7298] main libvlc debug: removing stats

出于某种原因,似乎vlc不能访问video数据,但错误信息并不是很有帮助,通常是指networkingstream而不是内存位置。

有没有人以这种方式成功地使用过imem,或者对这个问题有什么想法? video完全从磁盘播放VLC。 谢谢你的帮助。

编辑

它看起来像项目接口可能实际上不支持这种方式播放。 但是,libVLC提供了libvlc_media_t和livblc_media_new_callbacks,可以让我实现我想要的。 我会报告回来,如果我得到它的工作。

如何在Windows的特定显示器上打开窗口?

Visual Studio跳过代码

如何将标签或其他元素dynamic地添加到Windows窗体面板?

编译的C ++程序提出“不能打开共享目标文件”在另一个系统上,尽pipe该文件存在

如何连接在Visual C ++中使用lstrcat?

所以我不能让Imem工作,但是在VLC论坛上,我指出了3.0.0版本中提供了一个新的API。 我不得不删除我目前安装的vlc和libvlc-dev,并将VLC每日构建的PPA添加到Ubuntu安装中,然后安装这些版本。

API是libvlc_media_new_callbacks :

LIBVLC_API libvlc_media_t * libvlc_media_new_callbacks (libvlc_instance_t *instance,libvlc_media_open_cb open_cb,libvlc_media_read_cb read_cb,libvlc_media_seek_cb seek_cb,libvlc_media_close_cb close_cb,void *opaque)

您必须实现每个回调才能使VLC访问内存中的流。 虽然文档指出执行seek()回调是不必要的,我不能没有它的h264视频播放。

open()回调应该传递一个指向你的视频数据的指针,我推荐一个容器类,这样你可以存储最后一个字节的索引。

read()回调用于将len字节读入传入指针的缓冲区。 在这里你可以写len或者更少的字节到缓冲区并且返回复制的字节数,直到你有一些字节准备好,返回0代表EOF或者-1代表错误

seek()回调用于设置下一个read()将发生的字节索引。

最后关闭()不会返回任何东西,并用于清理。

这是一个read()实现的例子:

class MemVideoData { public: MemVideoData(char *data,int data_bytes) : video(data),bytes(data_bytes),lastByteIndex(0) {} //init ~MemVideoData() {} char* video; // pointer to video in memory int bytes; int lastByteIndex; }; ssize_t memVideo_read(void *opaque,unsigned char* buf,size_t len) { //Todo: block if not end of stream but no bytes available MemVideoData *mVid = (MemVideoData*) opaque; //cast and give context int bytesTocopy=0; int bytesSoFar = mVid->lastByteIndex; int bytesRemaining = mVid->bytes - mVid->lastByteIndex; if(bytesRemaining >= len) //at least as many bytes remaining as requested { bytesTocopy = len; } else if (bytesRemaining < len) //less that requested number of bytes remaining { bytesTocopy = bytesRemaining; } else { return 0; // no bytes left to copy } char *start = mVid->video; std::memcpy(buf,&start[mVid->lastByteIndex],bytesTocopy); //copy bytes requested to buffer. mVid->lastByteIndex = mVid->lastByteIndex + bytesTocopy; //increment bytes read count return bytesTocopy; }

按照要求这里是一个打开回调的例子:

int VideoPlayer::memVideo_open(void* opaque,void** datap,uint64_t* sizep) { MemVideoData *mVid = static_cast<MemVideoData*> (opaque); //cast and give context //Todo: get mutex on MemVideoData object pointed to by opaque *sizep = (uint64_t) mVid->bytesTotal; //set stream length *datap = mVid; /*point to entire object. Think this was intended to point to the raw video data but we use the MemVideoData object in read() and seek()*/ mVid->lastByteReadindex=0; return 0; }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐