【问题标题】:Get frame from video with libvlc smem and convert it to opencv Mat. (c++)使用 libvlc smem 从视频中获取帧并将其转换为 opencv Mat。 (c++)
【发布时间】:2014-05-30 08:26:42
【问题描述】:

[更新了部分答案]
这是我的代码:

void cbVideoPrerender(void *p_video_data, uint8_t **pp_pixel_buffer, int size) {
    // Locking
    imageMutex.lock();
    videoBuffer = (uint8_t *)malloc(size);
    *pp_pixel_buffer = videoBuffer;
}  
void cbVideoPostrender(void *p_video_data, uint8_t *p_pixel_buffer
      , int width, int height, int pixel_pitch, int size, int64_t pts) {
   // Unlocking
   imageMutex.unlock();
   Mat img = Mat(Size(width,height), CV_8UC3, p_pixel_buffer);
   //cvtColor(img,img,CV_RGB2BGR);
}
int main(int argc, char ** argv)
{
   libvlc_instance_t * inst;
   char smem_options[1000];
   sprintf(smem_options
      , "#transcode{vcodec=RV24}:smem{"
         "video-prerender-callback=%lld,"
         "video-postrender-callback=%lld,"
         "video-data=%lld,"
         "no-time-sync},"
      , (long long int)(intptr_t)(void*)&cbVideoPrerender
      , (long long int)(intptr_t)(void*)&cbVideoPostrender //This would normally be useful data, 100 is just test data
      , (long long int)200 //Test data
      );
    const char * const vlc_args[] = {
              "-I", "dummy", // Don't use any interface
              "--ignore-config", // Don't use VLC's config
              "--extraintf=logger", // Log anything
              "--verbose=1", // Be verbose
              "--sout", smem_options // Stream to memory
               };

    // We launch VLC
    inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
...
return 0;
}

问题已更新
我检查了我的两个回调函数似乎正确执行。
_RV32究竟输出什么样的数据?它是否适合 CV_8U3C(此处需要无符号 8 位 int 3 通道? _我需要在我的 Mat 类中添加一个步骤吗? (步骤 - 每个矩阵行占用的字节数)
UPDATED2
我将 RV32 更改为 RV24,这更有意义。我添加了 cvtColor,因为 Mat 矩阵似乎需要 BGR 像素而不是 RGB,但图像仍然无法正确显示。
_是否有一个 vcodec 可以给我一个 YUV 格式作为输出,这样我就可以在尝试输出 opencv::Mat img 之前测试像素数据?
[EDIT OUTPUT IMG](通过更改 vlc输入 CV_8UC4 四通道(不知道为什么)我们几乎可以看到框架,但质量真的很差,为什么会这样?
[解决方案]
我发现我视频开头的图像质量很差,这就是为什么我的 Mat imshow() 向我展示了这么丑陋的东西,上面的代码现在应该可以工作了(显然不需要 cvtColor)

【问题讨论】:

  • afaik,像素在 p_pixel_buffer 中,而不是在 p_video_data 中。另外,unlock() 不应该在 设置 Mat 的像素之后执行吗?
  • 我也有这个想法,但是如何将我的像素数组提供给 Mat 构造函数?
  • 以同样的方式,你现在就做。只需更改 varnames
  • 忍耐一下,我上次使用 vlc 已经很久了(也没有使用 smem),但我必须用libvlc_video_set_format( mp, "RV24", W,H, W * 3 );明确指定 rgb 格式>
  • 好的,我更改了像素缓冲区指针,没有更多致命错误,但图像输出真的很奇怪(黑色带有一些彩色点我现在将尝试使用格式)

标签: c++ opencv image-processing libvlc mat


【解决方案1】:

首先,快速警告:从 VLC2.2(当前 git 版本,即将发布)开始,size 参数是一个 size_t。 没有 smem 的 API(还没有?希望这会改变),这很糟糕,所以这会默默地破坏你的应用程序。

然后,快速评论一下“数据”参数:它应该包含您进行处理所需的内容。那是一个指向结构的指针,一个类的实例,你可以命名它。 我强烈怀疑通过 long long 是否可以在 32 位机器上工作,因为你会在只能包含 32 位的东西中强制使用 64 位。 您应该做的是声明一个结构,并将您需要的内容存储到其中。在这里,一个很好的例子可能是:

struct MyParamStruct
{
    YourMutexType imageMutex; // Here mutex is not a global variable anymore
    int otherParam; // You can use this to store the value 200 that you were passing before
};
//...

// Init the struct somewhere
MyParamStruct* param = new MyStructParam;
param->otherParam = 200;
//...

sprintf(smem_options
      , "#transcode{vcodec=h264}:smem{"
         "video-prerender-callback=%lld,"
         "video-postrender-callback=%lld,"
         "video-data=%lld,"
         "no-time-sync},"
      , (long long int)(intptr_t)(void*)&cbVideoPrerender
      , (long long int)(intptr_t)(void*)&cbVideoPostrender //This would normally be useful data, 100 is just test data
      , (long long int)(intptr_t)(void*)param
      );

关于互斥锁的使用,我觉得不错。实际上,您似乎在这里没有任何并发​​问题,因为您为每个帧同步分配了一个新缓冲区。如果您每次都使用预先分配的缓冲区,则需要在退出 postrender 函数时考虑锁定。

事实上,我什至不确定 void 指针 p_video_data 到底是什么。

这取决于您的图像格式。对于 H264,它将取决于解码器输出的像素格式。由于您要求的是 H264 输出,因此您很可能会获得平面像素格式,但具体类型取决于您的 H264 配置文件。

如果您期望结果是 rawdata(似乎是这种情况,因为 CV_8UC3 似乎指的是 3 通道原始图像,在快速浏览 google 之后),我建议您切换到 RV32: #transcode{vcodec=RV32}

你需要传递给转码模块的是你的输出fourcc,VLC会为你处理输入:)

更新

我不知道 Mat 类是否拥有您的指针的所有权,但您可能也想检查一下。

更新 2

回答您关于什么是 RV32 的进一步问题:

/* 24 bits RGB */
#define VLC_CODEC_RGB24           VLC_FOURCC('R','V','2','4')
/* 24 bits RGB padded to 32 bits */
#define VLC_CODEC_RGB32           VLC_FOURCC('R','V','3','2')
/* 32 bits RGBA */
#define VLC_CODEC_RGBA            VLC_FOURCC('R','G','B','A')

如果您只期望 3 个字节,那么您可能应该尝试 RV24! 我可能应该从一开始就建议,因为 8CU3 肯定只建议 3 个字节......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-25
    • 2012-03-04
    • 2016-07-07
    • 2020-04-27
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多