手机电视FAQ

来源:互联网 发布:阿里云主机80端口打开 编辑:程序博客网 时间:2024/04/28 22:50

Q:CMMB是什么意思?MBBMS又是什么?它们的关系是什么?

CMMBChina MobileMultimedia Broadcasting (中国移动多媒体广播)的简称。是国内自主研发的第一套面向手机、笔记本电脑等多种移动终端的系统,利用S波段信号实现“天地”一体覆盖、全国漫游,支持25套电视和30套广播节目。20061024日,国家广电总局正式颁布中国移动多媒体广播(俗称手机电视)行业标准,确定采用我国自主研发的移动多媒体广播行业标准。标准适用于30MHz3000MHz频率范围内的广播业务频率,通过卫星和/或地面无线发射电视、广播、数据信息等多媒体信号的广播系统,可实现全国漫游。

MBBMS是指Mobile BroadcastBusiness Management System (广播式手机电视业务管理系统),它的基础是利用现有移动通信网络的管理、计费系统和认证鉴权机制,实现对手机电视用户的管理。

CMMB是一个独立的系统,它可以脱离MBBMS独立的运行,但是无法使用MBBMS所带来的现有的移动通信网络资源。比如,MBBMS的密钥核心算法在SIM卡上存储和执行,CMMB CA的密钥核心算法在小卡/SMD/大卡上存储和执行。再比如,仅仅是CMMB无法使用移动网络现有的计费系统。

MBBMS提供了一系列使用现有移动资源的方法,除CMMB之外的其他手机电视标准也可以使用这些方法,比如MBMS

 

Q:CMMB+MBBMS系统需要手机提供什么样的软硬件资源?

首先说硬件,需要提供一颗CMMB芯片,负责调频,接收数据,改芯片上还需要集成一块UAM芯片,负责一些核心解密算法的实现。

如果是单独的CMMB系统,还需要提供一块小卡,该小卡的功能在MBBMS中被UAM+SIM卡取代。

 

Q:CMMB使用什么频段?

理论上是30MHz~3000MHz频率范围。全国的频段分布是:

http://wenku.baidu.com/view/27a1baa2b0717fd5360cdc66.html

 

Q:CMMB+MBBMS的基本流程是哪些?

1. 更新节目单 2. 更新订购关系表 3.GBA 4. 获取MSK 5. 若是扰流,进行解扰 6. 将音视频以RTP的形式输出

 

Q:CMMB芯片的基本工作原理是什么?

调到一定的频段,然后读取某个或某些时隙。物理层逻辑信道分为控制逻辑信道(CLCH)和业务逻辑信道(SLCH)。控制逻辑信道用于承载广播控制信息,业务逻辑信道用于承载广播业务。物理层只有一个固定的控制逻辑信道,占用系统的第0时隙发送。业务逻辑信道由系统配置,每个物理层带宽内业务逻辑信道的数目可以为1~39个,每个业务逻辑信道占用整数个时隙。

 

Q: 电子业务指南是什么?

就是ESGElectronic Service Guide),它分为SGDDSGDU,使用HTTP协议进行传输。

 

Q: 节目单是如何传送到手机的?

对于CMMB+MBBMS,业务指南是通过移动通信网络数据业务(如GPRSTDSCDMA等)下发的;对于单独的CMMB,业务指南是放到复用数据的数据段里下发的,需要通过解复用才能拿到。



Q: 什么是GBA?它有什么作用?

通用认证机制GBA(GeneralBootstrappingArchitecture),是3GPP定义的一种利用现有移动通信网络资源的认证机制。最终的一个目的就是为了在终端与业务平台之间共享一个秘密的密钥,用于安全通信。 

手机打开手机电视后的基本流程如下:

第一步,更新节目单:

1.   APP试图查找存在手机存储空间(如sdcard)里的SG文件,如发现没有,于是开始下载SG

2. MBBMS发送一个HTTP REQ来请求一个gzip包。然后解压缩到手机存储空间。

3. 进行SG的解析,其实就是XML数据的解析。最终得到SG相应分片的信息

purchaseChannelpurchaseItempurchaseDataservicepreviewDatascheduleinteractivityData等。

第二步,更新订购关系表:

更新订购关系表,并在手机存储空间存成文件。订购关系表就是提供了一堆已经订购了的服务的MSKID,举例:

<Response>

    <serviceID>ActivationStatus</serviceID>

    <ResponseCode>128</ResponseCode>

    <SubscriptionUpdateExtensionversion="">

    <LTKM validUntil="2000000000"validFrom="0">

    <MSKID>AAAAAQ== </MSKID>

    </LTKM>

    </SubscriptionUpdateExtension>

</Response>

<Response>

    <serviceID>0001000000000001</serviceID>

    <ResponseCode>000</ResponseCode>

    <SubscriptionUpdateExtensionversion="">

    <LTKMvalidUntil="1359648010" validFrom="1356969590">

    <MSKID>Alsi5A==</MSKID>

    </LTKM>

    ....

第三步,GBA

Generic Bootstrapping Architecture (GBA) 是一种用来进行用户鉴权的技术。

GBA流程(使用HTTP Digest,此协议的好处是无需明文传password,跟目前网站流行的加密密码是一个道理。明文传username,然后查询password并算出。所谓Digest,是因为采用了某些摘要算法,如MD5。另外,需要用到2G3G的鉴权机制)

1. mbbmsExecuteGBA,通过SetRequestREQ放入g_requestListHeader,然后通过GetRequestREQ拿到g_currentRequest

REQ的特征: 

req.cmd = REQCMD_INITIALIZE;

req.param = force;

2. REQ处理线程中,进入InnerInitialize

3. get imsi, HTTP_SendRequest(httpHandle,NULL, gbaBuf, STRLEN(gbaBuf), 0, 0, 0),其中有HTTPheadergbaBuf

HTTP的请求消息体,类似这样的消息

"<?xml version="1.0"encoding="UTF-8"?>

<UserID

xmlns:xs="http://www.w3.org/2001/XMLSchema\"xmlns="urn:3GPP:metadata:2005:mTV:IMPIRequest"

Type="IMSI"

TerminalCapability="%s"

UserAgent="%s">

%s

</UserID>"

其中UserID就是imsi

4. 然后函数进入循环死等RESP,成功后 解析Bootstrapping_Initiation.RESP

5. Create一个IMPIimpi:460029106017665@amobile.com,通过uam_get_version来获取Version

6. Create一个Digest请求,继续死等RESP

7. 开始鉴权ProcessGbaUnAuthorized,具体步骤是首先是SIMCard鉴权(2G3G不同的鉴权步骤),然后是UAM鉴权。

卡鉴权做完之后(即AV3,5鉴权)利用鉴权的中间结果,进行UAM鉴权。发送给UAM的中间结果是:如果是SIM卡,在命令中携带(Kc,RAND,Ks-Input,SRES), 如果是USIM卡,在命令中携带(RES,CK,IK)UAM计算KsRES‘,并生成cnonce,把Ks存储下来,并将RES'cnonce返回给终端。然后发送RES’给网络,网络生成Ks生命周期和B-TID,并发给终端。

8. 网络生成Ks生命周期和B-TID,返回给终端,写入UAM中。

综上,GBA之后,终端和网络都生成了用户共享密钥Ks,这是以后所有密钥工作的基础。



Q:如何获取MSK

MSK是通过HTTP交互获取的:根据订购关系表拿到MSKID,然后向网络发起请求

Field name Content-Type, valueapplication/mbms-msk+xml

里面带有KeyDomainIDMSKID

然后收到HTTP RESP,从中拿到 MSK Mikey。·

这是一个MSK Mikey的例子:

MSK:010015000C84B26D00010503000B00030100000104025A22E40B0250E7A1D9061031353730313439303936383836353833060000196E61662E6D62626D732E6368696E616D6F62696C652E636F6D010000355677744A2B62657733794B30487532535259494F74673D3D406273662E626A2E6D62626D732E6368696E616D6F62696C652E636F6D0001001E4534458CE203062C74A37816FCC3ABFAD4D3D39B58F5452BFFB4EB60CF7601041C2A6A570E7F3EE0F07494EDD3642714F61D75

拿到MSK Mikey后,通过UAM计算出MSK



Q:如何对扰流进行解扰?

1. 然后试图播放一个频道。如果是加密频道,需要解析SG里的SDP,拿到相关的解扰参数。这里是一个SDP的例子

<SDP>v=0 o=- 1736101621 822899201 INIP4 192.168.2.77 s=Profile 1 c=IN IP4 224.12.34.56/64 t=0 0a=min-buffer-time:1002 a=IPDCKSMStream:1 a=IPDCKSMStream:607a=IPDCKSMStream:607 m=video 55410 RTP/AVP 96 b=AS:356 b=TIAS:337792 b=RS:3000b=RR:0 a=rtpmap:96 enc-mpeg4-generic/90000 a=fmtp:96 profile-level-id=127;config=0142E00DFFE1000B6742E00D96520283F4900801000468CE3880; streamtype=4;ObjectType=33; mode=avc-video; DTSDeltaLength=22;RandomAccessIndication=1; ISMACrypCryptoSuite=AES_CTR_128;ISMACrypIVLength=4; ISMACrypDeltaIVLength=0; ISMACrypSelectiveEncryption=0;ISMACrypKeyIndicatorLength=1; ISMACrypKeyIndicatorPerAU=1; ISMACrypSalt=base64,ubH5Rf/nCGI= a=cliprect:0,0,240,320a=framerate:25. a=mpeg4-esid:201 a=x-envivio-verid:0002302D a=mid:1a=avg-br:355392 a=maxprate:55. m=audio 55412 RTP/AVP 97 b=AS:42 b=TIAS:33831b=RS:525 b=RR:0 a=rtpmap:97 enc-mpeg4-generic/48000/2 a=fmtp:97profile-level-id=15; config=131056E598; streamtype=5; ObjectType=64;mode=AAC-hbr; SizeLength=13; IndexLength=3; IndexDeltaLength=3; ISMACrypCryptoSuite=AES_CTR_128;ISMACrypIVLength=4; ISMACrypDeltaIVLength=0; ISMACrypSelectiveEncryption=0;ISMACrypKeyIndicatorLength=1; ISMACrypKeyIndicatorPerAU=1; ISMACrypSalt=base64,ubH56f/nCGI= a=mpeg4-esid:101a=x-envivio-verid:0002302D a=mid:2 a=avg-br:32000 a=maxprate:25.4375 m=data7691 UDP ipdc-ksm a=fmtp:ipdc-ksm IPDCStreamId=1; IPDCKMSId=1; IPDCOperatorId=8m=data 7491 UDP ipdc-ksm a=fmtp:ipdc-ksm IPDCStreamId=607; IPDCKMSId=6176;IPDCOperatorId=3089 m=data 7401 UDP ipdc-ksm a=fmtp:ipdc-ksm IPDCStreamId=607;IPDCKMSId=6178; IPDCOperatorId=3089</SDP>

其中下划线的部分就是一些对加密进行描述的参数。

然后根据加扰相关参数信息从加密节目流中RTP包的AU头取出key IndicatorIV

根据协议AU Header的结构如下:

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-.. -+-+-+-+-+-+-+-+-+-+

      |AU-headers-length|AU-header|AU-header|     |AU-header|padding|

      |                |  (1)   |   (2)   |      |  (n)   | bits  |

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-.. -+-+-+-+-+-+-+-+-+-+

例子:

比如某数据流第一秒数据的第一个视频单元,原数据如下:

0, 2a, f5, 85, 4d, fe, 6f, 0, fd, 63, b2,2e, 70, 92, 70,e0.

其中0,2a是指的是AuHeader的长度(42 bits ,换算成byte6)所以真正的加密数据从fd63…开始。在AuHeaderismaCrypIVLength4, ismaCrypKeyIndicatorLength1,所以KeyIndicator6f,而IVf5, 85, 4d,fe

然后,根据key Indicatorkey IndicatorMTKCW)的对应关系表中查找对应的MTKCW

对于UAM来说,输入Mikey, 输出Mtk 

然后就是解扰,使用MTKCW)以及CWIVSDP中的Salt等信息,解密节目流。

比较常用的是AES解密方法。

综上,整个MBBMS的安全架构已经比较清晰了,可以用下面这张图来概括一下:

Q:解扰后的音视频是如何播放的?

解扰后,对于视频,RAW NAL的帧被存储在m_vBuf,长度为m_vNalLen

在目前看到的Sample Data中,视频是每秒25NAL左右,有时候能到23个,或者30个,基本能组成25帧。目前在Sample Data,只有I帧和P帧,没有发现B帧。且,每秒必有一个I帧。

这些NAL单元有可能是一个帧的。

FRAME_MID           =0,//Neither the BEGIN or TAIL

FRAME_TAIL           =1,//This Piece of NAL data ends a frame

FRAME_BEGIN        =2,//This Piece of NAL data begins a frame

WHOLE_FRAME      =3,//This is a complete frame NAL data. normally A P-frame

我们要组成一个完整的帧之后再进行RTP传输。

 

音视频都会被打包成RTP进行发送,其中RTP时间戳会在解析复用子帧头的时候打上去。

音频是使用LATM的方式传输的,该格式也以帧为单位,主要由音频特定配置单元与音频负载组成。LATM帧通过RTP包发送出,而通过SDPStreamMuxConfig信息发送到解码端。音频负载由音频数据长度和音频数据组成。

对于音频来说,RAW DataAAC数据前面会有一个Byte来描述数据的长度(Except the Byte itself),

扰流格式为AU Header + Encrypted AAC DATA

下面的函数可以给AAC加上头以形成可以播放的ADTS文件:

void CDemuxClient::OnSaveAACFile(LPBYTEdata,WORD wDatalen)

{

       staticFILE *file = NULL;

       BYTEbuf[7]={0xff,0xf9,0x58,0x80,0x00,0x1f,0xfc};

       buf[5]|=((wDatalen+7)& 0x7)<<5;

       buf[4]|=((wDatalen+7)& 0x1FF8)>>3;

       buf[3]|=((wDatalen+7)& 0x1800)>>11;

       if(NULL==file)

       file= fopen("/mnt/sdcard/Download/audio","wb");

       if(!file)

       {

              fprintf(stderr,"Unable to open file\n");

              return;

       }

       if(wDatalen>0)

       {     

              fwrite(buf,1, 7, file);

              fwrite(data,1, wDatalen, file);

       }            

}

其中参数data必须是真正AAC RAW DATA的开始。

附录1HTTP Digest 认证基本框架

1.客户端希望取到服务器上的某个资源,向服务器发送Get请求。


2.服务器收到客户端的请求后,发现这个资源需要认证信息,判断请求报文中是否带有Authorization头,如果没有,返回一个 401(Unauthorized)给客户端。在这个401的回复中,同时服务器会加入一个WWW-Authenticate的头,其中有如下信息(各个字段的详细解释见RFC2617)

 

      challenge       =  "Digest"digest-challenge
      digest-challenge  = 1#( realm | [domain ] | nonce |
                          [opaque ] |[ stale ] | [ algorithm ] |
                          [qop-options ] | [auth-param] )

      domain            ="domain" "=" <"> URI ( 1*SP URI ) <">
      URI               =absoluteURI | abs_path
      nonce             ="nonce" "=" nonce-value
      nonce-value       =quoted-string
      opaque            ="opaque" "=" quoted-string
      stale             ="stale" "=" ( "true" | "false" )
      algorithm         ="algorithm" "=" ( "MD5" | "MD5-sess" |
                           token)
      qop-options       ="qop" "=" <"> 1#qop-value <">
      qop-value         ="auth" | "auth-int" | token

3.客户端收到服务器的401(Unauthorized)回复后,使用服务器回复报文中的nonce值,加上 usernamepassword, http method, http uri利用MD5(或者服务器指定的其他算法)计算出request-digest,作为repsonse头域的值。并重新发送请求,请求报文中包含 Authorization 头,其中有如下信息:

       credentials     = "Digest" digest-response
       digest-response  = 1#( username| realm | nonce | digest-uri
                       |response | [ algorithm ] | [cnonce] |
                       [opaque]| [message-qop] |
                           [nonce-count] | [auth-param] )

       username         ="username" "=" username-value
       username-value   =quoted-string
       digest-uri       ="uri" "=" digest-uri-value
       digest-uri-value = request-uri   ;As specified by HTTP/1.1
       message-qop      ="qop" "=" qop-value
       cnonce           ="cnonce" "=" cnonce-value
       cnonce-value     =nonce-value
       nonce-count      ="nc" "=" nc-value
       nc-value         =8LHEX
       response         ="response" "=" request-digest
       request-digest = <">32LHEX <">
       LHEX             = "0" | "1" | "2" | "3" |
                           "4"| "5" | "6" | "7" |
                           "8"| "9" | "a" | "b" |
                           "c"| "d" | "e" | "f"

4.服务器收到客户端发来的请求后,根据username,查找出用户的password,用和客户端同样的方法计算出request- digestresponse)。然后和收到的request-digest进行对比,如果一致,则验证成功,接受客户端的请求,成功返回结果。

 

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(6) | 评论(0) | 转发(0) |
0

上一篇:如何理解敏捷开发?

下一篇:如何优雅的使用“看板”?

相关热门文章
  • 支持移动3G网络手机推荐...
  • SAS vs SSD各种模式下MySQL TP...
  • linux 系统监控、诊断工具之 I...
  • gunicorn在terminal不显示信息...
  • 如何安全关闭MySQL进程...
  • 垂直搜索引擎之简单架构...
  • Nginx深入详解之日志
  • Haproxy、Keepalived双主高可...
  • socket中的短连接与长连接,心...
  • polo lacoste solde Pour sept...
  • 谁能够帮我解决LINUX 2.6 10...
  • 现在的博客积分不会更新了吗?...
  • shell怎么读取网页内容...
  • ssh等待连接的超时问题...
  • curl: (56) Recv failure: Con...
给主人留下些什么吧!~~
原创粉丝点击