iOS DLNA编程
近期实现了iOS下的DLNA,发现ios下的DLNA编程资料很少,其实DLNA文档还好 (28m) ,但是真的确定要看文档自己去实现么?
下面先介绍一下DLNA的基本概念,已经有概念的同学可以跳过,直接看iOS下的DLNA库
什么是DLNA
DLNA的全称是DIGITAL LIVING NETWORK ALLIANCE, 其宗旨是Enjoy your music, photos and videos, anywhere anytime, DLNA (Digital Living Network Alliance) 由索尼、英特尔、微软等发起成立、旨在解决个人PC, 消费电器, 移动设备在内的无线网络和有线网络的互联互通, 使得数字媒体和内容服务的无限制的共享和增长成为可能, 目前成员公司已达280多家.DLNA并不是创造技术, 而是形成一种解决的方案,
一种大家可以遵守的规范. 所以, 其选择的各种技术和协议都是当前所应用很广泛的技术和协议.DLNA将其整个应用规定成5个功能组件. 从下到上依次为:网络互连, 网络协议, 媒体传输, 设备的发现控制和管理, 媒体格式.
以上摘自百度百科.通俗的说就是一帮人为实现某些功能,定义了一个标准.
功能
- 探索:网络中寻找无配置的设备并计算出其提供的性能
- 浏览:浏览内容并通过不同方式分类
- 搜索:在设备上寻找特定内容
- 分流:全网发送多媒体内容
- 服务:网络通知通讯录
- 打印:向网络附属打印机发送内容
- 控制:使用网络改变设备状态
- 上传:发送内容到服务器
- 下载:接收并储存内容
- 自动译码:改变分辨率或内容格式来确保设备正确翻译
- 服务保证:区分网络交通优先次序, 若网络超载, 优先放弃最弱的优先权
功能模块
- 数字媒体服务器 (DMS, Digital Media Server) :提供了媒体文件的获取、录制、存储以及作为源头的设备.
- 数字媒体播放器 (DMP, Digital Media Player) :可查找并播放或输出任何由DMS所提供的媒体文件的设备.
- 移动式数字媒体服务器 (M-DMS, Mobile Digital Media Server) :针对手机等体积较小、轻巧可移动式的电子设备所定义的服务器, 多媒体格式支持与一般DMS稍有不同.
- 移动式数字媒体播放器 (M-DMP, Mobile Digital Media Player) :同样是针对移动设备的播放器, 多媒体格式支持与一般DMP稍有不同.
- 数字媒体控制器 (DMC, Digital MediaController) :作为遥控设备使用, 可查找DMS上的多媒体文件, 并指定可播放该多媒体文件的DMP进行播放或是控制多媒体文件上下传到DMS的设备.
- 数字媒体打印机 (DMPr, Digital Media Printer) :DMPr的打印机可以在DLNA网络架构下提供打印功能.
iOS下的DLNA库
git上搜的话,只搜到一个oc包装的库https://github.com/FuruyamaTakeshi/DLNA
这个库的问题还是有些的
- 文档嘛,去了作者的个人站点,发现有了和没有一样.
- demo不全,不是所有的功能写了
- 还有个bug,seek那里应该用REL_TIME
- 所有的请求是走是程同步,非多线程
- 初始化到启动时间过长,ip6测试从init开始到搜索需要6s左右.
- DLNA协议实现的也不全,但是再不全也比自己重写的好.
iOS下的DLNA
咱项目呢,需要用的是DMC那部分,通俗的说就是把手机上的在线的视频投放到小米盒子之类的产品上.
具体的实现:
// 搜索设备,我们这里就只搜DMR了
CGUpnpAvController *avCtrl = [[CGUpnpAvController alloc] init];
avCtrl.delegate = self;
// 这个 start 要6s
[self.avCtrl start];
[self.avCtrl searchWithST:DLNAService__CG_UPNPAV_DMR_DEVICE_TYPE];
// 响应设备跟新的委托
- (void) controlPoint: (CGUpnpControlPoint *) controlPoint deviceAdded: (NSString *) deviceUdn;
- (void) controlPoint: (CGUpnpControlPoint *) controlPoint deviceUpdated: (NSString *) deviceUdn;
- (void) controlPoint: (CGUpnpControlPoint *) controlPoint deviceRemoved: (NSString *) deviceUdn;
- (void) controlPoint: (CGUpnpControlPoint *) controlPoint deviceInvalid: (NSString *) deviceUdn;
// 有设备后,给设备发送相应的命令,控制设备的行为
// 给指定的设备设置播放地址
// 这里DLNA的文档上是用了这个action后DMP会变成play状态,就是会自动播放
BOOL b = [_currentRenderer setAVTransportUrl:url];
// 但是腾讯是又发了一个play的action,可能是腾讯测试的机子多,发现有些设备没有自动播放吧
b = [_currentRenderer play] && b;
// 设置seek的时间,这里记得fix下库的bug
[_currentRenderer seek:iTime]
// 这样就完成了将网上的视频投放到盒子 (电视上了) ,但是还没完,我们不知道播放进度
// 我们得自己写个定时器,主动问设备,您播放到哪秒了啊
CGUpnpAVPositionInfo *positionInfo = [_currentRenderer positionInfo];
// 最后就是关于停止暂停的一些方法了
[_currentRenderer stop];
[_currentRenderer pause];
// 如果你还想改音量啊,连续播放视频啊
// 呵呵,这个库没带,请自己实现
// 类似下面的下一个
- (BOOL) next
{
CGUpnpAction *action = [self actionOfTransportServiceForName:@"Next"];
if (!action)
return NO;
[action setArgumentValue:@"0" forName:@"InstanceID"];
if (![action post])
return NO;
return YES;
}
// 当你实现了连续播放视频的功能时候呢,你会发现,小米盒子没实现这个功能
// SetVolume这个action是实现设置音量的,这个可以试试看哦
看了上述代码发现其实也不难嘛,具体试了之后呢会发现一堆坑的,如seek, 文档上是说只有play或者stop的状态下发送才能成功.所以呢,你直接发完play的action后,立马发一个seek,觉得会成功么?DMR刚刚收到setAVTransportUrl后是下载,不是play状态哦,但是这个时候已经回复你action成功了.如果你想知道DMR的状态是有办法的,但是这个oc包装的库没写.但是呢有的设备可以直接就发送seek,有的就必须等下载完成开始play后才能seek,我说的设备还都是小米盒子.