一、前言

最开始接触视频监控这块的时候,用的就是vlc作为解码的内核,主要是因为vlc使用简单方便,直接传入一个句柄即可,简单几行代码就可以实现一个视频流播放,很适合初学者使用,也推荐初学者用qt+vlc来做播放器,提供的接口还是非常友好的,而且门类特别多,想要获取媒体文件的各种信息比如宽高,设置宽高比等,直接调用接口函数传入参数就能设置。

所有用vlc做视频监控解码的人都会遇到一个问题,那就是鼠标事件被接管拦截了,不能识别鼠标事件,比如双击最大化等,这就很憋屈了,明明很好用的一个东西,怎么突然之间鼠标事件也识别不到了呢,网上一搜一大把,主要有三个解决办法。

  1. 修改vlc源码,重新编译,替换动态库文件。
  2. 全局鼠标钩子拦截鼠标消息进行处理。
  3. 设置句柄以后直接将控件/接受视频渲染的控件禁用掉。

最终采用方法3,实现起来简单快速,修改vlc源码的编译工作量太大了,毕竟vlc依赖一大堆的插件,用vlc的人一般都是初学者半吊子,哪里有能力去编译一遍vlc哦。

二、功能特点

  1. 多线程实时播放视频流和本地视频。
  2. 支持windows+linux+mac,支持vlc2和vlc3。
  3. 多线程显示图像,不卡主界面。
  4. 自动重连网络摄像头。
  5. 可设置边框大小即偏移量和边框颜色。
  6. 可设置是否绘制OSD标签即标签文本或图片和标签位置。
  7. 可设置两种OSD位置和风格。
  8. 可设置是否保存到文件以及文件名。
  9. 可直接拖曳文件到vlcwidget控件播放。
  10. 支持h265视频流+rtmp等常见视频流。
  11. 可暂停播放和继续播放。
  12. 支持回调模式和句柄两种模式。
  13. 支持线程读取进度等信息和事件回调两种处理模式。
  14. 自动将当前播放位置和音量大小是否静音以信号发出去。
  15. 提供接口设置播放位置和音量及设置静音。
  16. 支持存储单个视频文件和定时存储视频文件。
  17. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。

三、效果图

四、相关站点

  1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  5. 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652

五、核心代码

bool VlcThread::init()
{
//判断该摄像机是否能联通
if (checkConn && isRtsp) {
if (!checkUrl(url, checkTime)) {
return false;
}
} QFileInfo info(url);
suffix = info.suffix(); //设置拓展名
if (url.startsWith("dshow://")) {
suffix = "dshow";
} else if (url.startsWith("rtsp")) {
suffix = "rtsp";
} else if (url.startsWith("rtmp")) {
suffix = "rtmp";
} else if (url.startsWith("http")) {
suffix = "http";
} const char *tempArg = "";
if (suffix == "h264") {
tempArg = "--demux=h264";
} else if (suffix == "h265") {
tempArg = "--demux=h265";
} const char *vlc_args[9] = {"-I", "dummy", "--no-osd", "--no-stats", "--ignore-config", "--no-video-on-top", "--no-video-title-show", "--no-snapshot-preview", tempArg};
vlcInst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
if (vlcInst == NULL) {
return false;
} if (isRtsp || suffix == "dshow") {
vlcMedia = libvlc_media_new_location(vlcInst, url.toUtf8().constData());
} else {
//windows上需要替换文件路径
QString url = this->url;
url = QDir::toNativeSeparators(url);
vlcMedia = libvlc_media_new_path(vlcInst, url.toUtf8().constData());
} if (vlcMedia == NULL) {
return false;
} //媒体播放对象
vlcPlayer = libvlc_media_player_new_from_media(vlcMedia);
if (vlcPlayer == NULL) {
return false;
} //创建事件管理器
if (callbackevent) {
vlcEvent = libvlc_media_player_event_manager(vlcPlayer);
libvlc_event_new(vlcEvent, this);
} //回调方式和句柄方式两种分别处理
if (callback) {
callbackData = new CallbackData;
callbackData->thread = this;
callbackData->pixels = new uchar[bufferWidth * bufferHeight * 4];
memset(callbackData->pixels, 0, bufferWidth * bufferHeight * 4); int width = callbackData->thread->getBufferWidth();
int height = callbackData->thread->getBufferHeight(); //设置回调拿到每帧数据
libvlc_video_set_callbacks(vlcPlayer, lock, unlock, display, callbackData);
//设置每帧格式 RV32-Format_RGB32 RGBA-Format_RGBA8888 YUYV I420
libvlc_video_set_format(vlcPlayer, "RV32", width, height, width * 4);
} else {
//设置播放句柄
if (playWidget == NULL) {
return false;
} #if defined(Q_OS_WIN)
libvlc_media_player_set_hwnd(vlcPlayer, (void *)playWidget->winId());
#elif defined(Q_OS_LINUX)
libvlc_media_player_set_xwindow(vlcPlayer, playWidget->winId());
#elif defined(Q_OS_MAC)
libvlc_media_player_set_nsobject(vlcPlayer, (void *)playWidget->winId());
#endif //禁用句柄鼠标消息
QTimer::singleShot(1000, this, SLOT(disableHwnd()));
} //设置硬件加速 none auto any d3d11va dxva2
setOption(QString(":avcodec-hw=%1").arg(hardware));
//设置通信协议 tcp udp
setOption(QString(":rtsp-%1").arg(transport));
//设置缓存时间 默认500毫秒
setOption(QString(":network-caching=%1").arg(caching));
//:rtsp-frame-buffer-size=1000000 //设置宽度高度,本地USB摄像头需要单独设置
if (suffix == "dshow") {
setOption(QString(":dshow-size=%1*%2").arg(videoWidth).arg(videoHeight));
} else {
setSize(videoWidth, videoHeight);
} //设置保存文件
this->initSave();
//打开播放
libvlc_media_player_play(vlcPlayer); //qDebug() << TIMEMS << "init vlc finsh";
return true;
}

Qt音视频开发1-vlc解码播放的更多相关文章

  1. Android 音视频深入 三 MP4解码播放视频 (附源码下载)

    本篇项目地址,名字是媒体解码MediaCodec,MediaExtractor,求starhttps://github.com/979451341/Audio-and-video-learning-m ...

  2. Android 音视频开发(一):PCM 格式音频的播放与采集

    什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...

  3. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  4. Android音视频开发(1):H264 基本原理

    前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...

  5. Android IOS WebRTC 音视频开发总结(八十三)-- 使用WebRTC广播网络摄像头视频(上)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  6. Android IOS WebRTC 音视频开发总结(十九)-- kurento

    折腾了一个多星期终于将kurento的环境搭建好(开发阶段的产品,有些BUG要自己解决),所以单独写篇文件来介绍. 下面开始介绍kurento,文章来自博客园RTC.Blacker,转载请说明出处. ...

  7. Android WebRTC 音视频开发总结

    www.cnblogs.com/lingyunhu/p/3621057.html 前面介绍了WebRTCDemo的基本结构,本节主要介绍WebRTC音视频服务端的处理,,转载请说明出处(博客园RTC. ...

  8. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

  9. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  10. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

随机推荐

  1. go~wasm插件的开发

    Go和TinyGo是两种不同的Go语言编译器,它们之间有以下几点区别: 目标平台: Go:Go语言编译器主要面向通用计算机平台,如Windows.Linux.macOS等. TinyGo:TinyGo ...

  2. ASP.NET实现网站发布及跨域访问

    1.软件下载及安装 visual studio 2012 or 2013 启用电脑IIS配置 2.网页编写及排版 在visual studio中创建web项目添加aspx页面(个人网页:和html差不 ...

  3. 快来考试拿证书!KubeSphere 个人技能专业考试认证上线啦!

    以容器技术和容器编排为基础的云原生应用,被越来越多的企业用户接受和使用,并且在生产环境中使用容器技术的比例逐年增加.Kubernetes 无疑已经成为容器编排的事实基础,而依托于 Kubernetes ...

  4. 为你的Windows用户设置无边框半透明头像

    步骤一:锁定头像 Win+R输入gpedit.msc进入组策略编辑器,按图中所示,选择"计算机管理->管理模板->用户账户设定",将里面唯一选项"对所有账户使 ...

  5. 关于在有动态的Scroll Bar情况下页面内容的对齐问题

    关于在有动态的Scroll Bar情况下页面内容的对齐问题 问题场景 一个标题行 + 一些内容行 要求在内容行超过指定行数时 将多出的行隐藏,并展示Scroll Bar的来提示用户可以下划查看更多内容 ...

  6. (系列十)Vue3中菜单和路由的结合使用,实现菜单的动态切换(附源码)

    说明 该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发). 该系统文章,我会尽量说的非常详细,做到不管新手.老手都能看懂. 说明:OverallAuth2 ...

  7. 开源一款AI聊天工具

    学习Spring AI项目,开发一款问答工具 AI大模型请注册并生成API密钥 获取API密钥地址:https://bigmodel.cn/console/overview 开源地址:LuckyAI ...

  8. Avalonia开源控件库强力推荐-Semi.Avalonia

    Avalonia是什么? Avalonia是一个强大的框架,使开发人员能够使用.NET创建跨平台应用程序.它使用自己的渲染引擎绘制UI控件,确保在Windows.macOS.Linux.Android ...

  9. 经典强化学习算法:分层强化学习算法—options算法2(理解篇)

    论文地址: https://people.cs.umass.edu/~barto/courses/cs687/Sutton-Precup-Singh-AIJ99.pdf 例子: 这是一个寻路问题,该问 ...

  10. downloadFile:base64数据导出文件,文件下载

    function downloadFile(filename, data){ let DownloadLink = document.createElement('a'); if ( Download ...