最近用activeX media player做了個播放器,做過的人都知道,幾乎沒技術含量。在自己無聊的玩弄中,發現這個控件能夠解析http、ftp協議,播放互聯網的文件資源。現在被困在學校也無事可做,干脆把給這播放器寫個服務器,用來播放互聯網上的公開資源。
media player的activeX控件十分強大,只需設置正確的url即可播放本地乃至互聯網的文件資源。因此要給播放器做服務端,最重要的是向客戶端傳達正確的URL的信息。做服務器的思路便是:通過數據庫記錄下所有文件資源的信息與url,服務端讀取這些信息通過列表的形式發送給客戶端。客戶端將這些信息呈現給用戶,又用戶選擇播放的文件,之后將相應的url傳達給播放控件,由播放控件自動向url對應的服務器發起文件請求實現播放。
綜上所述,服務端只需要完成數據庫存儲,與客戶端傳輸文件信息,以及與播放器傳輸文件數據即可。為了簡化開發,我們這里的文件傳輸暫時先采用apache這些http服務器,這樣也便於更早的調試。
數據庫使用的mysql,服務器使用linux下的c++ socket epoll(其實使用php或是javaweb更方便,但我更想多用用c++)。客戶端使用的mfc+ActiveX。
雖然服務器的實現很簡單,但客戶端更簡單,我先從最簡單的客戶端說起:
有段時間沒摸過vs了,上次使用還是在擼cocos2d的時候。得意與強大的vs和activeX,一個能播放視頻的播放器只用了10幾分鍾就做好了,剩下的時間全花在播放控制與播放列表存儲與管理上。
因為用的是vs2012,似乎並沒有該activeX的doc,於是自己在網上下載的CWMPPlayer4這些doc。
可以通過輸入url直接播放該地址文件。
簡單而強大,不單單能播放本地與自己服務器的視頻。但mkv這些視頻格式需要另寫解碼器,一些其他協議的網絡視頻需要作額外的處理。客戶端的介紹就這么點,真的沒再多了,另外只有關於鏈接服務器的部分。
視頻信息服務器:
首先是數據庫的設計,目前就一張表:
name | type |
id | int |
created_at | timestap |
updated_at | timestap |
type | int |
fileurl | string |
imgurl | string |
info | text |
其中有個imgurl用於指向視頻介紹的截圖,用於用戶參看。
因為服務的部分也沒太復雜或繁雜的地方,也就沒做什么設計,直接在自己以前封裝的epoll模型接口上開始寫服務邏輯。
首先是數據庫通信,這里使用的自己以前封裝的數據庫類sqluse,添加上這次的查詢格式:
模型:
1 #define data_statu_end 0 2 #define data_statu_wait 1 3 #define data_statu_rewait 2 4 #define data_statu_error 3 5 #define data_statu_run 4 6 7 #define data_type_unkonw 0 8 9 struct model_filelist 10 { 11 int id; 12 string created_at; 13 string updated_at; 14 string name; 15 string info; 16 string imageurl; 17 string fileurl; 18 int type; 19 };
然后是協議文件:
1 #ifndef _PROTO_H_ 2 #define _PROTO_H_ 3 4 5 #define QUEST_GET_LIST 100 6 #define QUEST_GET_ONE 200 7 8 #define RQUEST_ERROR 1000 9 #define RQUEST_GET_LIST 1100 10 #define RQUEST_GET_ONE 1200 11 12 13 #define LIST_MAX_NUM 200 14 15 struct proto_base 16 { 17 unsigned short quest; 18 unsigned long long sign; 19 }; 20 21 struct proto_filelist 22 { 23 int id; 24 char created_at[32]; 25 char updated_at[32]; 26 char name[64]; 27 char info[256]; 28 char imageurl[128]; 29 char fileurl[128]; 30 int type; 31 }; 32 33 struct proto_filelist_id 34 { 35 int num; 36 unsigned int idarr[LIST_MAX_NUM]; 37 }; 38 39 #endif // _PROTO_H_
因為封裝的epoll模型網絡部分和服務邏輯部分耦合較低,因此還是只通過那一個接口就能聯系到網絡部分與邏輯部分:
1 #ifndef _MPLAYERSERVER_H_ 2 #define _MPLAYERSERVER_H_ 3 4 #include "include/sqluse.h" 5 #include "include/proto.h" 6 #include "include/ssock.h" 7 8 9 class mplayerserver 10 { 11 sqluse sql; 12 public: 13 mplayerserver(); 14 ~mplayerserver(); 15 16 mdata *dealdata(mdata *data);//the only api 17 18 }; 19 20 #endif //_MPLAYERSERVER_H_
最后就是服務器處理數據的邏輯:
1 mdata *mplayerserver::dealdata(mdata *data) 2 { 3 mdata *newdata=new mdata; 4 newdata->fd=data->fd; 5 6 proto_base rebase; 7 8 proto_base *basedata=(proto_base *)data->buf; 9 10 if(basedata->quest==QUEST_GET_LIST) 11 { 12 proto_filelist_id re; 13 re.num=sql.getfilelistid(re.idarr,sizeof(re.idarr)); 14 if(re.num>0) 15 { 16 rebase.quest=RQUEST_GET_LIST; 17 newdata->adddata((char *)&rebase,sizeof(rebase)); 18 newdata->adddata((char *)&re,sizeof(re)); 19 } 20 else 21 { 22 failmdata(newdata); 23 } 24 25 } 26 else if(basedata->quest==QUEST_GET_ONE) 27 { 28 unsigned long filelistid=basedata->sign; 29 30 model_filelist mlist; 31 mlist.id=filelistid; 32 if(sql.getonefilelist(&mlist)) 33 { 34 proto_filelist re; 35 re.id=mlist.id; 36 strcpy(re.created_at,mlist.created_at.c_str()); 37 strcpy(re.updated_at,mlist.updated_at.c_str()); 38 strcpy(re.name,mlist.name.c_str()); 39 strcpy(re.info,mlist.info.c_str()); 40 strcpy(re.imageurl,mlist.imageurl.c_str()); 41 strcpy(re.fileurl,mlist.fileurl.c_str()); 42 re.type=mlist.type; 43 44 rebase.quest=RQUEST_GET_ONE; 45 newdata->adddata((char *)&rebase,sizeof(rebase)); 46 newdata->adddata((char *)&re,sizeof(re)); 47 } 48 else 49 { 50 failmdata(newdata); 51 } 52 } 53 //more quest.. 54 55 return newdata; 56 }
客戶端連接服務器后獲取到網絡視頻列表:
視頻數據傳送:
這里采用的是apache服務器來進行文件傳送,通過url導向Apache所在服務器以及文件結構下的視頻文件,來實現視頻文件傳輸與播放。這部分以后可以自己用http協議或者是public ftp實現。
一套能用的網絡播放器就做好,非常的簡單。
但是這樣的播放器還是不能滿足現代視頻播放的需要的。因為版權與利益的問題,網絡上的大量視頻都經過加密、路由轉換等手段使得其他終端不能輕易的獲取與播放,再加之目前的很多視頻在容量上有很大的壓縮空間,可以通過一些優化的算法與協議對傳輸的視頻數據進行處理,實現視頻的高效傳輸。我因為經歷有限,也不想在這方面深入下去。希望自己這微不足道的網絡播放器制作經歷對大家有點幫助。
筆者都大四該出去實習了,學校逼着留校實訓竟然還是讓做視頻播放器,而且是2人一組使用mfc activeX做一個本地視頻播放器,服務端都還是自己主動做的。一共要求做一個月,每天都要寫進度文檔,666,最多一天就做完的東西,剩下的29天進度文檔就要靠想象力。雖然是個本科,但待這學校里面除了靠自己,真學不到任何東西,要出去實習只能去給過學校好處的單位,已經有朋友去其他單位被強制弄回來或是給處分了。系領導是個當兵的,根本就不知道什么是道理與邏輯,自己說什么就是什么。學校一瓢葷菜8塊素材4塊...還想吐很多學校的槽(最后還是忍住了,肯定還有很多更糟糕的學校,自我安慰下)