Android DLNA投屏-基本原理

1. DLNA简介

DLNA(Digital Living Network Alliance),即数字家庭网络联盟。
DLNA不是技术,而是一种解决方案,它是多种技术的整合,并致力于构建家庭媒体共享。
DLNA包含多种网络协议,如http、https、upnp等,其中upnp是其重要组成部分。
DLNA主要包含以下四种产品:
DMS,即Digital Media Server(数字媒体服务器)的缩写,其主要作用是作为媒体内容的提供者,为DMP/DMR提供内容播放,DMS可控制提供哪些媒体内容。
DMP,即Digital Media Player(数字媒体播放器)的缩写,可搜索并播放DMS的内容,其作用相当于DMR+DMC。
DMC,即Digital Media Controller(数字媒体控制器)的缩写,可搜索并控制DMR播放DMS提供的内容,即控制DMR与DMS的交互。
DMR,即Digital Media Renderer(数字媒体渲染器)的缩写,可播放DMS提供的内容。

2.Upnp设备架构(Upnp Device Architecture)

Upnp DA将家庭网络中的角色分为三种:控制点、设备和服务。它们之间主要通过HTTP技术实现通信。设备和相关服务的规格信息使用XML方式向其他节点公布。
Upnp DA中各角色的关系如下图:


Upnp组件架构.png

各个角色的基本概念如下:

  1. 根设备/设备,即硬件设备,如电脑、电视盒子等。一个设备可提供多个服务。但是家用电器内部一般都包含了多个功能不同的设备,这样由多个设备集合而成的设备集合体,被称为根设备。
  2. 设备所能提供的功能服务。分为控制服务、事件服务、展示服务。服务是Upnp系统中最小的可控制单元(动作与状态)。
  3. 控制点。即控制设备,可发现并控制其他设备。如控制其他设备的视频播放、暂停等。
    在DLNA投屏的过程中,Android设备充当的角色是控制点,它初始化并配置好DMS和DMR设备之间的连接,并不直接参与真正的内容传输,内容传输由DMS和DMR完成。

3.DLNA网络传输流程

DLNA的网络传输由设备发现开始。首先,一个新的控制点(Control Point)加入局域网,那么这个Control Point就会开始搜索局域网内可用的设备了。当控制点开始搜索时,它会从UDP端口发送如下格式的搜索请求消息:

M-SEARCH * HTTP/1.1

MX: 1 //最大时间间隔数

ST: upnp:rootdevice //搜索的设备类型

MAN: "ssdp:discover" 

User-Agent: iOS 10.2.1 product/version

Connection: close

Host: 239.255.255.250 //多播地址

如果发现可用设备,则会从UDP端口收到如下响应消息:

HTTP/1.1 200 OK

Cache-control: max-age=1800

Date: Thu, 16 Feb 2017 09:09:45 GMT

EXT:

LOCATION: http://10.2.9.152:49152/TxMediaRenderer_desc.xml //URL for UPnP description for device

Server: search target

USN: uuid:3c970e3c0c0d0000_MR::upnp:rootdevice //composite identifier for the advertisment

BOOTID.UPNP.ORG: 1487062102 //number increased each time device sends an initial announce or an update message

CONFIGID.UPNP.ORG: 499354 //number used for caching description information

SEARCHPORT.UPNP.ORG: number identifies port on which device responds to unicast M-SEARCH

ST: upnp:rootdevice //device type

可以看到,在响应消息中,LOCATION这个字段是一个url:

LOCATION: http://10.2.9.152:49152/TxMediaRenderer_desc.xml  //URL for UPnP description for device

这个url指向的是设备服务和信息描述文档,一般为xml格式。我们可以直接通过浏览器访问该链接查看该设备的相关信息:

<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0" configId="499354">
  <specVersion>
    <major>1</major>
    <minor>1</minor>
  </specVersion>
  <device>
    <deviceType>urn:schemas-upnp-org:device:MediaRenderer:1</deviceType>
    <friendlyName>卧室的创维盒子Q+</friendlyName>
    <manufacturer>Plutinosoft LLC</manufacturer>
    <manufacturerURL>http://www.plutinosoft.com</manufacturerURL>
    <modelDescription>Plutinosoft AV Media Renderer Device</modelDescription>
    <modelName>AV Renderer Device</modelName>
    <modelURL>http://www.plutinosoft.com/platinum</modelURL>
    <UDN>uuid:9c443d47158b-dmr</UDN>
    <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMR-1.50</dlna:X_DLNADOC>
    <serviceList>
      <service>
        <serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
        <serviceId>urn:upnp-org:serviceId:AVTransport</serviceId>
        <SCPDURL>/AVTransport/9c443d47158b-dmr/scpd.xml</SCPDURL>
        <controlURL>/AVTransport/9c443d47158b-dmr/control.xml</controlURL>
        <eventSubURL>/AVTransport/9c443d47158b-dmr/event.xml</eventSubURL>
      </service>
      ...
    </serviceList>
  </device>
</root>

在设备信息描述文档中,有一个名为<serviceList>的节点,该节点是设备可提供服务的描述。有多个<service>节点,
<serviceList>节点中,包含了多个在<service>节点,每一个<service>节点代表着一个服务
<service>节点中主要包含着以下节点:

  • <serviceType> service的类型
  • <serviceId> service的ID值
  • <SCPDURL> 该节点的url指向服务的动作描述文档(SDD),可以直接通过浏览器访问
  • <controlURL>该节点为服务请求url,在发送动作请求消息时,需要将动作参数以规定格式发送给该url以获取响应消息

可以看出,<SCPDURL>节点的url并没有标出域名和端口号,因为其域名和端口号与响应消息中LOCATION字段的域名和端口号一致。如上述代码中的<SCPDURL>的完整url应为:

http://10.2.9.152:49152/AVTransport/9c443d47158b-dmr/scpd.xml

通过浏览器访问url,可获取如下格式的内容:

<scpd xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion>
    <major>1</major>
    <minor>0</minor>
  </specVersion>
  <actionList>
    <action>
      <name>SetAVTransportURI</name>
      <argumentList>
        <argument>
          <name>InstanceID</name>
          <direction>in</direction>
          <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
        </argument>
        <argument>
          <name>CurrentURI</name>
          <direction>in</direction>
          <relatedStateVariable>AVTransportURI</relatedStateVariable>
        </argument>
        <argument>
          <name>CurrentURIMetaData</name>
          <direction>in</direction>
          <relatedStateVariable>AVTransportURIMetaData</relatedStateVariable>
        </argument>
      </argumentList>
    </action>
    ...
  <serviceStateTable>
    <stateVariable sendEvents="no">
      <name>AVTransportURI</name>
      <dataType>string</dataType>
    </stateVariable>
    ...
  </serviceStateTable>
</scpd>

可以看到,文档中包含一个名为<actionList>的节点,该节点为服务的动作描述。
<actionList>中包含了多个<action>节点,每个节点对应着一个动作
每个<action>节点中都包含着如下节点:

  • <name> 动作名
  • <argumentList> 参数列表。每个<argumentList>节点中包含了多个<argument>节点,每个<argument>节点代表着一个动作参数。一个<argument>节点包含着如下节点:
    • <name> 参数名
    • <direction> 该节点参数取值为in/out, 当<direction>的值为in时,表明这个参数的值是传入值,当为out时,表明这个参数的值是返回值,则该值会随着订阅事件一起返回给订阅者。
    • <relatedStateVariable> 该节点的值是一个<stateVariable>节点的映射,映射的内容可在下方<serviceStateTable>节点中找到,<stateVariable>节点包含值的类型及取值范围等信息。

简单的来说,可以把一个action当成一个API接口,而action中的argument则可表示为API接口的参数,而service即是多个相关接口的集合。
通过上面的信息,就可以请求服务动作,实现设备控制了。开发者可根据文档中规定的请求参数,发送如下格式的请求消息:

POST /AVTransport/9c443d47158b-dmr/control.xml HTTP/1.1
HOST: 10.2.9.152
Content-Type: text/xml; charset="utf-8"
SOAPAction: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"
<?xml version="1.0"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <s:Body>
    <u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
      <InstanceID>0</InstanceID>
      <CurrentURI>yourAVURI</CurrentURI>
    </u:SetAVTransportURI>
  </s:Body>
</s:Envelope>

POST 字段后面跟的是<controlURL>节点的url,HOST对应的LOCATION字段的IP。
SOAPAction的格式:"<serviceType>节点的值#请求的action的名称"
<s:Body>节点的内容是请求体,请求体的格式为:

<u:请求的action的名称 xmlns:u="<serviceType>节点的值">
      <参数1>参数值</参数1>
      <参数2>参数值</参数2>
      ...
    </u:请求的action的名称>

如果请求成功,会获取如下格式的响应消息:

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Date: Thu, 16 Feb 2017 09:09:45 GMT
Server: OS/version UPnP/1.1 product/version
<?xml version="1.0"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
      <u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
        <u:SetAVTransportURIResponse>
          <_xmlns:u>"urn:schemas-upnp-org:service:AVTransport:1"</_xmlns:u>
        </u:SetAVTransportURIResponse>
      </u:SetAVTransportURI>
    </s:Body>
  </s:Envelope>

这样,整个传输流程就完成了。同一种类型的设备提供的服务大部分相同,但也可能有所差异,因此,在请求设备服务之前,最好先浏览其设备描述文档,查看设备支持哪些服务。
在介绍完DLNA投屏基本原理之后,在下一篇博客《Android DLNA投屏-基于CyberGarage开发投屏功能》,我将介绍如何使用CyberGarage开发Android投屏功能。
参考博客:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,192评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,186评论 1 303
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,844评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,471评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,876评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,891评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,068评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,791评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,539评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,772评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,250评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,577评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,244评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,146评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,949评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,995评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,812评论 2 276

推荐阅读更多精彩内容