Android基于UPnP/DLNA的智能设备媒体互联


声明:本文转载自https://my.oschina.net/u/3548910/blog/1058146,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

有趣的

在一个项目工作中偶然接触到 UPnP -- 一个基于本地网络的即插即用设备互联协议标准,后来经了解发现 UPnP 是个很有趣的东西。这个协议有一些特性(详细信息可参考官方资料 http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf

⦁ 对等,没有主次

所有 UPnP 网络中的设备及可以提供服务,也可以主动发起数据传输,设备的角色取决于软件(不像 USB 协议那样的主从模式)。如果一个设备实现了 AVTransport 那么它可以提供媒体渲染服务,例如一台智能电视;如果设备实现了 ContentDirectory 那么它可以提供流媒体服务,例如开启媒体流的功能的 PC;如果设备是使用 ControlPoint 那么它就像是个智能遥控器,例如安装一些 DLNA 控制软件的手机;一台设备可以同时支持多个服务,例如Windows Media Player它即可以接受渲染推送来的媒体,也可以吧媒体推送到其他设备上播放(Play To)。UPnP网络中的设备没有一个Master,所有设备都是对等。

⦁ 即插即用,零配置

这个即插即用不是硬件层面的(不像USB那样的串行总线设备拓展),而是通过本地网络实现。设备可以动态加入网络(通过SSDP发现设备),传达其功能(使用XML描述),并了解其他设备的存在和功能。 设备可以顺利自动地离开网络,而不会留下任何不必要的状态,比如正在推送一部电影到智能电视上播放,电视突然掉电了软件也不会出现异常。UPnP不需要硬件支持(带Wi-Fi/Ethernet就行),不需要设备驱动程序,设备处于同一个网络下就可以通过UPnP直接互动。

⦁ 安全性与路由器的UPnP功能

首先,路由器的NAT穿透用到的是UPnP的Internet Gateway Device(简称IGD),IGD是UPnP定义的设备服务之一,提供端口映射功能,让本地网络的设备端口映射到外网。这样软件(自动设置不需要用户参与)就能使用IGD绕过NAT进行一些数据传输,但是这样也有安全隐患,比如来自外部网络的主动的恶意访问。下图是路由器开启UPnP IGD功能后被网络中的Android设备及Windows PC所发现,和UPnP网络的其他设备一样,软件能够直接发现它并使用它的(端口映射)功能。

Windows 10 发现IGD设备

Android 发现IGD设备

另外一方面,UPnP/DLNA设备互动一般没有身份验证,比如家用智能电视机任何设备都可以控制,但是说这样不安全就有点夸张,因为是本地网络的操作,虽然一个ControlPoint能够推送外网上的视频(发一个URL地址)给电视机,但是就和打开电脑浏览器看电影差不多和IGD没关系。

媒体分享与无线显示

UPnP本身包含了一些网络协议如TCP、UDP、HTTP、XML,DLNA又是包含了更多协议的标准,如下图的一份DLNA的技术架构,里面就包含了对UPnP的使用(详细信息可参考官方资料https://spirespark.com/dlna/guidelines/)。标题里写UPnP/DLNA是因为在Android上做的设备互联应用走的是主要是UPnP标准,用了部分DLNA功能。

DLNA的内容很多是媒体分享娱乐方面,和现在的无线显示技术标准Mirocast(开放标准,Android 4.2以上、Windows 8.1以上)、Airplay(Apple家的,不了解)有着本质的区别

⦁ 硬件支持

UPnP/DLNA是基于网络的设备互联,不需要硬件、操作系统支持,软件就可以实现。无线显示要取得屏幕数据,需要操作系统提供支持,也需要Wi-Fi硬件模块支持。

⦁ 媒体传输

DLNA是Play To,当用户推送一个电影到电视机(DLNA渲染设备简称MR)上时候是向MR发送了一个的URL,MR收到这个URL时就可以播放这个电影,数据传输是在媒体服务器(简称MS)和MR之间。这个传输是媒体源直接传输到MR,由MR解码播放,过程:媒体源—>传输—>MR解码,MR需要支持全格式解码。DLNA没有涉及到屏幕传输,但是可以通过MediaProjection(Android 5.0以上支持)取得屏幕数据,编码,Play To到MR,这样也可以以软件的方式实现屏幕传输,但是其效率没有无线显示效率高,另外像Mirocast的远程屏幕点击的功能也难以实现。

Mirocast无线显示是Cast(屏幕投射,相当于一块拓展屏幕),它是将屏幕内容编码为一种媒体格式,再通过媒体流传输到接收端,接收端再解码,过程:屏幕—>编码—>传输—>接收端解码,接收端只需支持固定几种格式解码。当然也可以手机播放电影再Cast到大屏幕电视,然而此时的过程就会变成:媒体源—>解码—>编码屏幕—>传输—>接收端解码,其效率没有DLNA高,另外由于Cast的格式限制像1080p、4K、这样的高质量媒体源也很难保持原始质量,再如单纯的音乐Play To到智能音响的场景Mirocast就不合适。

⦁ 连接对象

DLNA是基于逻辑上的服务和控制点,而逻辑上的服务和控制是运行于那个设备上却是任意的,一个服务允许多个设备访问,一个控制点也可以处理多个服务,设备连接没有绑定。再说这个用户推送的一个电影到MR,他发的电影有可能在手机上、电脑上、电视机上(电视机支持MR、MS即可),还可以是一个外网视频,而这些MS同时还能支持其他设备的内容访问。同样的一个MR可以同时支持多个ControlPoint控制。

无线显示则是点对点,Peer to Peer,连接建立并绑定于2个设备之间,相当于外接一块无线显示屏,如果需要连接其他设备则先要解除之前的连接。

Android UPnP/DLNA应用

在发布UPnP协议规范的https://openconnectivity.org网站上也列出了一些开源的UPnP SDK,cling(https://github.com/4thline/cling)就是java实现的Android上用的多的一款。cling主要分2部分:cling core,由java实现的UPnP Device Architecture 1.0;cling support,Media Server、Media Renderer的一些拓展还有路由器NAT映射的支持,使用cling可以实现大部分的UPnP/DLNA功能应用。

使用cling库的一些关键点

⦁ 导入库

cling相互依赖的库不少,该项目源码是通过maven在线构建的方式编译,也可以将依赖库下载到本地通过Android Studio(gradle)直接构建。这个是cling 2.1.1的完整依赖库(供参考)

cling-core-2.1.1.jar,cling-support-2.1.1.jar,seamless-http-1.1.1.jar,seamless-util-1.1.1.jar,seamless-xml-1.1.1.jar

jetty-client-8.1.21.v20160908.jar,jetty-continuation-8.1.21.v20160908.jar,jetty-http-8.1.21.v20160908.jar,jetty-io-8.1.21.v20160908.jar,jetty-security-8.1.21.v20160908.jar,jetty-server-8.1.21.v20160908.jar,jetty-servlet-8.1.21.v20160908.jar,jetty-util-8.1.21.v20160908.jar,servlet-api-3.0.jar

javax.enterprise-cdi-api-1.2.jar,javax.mail-mail-1.4.7.jar

net.sf.kxml-kxml2-2.3.0.jar

org.dbunit-dbunit-2.2.3.jar

org.hibernate-hibernate-core-3.6.10.Final.jar

org.slf4j-slf4j-api-1.6.6.jar,org.slf4j-slf4j-jdk14-1.6.6.jar

⦁ 创建设备,实现服务

如果一个UPnP设备提供功能服务则需要创建一个LocalDevice:

new LocalDevice(     new DeviceIdentity(new UDN("1111")),     new UDADeviceType("MediaRenderer"),     new DeviceDetails("My MediaRenderer"),     new LocalService[] {         createAVTransportService(),         createRenderingControlService()      }) 

DeviceIdentity:设备的UDN,即UPnP网络中唯一的设备标识符需要唯一,程序可以读取机器的一些特征ID来生成UDN

UDADeviceType:设备类型,比如媒体渲染器是 “MediaRenderer” ,媒体服务器是 “MediaServer”

DeviceDetails:设备的名称,制造商,型号等信息。这些信息一般是对用户可见的,默认读取机器的一些信息,然后用户可以设置

LocalService:设备提供的服务,这里就是UPnP设备服务功能的入口,要根据上面的UDADeviceType实现不同的服务。这里的Object类型是cling库封装好的各种设备服务的抽象类,继承服务抽象类,实现功能即可。MR要实现的AVTransport(简称AVT)里要Override有十多个方法,对接播放器核心也是在AVT里处理,比如AVT里一个来自远程Seek的操作,此时调用VLC的Seek或是Android自带MediaPlayer的Seek取决于选用的播放核心。

⦁ 注册表,事件侦听,控制点

UPnP的控制能操控网络中的各种服务,cling的API功能主要封装在那个AndroidUpnpService里。

Registry(这个注册表不是操作系统的注册表)是通过AndroidUpnpService. getRegistry()得到UPnP服务的Registry,这里有UPnP网络中的本地及远程设备列表,也是在这里添加删除本地服务,另外在这里设置UPnP事件侦听。

RegistryListener事件侦听器里有设备上线、下线、更新等消息,通过Registry.addListener()、Registry.removeListener()来设置。

ControlPoint通过AndroidUpnpService.getControlPoint()得到,通过ControlPoint就可以搜索设备,可以执行各种使用服务的操作。

媒体分享及推送

如果一个DLNA应用需要能够分享本地媒体,让UPnP网络上的其他设备能看到,或是能够主动推送本地媒体到一个远程MR播放。那么这个应用需要实现HTTP/RTP媒体流传输,本地媒体服务需要创建一个MS设备,MS加入到UPnP后会被其他设备看到会收到服务请求,请求的处理将是与媒体服务对接。推送本地媒体的操作是发送一个URL,这个URL是源自本地媒体器生成的链接,后面的数据传输都是本地媒体服务器的任务。媒体流服务一般用HTTP,因为HTTP媒体流传输是DLNA规范要求支持,而其他媒体流传输可以是Optional。下图是Android推送一个短视频到Windows 10,Media Player播放中,显示的媒体来源来自于192.168.1.101:9000(即手机,URL地址资源路径经过编码)

Android 设备推送

Windows 10 MR设备播放

一些HTTP库的信息

⦁ Apache HttpComponents

https://hc.apache.org,Apache开发的,很专业,需求匹配基本上就可以选用了。早期版本的Android集成了该库后面Android没有集成了(官方解释https://hc.apache.org/httpcomponents-client-4.3.x/android-port.html),如果现在使用该库可能会遇到兼容性问题,如Android Studio提示过期的API(deprecated),编译会提示缺少class之类的信息。

⦁ NanoHTTPD

https://github.com/NanoHttpd/nanohttpd,引用官方的说法:Java实现的一个小型的Web Server。确实很小,把几个java文件引入项目总即可,该库也有实现了Seekable Content服务的代码。目前他是以源码的形式发布。不过在开发后期的代码检查和分析里(Inspection)会有不少警告,该库提升空间比较大,例如下面源码里的一行代码(NanoHTTPD.java 第651行):

 this.remoteIp = inetAddress.isLoopbackAddress() || inetAddress.isAnyLocalAddress() ? "127.0.0.1" : inetAddress.getHostAddress().toString();  

该行是要得到一个地址字符串给remoteIp(String类型),下划线部分inetAddress.getHostAddress()返回的其实已经是String类型,但是他这里是调用了String.toString来返回一个String。

⦁ Jetty

https://www.eclipse.org/jetty/,Android上也可以使用Jetty,cling的依赖之一就是Jetty,正是因为cling依赖它所以直接使用这款可以省个库。详细信息可参考官方网站。

Idea

感觉没说多少,写到这里却发现已经敲了三千多字。。。

正在处于研究发展阶段的IoTivity(https://openconnectivity.org/https://www.iotivity.org/)设备互联的目标和UPnP有点像,IoT是一张更广扩的设备互联网,UPnP/DLNA则更加针对于媒体应用的设备互联,也有IoT的一些实现库会直接桥接UPnP(https://www.iotivity.org/downloads/iotivity-1.3.0

以前做过一版UPnP/DLNA应用软件,用了信号量(Semaphore)对UPnP操作进行锁定和排队,其实这个没必要,当然近期做的新版本(UI很丑)也就取消了这方面处理还引入了全能播放核心VLC。新拍了一个技术演示视频放到了优酷(http://v.youku.com/v_show/id_XMjgzNzk5NzEyNA==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2)。视频长度2分钟,演示的是Android软件通过UPnP/DLNA将一部1080p 18G的电影推送到电脑上播放,期间Android软件有调整播放进度、控制音量、的操作,位于PC的播放器同步了这些操作。这是技术演示视频,实际的应用可能是推送到智能电视或是机顶盒。

最后附上一些功能截图

上图,浏览媒体服务器的内容,这里是一台Windows PC,MediaPlayer 提供的流媒体服务

 

上图,设备播放媒体服务器上的歌曲,透明信息框里显示了媒体地址,另外Windows MediaPlayer流媒体服务还提供了不同码率的多种资源,歌曲的封面也来自媒体服务器

 

上图,直接对接媒体渲染器,控制音量、播放等。

knight.mobile@outlook.com

本文发表于2017年06月29日 10:36
(c)注:本文转载自https://my.oschina.net/u/3548910/blog/1058146,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 4752 讨论 0 喜欢 4

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1