1、项目背景:前端
因为一个项目的附加部分,客户要求实现一个关于视频流媒体的方面内容,并且没有经费,且作为项目的附加条款,采购现成的系统,因为经费的问题,不太现实,因此上到开源社区寻找视频流媒体方面的开源项目,通过一番比较,选中了EasyDarwin。c++
2、布署服务器端git
下载了服务器端的编译版本直截在本地的Linux服务器上进行了布署。为了方便启动服务器,写了一个脚本。github
#!/bin/bash #file name start_easydarwin_server.sh sudo ~/EasyDarwin-CentOS-x64-7.0.3-Build15.1130/easydarwin -c ~/EasyDarwin-CentOS-x64-7.0.3-Build15.1130/easydarwin.xml -d
运行后,结果以下:c#
[janl@svr1 sh]$ ./start_easydarwin_server.sh [sudo] password for janl: WARNING: No module folder exists. INFO: Module Loaded...QTSSFileModule [static] INFO: Module Loaded...QTSSReflectorModule [static] INFO: Module Loaded...EasyRelayModule [static] INFO: Module Loaded...EasyHLSModule [static] INFO: Module Loaded...QTSSAccessLogModule [static] INFO: Module Loaded...QTSSFlowControlModule [static] INFO: Module Loaded...QTSSPosixFileSysModule [static] INFO: Module Loaded...QTSSAdminModule [static] INFO: Module Loaded...QTSSMP3StreamingModule [static] INFO: Module Loaded...QTSSAccessModule [static] WARNING: No users file found at ./qtusers. WARNING: No groups file found at ./qtgroups. Streaming Server done starting up
到这服务器端就能运行了。bash
3、实现我须要的客户端:服务器
先看一下最后的运行结果:tcp
从官方下载了EasyClient,这个没有编译好的版本,直截下载了源码,在Win7 x64下用VS2013编译。函数
值得注意的一点是,源生下截的代码EasyClient在编译时会报错,提示找不libmp4creator,通过群主帮忙指点,其实工具
libmp4creator在下边的EasyPlayer项目中就有,直截Copy到EasyClient项目中就能够了。
后面一切顺利,编译成功,后运行EasyClient能够用了。
4、实现自已想要的客户端:
EasyClient客户端虽然不错,可是并非我能够交付给客户的东西,因此实现自已的客户端就成为主要难点。
EasyClient是用C++编写的,而我对C++并不熟,凭着多年工做经验,只能看懂个大概,最优的方案就是调用EasyClient类库,前端界面用C#从新实现。
废话很少说了,本着从最容易的着手,就从EasyPlayer着手,从EasyClient目录,Copy了libEasyPlayer.dll及其它动态库,新建了c#项目,解决方案。
第一个要解决的是,导出函数的定义,在c#中导入libEasyPlayer.dll的API导出函数,这里不得不说,EasyPlayer的做者把EasyPlayer的导出函,封装的很清晰:
typedef int (CALLBACK *MediaSourceCallBack)( int _channelId, int *_channelPtr, int _frameType, char *pBuf, RTSP_FRAME_INFO* _frameInfo); LIB_EASYPLAYER_API int EasyPlayer_Init(); LIB_EASYPLAYER_API void EasyPlayer_Release(); LIB_EASYPLAYER_API int EasyPlayer_OpenStream(const char *url, HWND hWnd, RENDER_FORMAT renderFormat, int rtpovertcp, const char *username, const char *password, MediaSourceCallBack callback=NULL, void *userPtr=NULL); LIB_EASYPLAYER_API void EasyPlayer_CloseStream(int channelId); LIB_EASYPLAYER_API int EasyPlayer_SetFrameCache(int channelId, int cache); LIB_EASYPLAYER_API int EasyPlayer_SetShownToScale(int channelId, int shownToScale); LIB_EASYPLAYER_API int EasyPlayer_SetDecodeType(int channelId, int decodeKeyframeOnly); LIB_EASYPLAYER_API int EasyPlayer_SetRenderRect(int channelId, LPRECT lpSrcRect); LIB_EASYPLAYER_API int EasyPlayer_ShowStatisticalInfo(int channelId, int show); LIB_EASYPLAYER_API int EasyPlayer_SetDragStartPoint(int channelId, POINT pt); LIB_EASYPLAYER_API int EasyPlayer_SetDragEndPoint(int channelId, POINT pt); LIB_EASYPLAYER_API int EasyPlayer_ResetDragPoint(int channelId); LIB_EASYPLAYER_API int EasyPlayer_StartManuRecording(int channelId); LIB_EASYPLAYER_API int EasyPlayer_StopManuRecording(int channelId); LIB_EASYPLAYER_API int EasyPlayer_PlaySound(int channelId); LIB_EASYPLAYER_API int EasyPlayer_StopSound();
导入到c#的代码中,具体就是如这个样子。
/// Return Type: int [System.Runtime.InteropServices.DllImportAttribute("libEasyPlayer.dll", EntryPoint = "?EasyPlayer_Init@@YAHXZ")] //[DllImport("libEasyPlayer.dll", EntryPoint = "EasyPlayer_Init", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] public static extern int EasyPlayer_Init(); /// Return Type: void [System.Runtime.InteropServices.DllImportAttribute("libEasyPlayer.dll", EntryPoint = "?EasyPlayer_Release@@YAXXZ")] public static extern void EasyPlayer_Release();
这里我要提到一个工具,叫Invoke Interop Assistant 这个工具能够帮我将C++的头件,转换为c#的导入代码就是上边的代码,这个工具我是在CSDN上下载的,不过有点遗憾的是,最复杂而且带回调函数的EasyPlayer_OpenStream,没法自动生成,工具报了一个错误,具体错误信息是:
Error: Error processing procedure EasyPlayer_OpenStream: Expected token of type ParenClose but found ParenOpen instead.
我在Baidu上查了一下,没有什么有效的解决办法,并且我也没有弄清 ParenClose 与ParenOpen是否c++的专用术语或是什么,导出函出的定义方式,总之问题没有解决。EasyPlayer_OpenStream 和 回调函数 只好手动来码。
若是谁知道是怎么回事,必定要告诉我一下。
完成的导入函数以下,超长了,贴不上来,我一会传到群空吧。
程序的调试过程遇到两个问题要提醒注意一下:
1. 找不到动态库,明明libEasyPlayer.dll就在可执行目录,系统提示找不到。通过尝试后我把项目编译配置由AnyCPU改成X86后终于再也不报找不到动态库了。
2. 提示找不动态库的入口点,这个把我郁闷坏了,明明比较和定义同样,就是提示找不到入口点,后来实在没办法了,只好上看雪下了一个Dll导出表查看器,具体的名字叫ExportList,有图有真相啊!
看到第一行那个函数符号了吗? 我想多是由于编译字符集或者是什么缘由引发的吧,照这个定义就能找到入口点了。
若是你有更好的办法,请不要忘记告诉我一声。
看到你们找不到这个源码给个人留言,我首先感谢你们,让我知道这个东西仍是有一点点用。
为了方便你们,我把源码整理了一下,放到了github上,以方便你们下载。
对于给我留言,须要发源码的朋友,我由于时间有限就不给你们一一回邮件了,请你们到github上去下载吧,在此报歉了。下载地址:
https://github.com/janl99/EasyClient.Net.git