使用 VLC imem 从内存播放 h264 视频文件但收到错误“主流错误:无法预填充缓冲区”

2024-03-25

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

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

此类别还意味着我不必提供 DTS 和 PTS。 VLC 的 imem 模块没有很好的文档记录,但我在几个地方找到了提示,例如

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

在 python 中使用 libVLC 从内存中播放视频 https://stackoverflow.com/questions/19602790/play-video-using-libvlc-from-memory-in-python

我的 imem-get 函数只是在第一次调用时将缓冲区指针设置为视频数据,返回 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), 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 似乎无法访问视频数据,但错误消息不是很有帮助,并且通常指的是网络流而不是内存位置。

有没有人以这种方式成功使用 imem 或者对问题可能是什么有任何想法?该视频可以在 VLC 中完美地从磁盘播放。 谢谢你的帮助。

Edit

看起来物品界面实际上可能不支持这种方式播放。然而,libVLC 提供了 libvlc_media_t 和 livblc_media_new_callbacks ,这可以让我实现我想要的。如果我能正常工作,我会报告。


所以我无法让 Imem 工作,但是在 VLC 论坛上,有人向我指出了 3.0.0 版本中提供的新 API。我必须删除当前安装的 vlc 和 libvlc-dev,并将 VLC 每日构建 PPA 添加到 Ubuntu 安装中,然后安装这些版本。

API 是libvlc_media_new_callbacks https://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__media.html#ga591c3cbe56444f1949165b2b9b75d8e2:

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 或更少的字节写入缓冲区并返回复制的字节数,阻塞直到有一些字节准备好,对于 EOF 返回 0 或对于错误返回 -1。

eek() 回调用于设置下一次 read() 发生的字节索引。

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

以下是 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) bytesToCopy = len;   //at least as many bytes remaining as requested
  else if (bytesRemaining < len) bytesToCopy = bytesRemaining;    //less that requested number of bytes remaining
  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 回调的示例:

int VideoPlayer::memVideo_open(void* opaque, void** datap, uint64_t* sizep)
{
   //TODO: get mutex on MemVideoData object pointed to by opaque
   MemVideoData *mVid = static_cast<MemVideoData*> (opaque); //cast opaque to our video state struct
   *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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 VLC imem 从内存播放 h264 视频文件但收到错误“主流错误:无法预填充缓冲区” 的相关文章

随机推荐

  • TinyMCE客户端验证问题

    我在使用 TinyMCE 编辑器时遇到问题 我的表单带有很少的文本字段和文本区域 tinymce 并启用了客户端验证 当我单击 保存 按钮时 所有文本字段都会进行验证 但需要单击两次才能验证tinymce内容 此外 验证仅在字段为空或条件不
  • 异步 ServiceController.WaitForStatus 如何执行?

    So ServiceController WaitForStatus https msdn microsoft com en us library system serviceprocess servicecontroller waitfo
  • 如何将javascript变量值分配给php变量[重复]

    这个问题在这里已经有答案了 我已经宣布了JavaScript 变量 var myJavascriptVar 12345 并且无法将该值分配给php多变的 myPhpVar myJavascriptVar 我知道 Ajax 可能可以解决我的问
  • 从现有 CXF Rest 服务生成 wadl

    我有使用 CXF 实现的工作 JAX RS 服务 如何生成 wadl 或者有类似球衣的东西吗http path to your restapp application wadl http path to your restapp appli
  • Facebook“无法从 URL 检索数据”

    当尝试对 facebook 进行图形 api 调用时 我收到以下错误 我知道我的回调 url 很好 因为当我在 facebook 调试器中测试它时 它可以很好地查看页面 我也在使用 Google App Engine 我真的认为这个错误可能
  • C++ 匿名变量

    为什么这不起作用 0 define CONCAT x y x y 1 2 define VAR LINE x 3 int CONCAT anonymous LINE x 4 5 define VAR LINE2 x 6 int anonym
  • 如何向图表添加适当的噪声

    我有一个 matlab 图表 类似轨迹的东西 我想向图表添加噪音 我尝试添加正态分布噪声 使用兰特 例如 x1 x a rand size x 对于 y 也是如此 结果附在下面 这不是我想要的 这给了我一个散点图 或者完全嘈杂的图 如下图所
  • 2D RPG 中的 XML、YAML 和 JSON [重复]

    这个问题在这里已经有答案了 我不知道对于 C 2D RPG 是否使用 XML YAML 或 JSON 这是我的想法 我需要一些简单的东西 不仅可以保存玩家数据 还可以保存环境数据 例如对象 x y 坐标 加载时间 日期 图形配置等 我需要一
  • 为什么 setLastModified(time) 对此文件不起作用?

    为什么下面代码中的文件日期没有改变 fLocal location C 中的现有文件 fLocal date 以长整型设置的日期 boolean x new File fLocal location setLastModified Long
  • 在 Ubuntu 中从 CSV 复制到 Postgres

    我的问题与此类似one https stackoverflow com q 14083311 1777654但在 Linux Mint 15 Ubuntu 中 我已经尝试过标准COPY http www postgresql org doc
  • Laravel:字符串数据,右截断:1406 数据对于列来说太长

    我有一张桌子 上面有一列 酒店 该项目是在 Laravel 5 4 中创建的 因此我使用了 Migrations table gt string hotel 50 这是 MYSQL VARCHAR 50 它运作良好 因为当我开发时 我使用了
  • Android 操作系统认为应用程序在调试期间处于断点时没有响应

    我不确定这是否是 Android studio 2 0 的问题 还是因为我正在开发的这个新应用程序中存在一些奇怪的项目设置 当我在调试期间停在断点处时 操作系统会向我显示一个对话框 指出应用程序没有响应 并让我选择等待或终止应用程序 然后过
  • 安全方法为无安全性,但不允许页面提取和文档组装

    我有一个非常奇怪的问题 我不确定问题出在哪里 我正在创建 PDF 但未设置任何安全限制或密码 当我在 Adob e Reader DC 中打开 PDF 并获取属性时 它确实将安全方法显示为 无安全 但是 文档组装和页面提取设置为不允许 PD
  • 即席查询和存储过程哪个更好? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • btree是如何存储在光盘上的?

    我知道如何在内存中实现b树 但不清楚如何在光盘中存储trie 我认为主要有两点区别 内存指针和磁盘地址之间的转换 看这个 插入新的k v项时如何拆分页面 在内存中很容易实现 Thanks 这完全取决于您使用的 DBMS 如果您想知道它是如何
  • angular-cli 库创建辅助入口点

    我正在尝试创建我认为所谓的 Angular npm 包的辅助入口点 我想要以下两个入口点 scope data service scope data service models 使用 angular cli 生成基础包生成以下结构 sco
  • linq 中的简单选择查询

    假设我有一个学生表 我想显示 ID 为 1 的学生 SELECT FROM STUDENT ST WHERE ST ID 1 这就是我在 Linq 中实现这一目标的方法 StudentQuery from r in oStudentData
  • VBA - 冒号“:”如何在带有条件的 VBA 代码中工作

    冒号运算符 是VBA中的语句分隔符 但是 有谁知道为什么前三个示例有效而第四个示例 未注释时 会产生错误 Option Explicit Public Sub TestMe If 1 1 Then Debug Print 1 If 2 2
  • 如何将 .txt 读入 Python 对象列表?

    我正在尝试使用 Python 制作纸牌游戏 下面有这个文本文件 其中包括卡 ID 卡名称 卡描述和卡生命值 1 Medusa Feel The Wraith 98 2 Gigle See Him See Him 54 3 Brozi Pin
  • 使用 VLC imem 从内存播放 h264 视频文件但收到错误“主流错误:无法预填充缓冲区”

    我有一个加载到内存中的 h264 视频文件 我尝试使用参数 imem cat 4 使用 imem 播放它 以便 vlc 将使用访问模块来解复用视频 并且 vlc 启动并接收我的 imem参数成功 0x7f38a0000e28 access