使用VLC imem从存储器播放h264视频文件,但是接收到错误“主流错误:不能预填充缓冲器". [英] Using VLC imem to play an h264 video file from memory but receiving error "main stream error: cannot pre fill buffer"

查看:695
本文介绍了使用VLC imem从存储器播放h264视频文件,但是接收到错误“主流错误:不能预填充缓冲器".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个h264视频文件已加载到内存中,我尝试使用参数"imem-cat = 4"与imem播放,以便vlc将使用访问模块对视频进行解复用,然后vlc启动并成功接收我的imem参数:

I have an h264 video file that is loaded into memory, and I attempt to play it with imem using the parameter "imem-cat=4" so that vlc will use an access module to demux the video, and vlc starts and receives my imem parameters successfully:

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

此类别也意味着我不必提供DTS和PTS. VLC的imem模块没有充分的文档记录,但是我在几个地方都找到了提示,例如

This category also means I don't have to provide DTS and PTS. The imem module for VLC isn't well documented, but I've found hints in several places e.g.

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

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

使用libVLC从python的内存中播放视频

我的imem-get函数只是在第一次调用时将缓冲区指针设置为视频数据,返回0,在以后的调用中,它返回1表示没有更多数据:

My imem-get function simply sets the buffer pointer to the video data on the first call, returning 0, on any further calls it returns 1 to indicate that there is no more data:

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;
}

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

Unfortunately after the first call I receive the following errors:

[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), release(0x404e91), 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), release(0x404e91), data(0x7ffe0da3b940), 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无法访问视频数据,但是错误消息不是很有用,通常是指网络流而不是内存位置.

For some reason it seems vlc cannot access the video data, but the error messages aren't very helpful and normally refer to network streams rather than memory locations.

有人通过这种方式成功使用了imem还是对可能的问题有任何想法?视频可以从磁盘完美地在VLC中播放. 感谢您的帮助.

Has anyone successfully used imem in this way or have any ideas as to what the problem could be? The video plays in VLC perfectly from disk. Thanks for any help.

看来项目界面可能实际上不支持这种方式的播放.但是,libVLC提供了libvlc_media_t和livblc_media_new_callbacks,它们可以使我实现自己想要的目标.如果可以,我会报告.

It looks like the item interface may not actually support playing in this way. However, libVLC provides libvlc_media_t and livblc_media_new_callbacks which may allow me achieve what I want. I'll report back if I get it working.

推荐答案

所以我无法使Imem正常工作,但是在VLC论坛上,我指向的是3.0.0版中可用的新API.我必须删除当前安装的vlc和libvlc-dev,并将VLC的每日构建PPA添加到Ubuntu安装中,然后再安装这些版本.

So I couldn't get Imem to work, however on the VLC forums I was pointed towards a new API available in version 3.0.0. I had to remove my current installs of vlc and libvlc-dev and add the VLC daily builds PPA to the Ubuntu install, then install those versions.

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视频.

You must implement each of those callbacks to give VLC access to the in-memory stream. Although the documentation states that implementing the seek() callback is unnecessary, I couldn't get h264 video to play without it.

open()回调函数应将指针传递给您的视频数据,我建议使用一个容器类,以便您可以存储沿其读取的最后一个字节的索引.

The open() callback should pass a pointer to your video data, I recommend a container class so you can store the index of the last byte read along side it.

read()回调用于将len个字节读取到传递指针的缓冲区中.在这里,您可以将len个字节或更少的字节写入缓冲区,并返回复制的字节数,阻塞直到准备好一些字节为止,EOF返回0,错误返回-1.

The read() callback is used to read len bytes into a buffer for which a pointer is passed. Here you can write len or less bytes to the buffer and return the number of bytes copied, block until you have some bytes ready, return 0 for EOF or -1 for error.

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

The seek() callback is used to set the byte index at which the next read() will take place.

最后close()不返回任何内容,用于整理内容.

Finally close() doesn't return anything and is used to tidy up.

以下是read()实现的示例:

Here is an example of a read() implementation:

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;
}

此处要求提供一个Open回调的示例:

As requested here is an example of an Open callback:

int VideoPlayer::memVideo_open(void* opaque, void** datap, uint64_t* sizep)
{
   //cast opaque to our video state struct
   MemVideoData *mVid = static_cast<MemVideoData*> (opaque);    

   //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;
}

这篇关于使用VLC imem从存储器播放h264视频文件,但是接收到错误“主流错误:不能预填充缓冲器".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆