MFC+DuiVision结合VLC播放器开发直播客户端

说明:windows 10 VS2015社区版

关键字:c++ VisualStudio DuiVision VLC播放器

开发这个视频播放器的需求很简单:实现远程直播视频查看。实时点播、直播,VLC可以搭建一个直播客户端,然后再基于VLC开发视频播放器客户端查看直播视频。本文只涉及到客户端看直播的功能所涉及到的开发方法,没有过深的讲解直播等技术。

Duivision

参照官网说明,duivision是基于DirectUI技术开发,DirectUI一般是指将所有的界面控件都绘制在一个窗口上,这些控件的逻辑和绘图方式都必须自己进行编写和封装,而不是使用Windows控件,所以这些控件都是无句柄的。
DirectUI技术需要解决的主要问题如下:

  • 窗口的子类化,截获窗口的消息
  • 封装自己的控件,并将自己的控件绘制到该窗口上
  • 封装窗口的消息,并分发到自己的控件上,让自己的控件根据消息进行相应和绘制
  • 根据不同的行为发送自定义消息给窗口,以便程序进行调用
  • 一般窗口上控件的组织使用XML来描述

通常DirectUI的界面库都采用XML配置文件+图片+控制脚本(Lua、Javascript等)的开发方式,非常类似于Web程序的开发方式,当然这里面控制脚本也可以直接使用C++代码来实现。这种开发方式可以大大提高开发效率,将程序员从繁琐的界面工作中解脱出来,并且通过美工的设计,可以使界面更美观
DuiVision开源下载地址
源码目录结构

其中使用源码中的DuiVision文件夹中的内容,其中包含08、10、13、15版本的工程,使用的时候根据自己的VS选择工程引入。

打开VS创建自己的MFC工程,选择MFC应用程序,选择“基于对话框”和使用Unicode库,其他默认,创建之后将IDE生成的按钮和控件删除,只保留一个什么都没有的干净的对话框。其中部分如图:


然后一路“下一步”或者直接finish创建空白的MFC工程,创建结果如图(将默认生成的控件删除):

然后引入DuiVision,即前文说到的源代码中的DuiVision文件夹。先将DuiVision拷贝到工程目录中:

然后,在VS中:右键Solution->add->existingProject找到DuiVison工程

当前VS是15版,所以选择DuiVision.2015.vcxproj
根据以下图配置项目的资源:

AdditionLibrary Directories 是DuiVision文件夹中Lib文件夹,我将其复制到项目根目录下所以值是../Lib;

(下图含有vlc字样的lib是后面将说到的vlc播放器要用到的)

然后将程序exe生成位置改为项目根目录下的bin目录,这是DuiVision程序的一个要求(控件等xml位置位于项目的EXE目录下)。

到此,使用DuiVision开发界面的环境搭建完毕,接下来进行界面开发。
界面使用XML开发,如觉得开发麻烦可以直接将源代码案例中的xml、skins以及plugins文件夹拷贝到工程的bin目录下

在xml文件夹中的resource.xml文件类似程序的主界面的入口,在其中定义界面的按钮、背景、文字以及加载的控件等资源,以及程序中使用到的全局变量。
官方说明官方开发文档传送门

A 编写界面

基于 DuiVision 界面库的程序,需要有一个默认的资源定义 XML 文件,此文件默认的位置是exe 文件所在路径下的 xml\resource.xml 文件,如果使用了 zip 压缩文件来保存所有资源文件,则此文件的位置是在压缩包中的 xml\resource.xml 文件。此文件中可以定义程序的全局配置、XML 文件、字体、图片、文字等资源。

<!—这是手册中定义的图片资源-->
<res type="img" name="IDB_MAIN_FRAME" file="skins\WindowsBack.png" />
<res type="img" name="IDB_BT_CLOSE" file="skins\BT_CLOSE.png" />
<res type="img" name="IDB_BT_MIN" file="skins\BT_MIN.png" />
<res type="img" name="IDB_BT_MENU" file="skins\BT_MENU.png" />
<res type="img" name="IDB_BT_SKIN" file="skins\BT_SKIN.png" />
<res type="img" name="IDB_TAB_1" file="skins\Tab1.png" />
<res type="img" name="IDB_TAB_2" file="skins\Tab2.png" />
<res type="img" name="IDB_ICON_INFO" file="skins\info.png" />
<res type="img" name="IDB_ICON_WARN" file="skins\warning.png" />
<res type="img" name="IDB_ICON_ERROR" file="skins\error.png" />
<res type="img" name="IDB_MENU_UPDATE" file="skins\MENU_UPDATE.png" />

其中name属性的值可以在其他xml文件和c++代码中使用。
界面中要使用的元素、控件均在resource.xml文件中引用,比如界面的主窗口均定义在type=”xml”的元素中:

B 编写c++代码

界面编写完了之后就是在VS工程中引用和使用界面的时候了。
在主程序的 App 类 InitInstance()函数中添加 DuiVision 库的引用代码,示例代码如下:

// 初始化DuiVision界面库,可以指定语言,dwLangID为表示自动判断当前语言
// 1116是Demo程序的应用程序ID,每个DUI应用程序应该使用不同的ID
// ID主要用于进程间通信传递命令行时候区分应用
// IDD_DUIVISIONDEMO_DIALOG是工程中创建的那个对话框资源ID,所有窗口都是共用此ID的
// 第三个参数可以指定资源文件名,如果不指定默认使用xml\resource.xml的定义进行资源的加载,资源文件名的定义方式参考下面的说明
DWORD dwLangID = 0;
new DuiSystem(m_hInstance, dwLangID, _T("DuiVisionDemo.ui"), 1116,
IDD_DUIVISIONDEMO_DIALOG, "");
// 创建主窗口,dlg_main即在上文resource.xml文件中,res元素中type=”xml”,name=”dlg_main”中的dlg_main
CDlgBase* pMainDlg = DuiSystem::CreateDuiDialog(_T("dlg_main"), NULL, _T(""), TRUE);
// 给主窗口注册事件处理对象
CDuiHandlerMain* pHandler = new CDuiHandlerMain();
pHandler->SetDialog(pMainDlg);
DuiSystem::RegisterHandler(pMainDlg, pHandler);
// 初始化提示信息窗口
DuiSystem::Instance()->CreateNotifyMsgBox(_T("dlg_notifymsg"));
// 按照非模式对话框创建主窗口,可以设置为默认隐藏
pMainDlg->Create(pMainDlg->GetIDTemplate(), NULL);
//pMainDlg->ShowWindow(SW_HIDE);
INT_PTR nResponse = pMainDlg->RunModalLoop();
// 如果是按照模式对话框运行主窗口,只要改为如下代码就可以
//INT_PTR nResponse = pMainDlg->DoModal();
// 释放DuiVision界面库的资源
DuiSystem::Release();

界面创建之后,现在为界面添加响应事件。除了界面的描述之外,最主要的工作就是业务逻辑的处理,为了将业务逻辑和界面展示能够更好的分离,DuiVision 中定义了事件处理基类,所有的业务逻辑都应该写在派生的事件处理类中,并把事件处理对象注册到相应的对话框或控件上,这样对应的子控件有事件需要处理的时候,就会自动调用注册的事件处理对象的相应函数。事件处理类只要在处理函数中根据控件的 ID 或名字决定该做什么事情,写相应的处理代码就可以。事件处理类中同时提供了一些函数方便根据 ID 或名字获取到对应的控件对象,并对控件进行操作,例如改变控件文字、获取控件的某个状态等。事件处理基类是 CDuiHandler,这个类的定义如下,提供了获取控件对象、设置控件的一些参数的函数,方便在事件处理类中对控件的操作:

class CDuiHandler{public:CDuiHandler(void);virtual ~CDuiHandler(void);LRESULT OnDuiMsgNotifyButton1 (UINT uID, CString strName, UINT Msg, WPARAM wParam, LPARAM lParam);protected:CDuiObject* m_pDuiObject; // 关联的DUI对象//消息处理定义,notify_button_1为xml文件中button的name值,BUTTOM_UP为DuiVision定义的事件名称,OnDuiMsgNotifyButton1这为自己编写的BUTTOM_UP事件的响应代码。DUI_DECLARE_MESSAGE_BEGIN(CDuiHandlerMain)DUI_CONTROL_NAMEMSG_MESSAGE(L"notify_button_1",BUTTOM_UP, OnDuiMsgNotifyButton1)DUI_DECLARE_MESSAGE_END()
};

对以上代码在cpp文件中的实现:

先include包含以上代码的.h文件,然后写如下代码:
LRESULT CDuiHandlerMain::OnDuiMsgMsgBoxButton1(UINT uID, CString strName, UINT Msg, WPARAM
wParam, LPARAM lParam)
{
DuiSystem::DuiMessageBox(NULL, _T("演示对话框!"));
return TRUE;
}

此程序的功能是鼠标点击一个名叫“notify_button_1”的按钮,当鼠标离开按钮时,弹出一个对话框。

VLC创建播放器窗口

将vlc视频播放器结合到MFC DuiVision 程序中
到VLC官网下载播放器并安装,安装后使用安装目录下的libvlc.dlllibvlccore.dll,将两个库拷贝放到工程的Lib目录下,并修改工程的属性配置中添加引用到这两个库,参考前文引用DuiVision.2015d.lib (项目属性->linker->input->additional Dependencies的步骤)。此外还需要include vlc的一些开发代码,在当前(2016年11月11日)我下载的播放器中没有找到,所以我打包作为附加资源放在文后。
使用播放器就很简单了,直接上测试代码:

    LRESULT doCennectionHandler(UINT uID, CString strName, UINT Msg, WPARAM wParam, LPARAM lParam);LRESULT disCennectionHandler(UINT uID, CString strName, UINT Msg, WPARAM wParam, LPARAM lParam);LRESULT doPrintScreenHandler(UINT uID, CString strName, UINT Msg, WPARAM wParam, LPARAM lParam);public:CPoint          m_ptControlImageNormal;CDuiFlashCtrl*  m_flash;CStatic *       m_pFlashPlayer;UINT_PTR        m_playerTimer;libvlc_instance_t * inst;libvlc_media_player_t * player;libvlc_media_t * media;libvlc_time_t   m_TotalTime;DUI_DECLARE_MESSAGE_BEGIN(CDuiMainHandler)DUI_CONTROL_NAMEMSG_MESSAGE(L"button.connect", MSG_BUTTON_UP, doCennectionHandler)DUI_DECLARE_MESSAGE_END()LRESULT CDuiMainHandler::doCennectionHandler(UINT uID, CString strName, UINT Msg, WPARAM wParam, LPARAM lParam)
{if (player != NULL) {libvlc_media_player_release(player);}inst = libvlc_new(0, NULL);media = libvlc_media_new_location(inst, "rtp://192.168.31.109:5004");player = libvlc_media_player_new_from_media(media);libvlc_media_release(media);HWND hw = m_pFlashPlayer->GetSafeHwnd();libvlc_media_player_set_hwnd(player, hw);//此处应先使用CStatic动态创建一个控件,获取句柄,因为官网说到duivsion创建的控件是没有句柄的,所以,这里为了将VLC播放器指定到duivision窗口中,CStatic * m_pFlashPlayer->Create(_T(""), WS_CHILD | WS_VISIBLE , CRect(50, 55, 790, 535), m_pDlg, 12345);libvlc_media_player_play(player);m_TotalTime = libvlc_media_player_get_length(player);return true;
}

当点击button.connect按钮之后,就能播放192.168.31.109:5004的视频了。
额,对于这个播放地址,使用VLC播放器发送的直播流,可以自己使用vlc播放器搭建一个本地的视屏直播源就行。对于其它操作,可以之间查看vlc源代码。Done!


附加资源:VLC开发库

MFC+DuiVision结合VLC播放器开发直播客户端相关推荐

  1. 基于VLC的播放器开发

    VLC的C++封装 因为工作需要,研究了一段时间的播放器开发,如果从头开始做,可以学习下FFmpeg(http://www.ffmpeg.org/),很多播放器都是基于FFmpeg开发的,但是这样工作 ...

  2. VLC播放器Demo(录像,截图等功能),Android播放器Demo可二次开发。ffmpeg-Kit (录像,截图,合流播放,合流推送,等一些列视频操作功能),可二次开发。

    VLC播放器Demo(录像,截图等功能),可二次开发. ffmpeg-Kit (录像,截图,合流播放,合流推送,等一些列视频操作功能),可二次开发. 如果帮助的到了您,请您不要吝啬你的Star,先谢谢 ...

  3. Wpf开发VLC播放器(万能播放器)

    一.在VLC官网下载最新的VLC播放器,然后安装,安装后在安装文件目录中分别把文件VideoLAN\VLC\和VideoLAN\VLC\plugins\拷贝到项目中. \VLC文件夹中包括\plugi ...

  4. 设置VLC播放器进行RTSP推流桌面(共享桌面)

    设置VLC播放器进行RTSP推流桌面(共享桌面) 一.推流与拉流概念 二.设置推流端 三.设置拉流端(播放端) VLC官网:https://www.videolan.org/ 一.推流与拉流概念 首先 ...

  5. 设置VLC播放器进行RTSP推流视频

    设置VLC播放器进行RTSP推流视频 一.推流与拉流概念 二.设置推流端 三.设置拉流端(播放端) VLC官网:https://www.videolan.org/ 一.推流与拉流概念 首先,做几个名词 ...

  6. (转)关于VLC 播放器

    最近比较忙,忙来忙去也不知道干了些什么 一直在了解 VLC 播放器方面的东西,目标是实现一个基于 VLC 的 Client , 来播放 RTP / RTSP 的流媒体. 下面是我对这东西的个人理解,写 ...

  7. 使用vlc播放器做rtsp流媒体服务器

    可参考: 使用vlc播放器播放rtsp视频 web网页中使用vlc插件播放相机rtsp流视频 使用vlc进行二次开发做自己的播放器 首先需要安装vlc播放器,下载及安装步骤略 使用vlc播放器做rts ...

  8. 关于vlc播放器的ActiveX控件调用问题

    下了好几个版本的vlc播放器,却发现vlc播放器自带的ActiveX插件除了初始化能用之外,后面的js接口完全用不了 从1.0.5版本之后的ActiveX无法调用第一版的js接口 从2.0.5版本之后 ...

  9. linux下和嵌入式linux下通过udp接收来自vlc播放器的视频并转发播放

    1.最近需要在linux下基于udp写一个应用程序,实现接收vlc播放器发送的视频流,并将接收到的视频流转发到另一个vlc客户端播放.并将这个应用程序交叉编译到ARM上执行测试通过.主机端ip地址:1 ...

最新文章

  1. 办理房贷前,名下信用卡必须全部还清吗?
  2. LazyInitializationException--由于session关闭引发的异常
  3. 简述TCP/IP四层体系结构及每层作用
  4. Mutual and feedback(互评与反馈)
  5. Python全栈开发之并发编程
  6. 织梦内核风吟导航QQ导航天下网址管理源码
  7. 数组实例的copyWithin()方法
  8. 人工智能综述性论文_人工智能论文研读:深度学习算法与架构综述(包含详细统计表)...
  9. ASP.NET三层架构的优点和缺点
  10. php汉字转拼音 字库型
  11. MSF(Metaspolit)复现MS12-020蓝屏漏洞
  12. 有趣的c语言代码大全,分享一段有趣的小代码
  13. C语言设计模式——简单工厂模式
  14. DoS攻击、CC攻击的攻击方式和防御方法
  15. c语言中字符型char数据在内存中占,互联网常识:在c语言中char型数据在内存中的储存形式为什么...
  16. vue中使用AntV G6 — 基础篇
  17. python绘制等边三角形的代码_python 打印直角三角形,等边三角形,菱形,正方形的代码...
  18. 高通SIMLOCK研究
  19. “下一代智能硬件Web应用防火墙”——创宇盾X完成统信互认
  20. 淘特(淘宝特价版)关键词搜索

热门文章

  1. 爆肝两万字,我爷爷都看的懂的《栈和队列》,建议各位观众姥爷先收藏
  2. 夫妻一方以婚前存款等个人财产在婚后购置的房屋或者其他财产,是否属于夫妻共同财产?
  3. Java——Web后端学习路线
  4. 浏览器出现500 Internal Privoxy Error
  5. tree view android,AndroidTreeView
  6. ALEXA排名机制(转)
  7. 雷击和高压Hipot
  8. Java函数知识大全
  9. [转载]浅谈电视剧《武林外史》之白飞飞_-刘艳红-_新浪博客
  10. 电脑最大支持多少内存是指什么意义?