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