最近用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块...还想吐很多学校的槽(最后还是忍住了,肯定还有很多更糟糕的学校,自我安慰下)