将 libVLC 视频渲染到 QWidget 中
在用 libVLC 播放视频时,会默认显示一个 Direct3D output 窗口。这个窗口不太美观,而且也没办法做一些定制,所以在绝大多数情况下都需要禁用(或者隐藏)它,好将视频渲染到我们自己的窗口中。
在 libVLC 中,要实现这个功能并不难,只要调用平台相关的接口,并将媒体播放器和窗口句柄传递进去就可以了,这样媒体播放器就会把视频呈现到该窗口上。
1
主要接口
一定要区分开下面这几个接口,因为在不同平台上(Windows/Linux/Mac OS)调用的不一样:
好在它们的参数几乎是一样的,就拿适用于 Windows 平台的接口来说,函数原型是这样的:
void libvlc_media_player_set_hwnd ( libvlc_media_player_t *p_mi, void *drawable );
其中,p_mi 就是我们的媒体播放器,而 drawable 是一个可绘制的窗口句柄(即:最终要显示视频的那个窗口)。对于 Qt 来说,它可以是一个普通的 QWidget,也可以是一个 QLabel,或者其他一些可用于显示的部件。
2
实现方式
在 Qt 中,几乎所有的 GUI 程序都使用 QApplication(控制台程序使用 QCoreApplication),它的作用是管理 GUI 程序的控制流和主要设置:
int main(int argc, char *argv[])
{
const char * rtspMrl = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov";
QApplication app(argc, argv);
接下来,创建 libVLC 媒体环境,具体解释见《最简单的 libVLC 播放器》:
libvlc_instance_t *instance;
libvlc_media_player_t *player;
libvlc_media_t *media;
// 创建 libvlc 实例、媒体、播放器
instance = libvlc_new(0, nullptr);
media = libvlc_media_new_path(instance, localMrl);
player = libvlc_media_player_new_from_media(media);
到了最关键的一步 - 创建一个 QWidget,并将其传递给 VLC,然后显示该窗口并进行播放:
// 创建一个窗口,用于显示视频
QWidget widget;
widget.resize(600, 400);
WId currentWId = widget.winId();
// 设置视频输出窗口
#if defined (Q_OS_WIN)
libvlc_media_player_set_hwnd(player, (void *)currentWId);
#elif defined (Q_OS_UNIX)
libvlc_media_player_set_xwindow(player, currentWId);
#elif defined(Q_OS_MAC)
libvlc_media_player_set_nsobject(player, (void *)currentWId);
#endif
// 将窗口显示出来
widget.show();
// 播放
libvlc_media_player_play(player);
调用 exec() 进入主事件循环。Qt 会接受并处理用户和系统的事件,并将它们传递给适当的部件:
int retVal = app.exec();
最后,在程序退出之前,记得释放资源:
// 释放资源
libvlc_media_release(media);
libvlc_media_player_release(player);
libvlc_release(instance);
return retVal;
}
和之前的代码相比,这里的改动并不算大。除了加了一些 Qt 的东西之外,主要就是使用了一些条件语句,根据特定的宏来区分不同的操作系统,这样我们的程序就能够跨平台了。
注意:这里用到的 RTSP 是一个测试地址,并不能保证随时有效。倘若无法播放,请更换为可用的地址。
3
测试程序
迫不及待了,运行看看效果吧(网络流稍慢,稍等片刻):
哇~,简直棒极了!
·END·