深入理解DRM——直播流中的DRM

Posted zhanghui_cuc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解DRM——直播流中的DRM相关的知识,希望对你有一定的参考价值。

直播流中的DRM涉及到一个Key Rotation的概念,所谓key rotation就是加密内容的key可以随时间变化,一般用于直播流媒体,但是在点播中也是可能存在的(may be optional for VOD streams). 根据widevine文档,key rotation往往结合fragemented mp4格式使用,利用关键的moof和pssh(包含drm初始信息) box完成。

具体来说,client不停的从流中读moof以及包含在moof中的pssh,当发现pssh发生变化的时候,就意味着发生了key rotation.此时client就需要利用读到的新drm初始化信息进行key request.如下图所示:


举一个实例:假设现在我们有一个包含key rotation的dash流,已知他的key rotation周期是30s,首先来看一下他的mpd:

<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version d8d94da-release-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="dynamic" profiles="urn:mpeg:dash:profile:isoff-live:2011" publishTime="2017-01-03T10:50:57Z" availabilityStartTime="2017-01-03T10:00:21Z" minimumUpdatePeriod="PT5S" timeShiftBufferDepth="PT1800S">
<Period id="0" start="PT0S">
<AdaptationSet id="0" contentType="video" width="640" height="272" frameRate="90000/3003" segmentAlignment="true" par="40:17">
<Representation id="0" bandwidth="558059" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="00000000-0000-0000-0000-000000000000"/>
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"/>
<SegmentTemplate timescale="90000" initialization="live-video-sd_enc.mp4" media="live-video-sd_enc-$Number$.mp4" startNumber="125">
<SegmentTimeline>
<S t="111855744" d="900900" r="180"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" segmentAlignment="true">
<Representation id="1" bandwidth="130161" codecs="mp4a.40.2" mimeType="audio/mp4" audiosamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="00000000-0000-0000-0000-000000000000"/>
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"/>
<SegmentTemplate timescale="90000" initialization="live-audio_enc.mp4" media="live-audio_enc-$Number$.mp4" startNumber="125">
<SegmentTimeline>
<S t="111786240" d="900480" r="180"/>
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>

注意:在mpd中并没有特别的信息标识了key rotation周期,也不像非rotation的流那样直接把pssh信息写在mpd里面。

于是我们尝试拿到他的每一个媒体分片看看pssh是否真的有变化,因为每一个分片时长10s,所以我们拿前四个分片看看,用mp4dump工具导出box信息:

第一个:

[pssh] size=12+105
system_id = [ed ef 8b a9 79 d6 4a ce a3 c8 27 dc d5 1d 21 ed]
data_size = 85
data = [12 10 79 15 3b f7 9e 68 53 ef b7 7c 32 42 e8 26 d9 0b 12 10 fe fb 71 93 7c 09 55 85 9e b7 55 ba df b7 b0 a4 12 10 0d 6b 3c d3 bc af 59 1a 8e 1c 5d bf 01 5a be 61 1a 0d 77 69 64 65 76 69 6e 65 5f 74 65 73 74 22 04 32 32 32 32 38 00 48 e3 dc 95 9b 06 50 00]

第二个:

[pssh] size=12+105
system_id = [ed ef 8b a9 79 d6 4a ce a3 c8 27 dc d5 1d 21 ed]
data_size = 85
data = [12 10 79 15 3b f7 9e 68 53 ef b7 7c 32 42 e8 26 d9 0b 12 10 fe fb 71 93 7c 09 55 85 9e b7 55 ba df b7 b0 a4 12 10 0d 6b 3c d3 bc af 59 1a 8e 1c 5d bf 01 5a be 61 1a 0d 77 69 64 65 76 69 6e 65 5f 74 65 73 74 22 04 32 32 32 32 38 00 48 e3 dc 95 9b 06 50 00]

第三个:

[pssh] size=12+105
system_id = [ed ef 8b a9 79 d6 4a ce a3 c8 27 dc d5 1d 21 ed]
data_size = 85
data = [12 10 79 15 3b f7 9e 68 53 ef b7 7c 32 42 e8 26 d9 0b 12 10 fe fb 71 93 7c 09 55 85 9e b7 55 ba df b7 b0 a4 12 10 0d 6b 3c d3 bc af 59 1a 8e 1c 5d bf 01 5a be 61 1a 0d 77 69 64 65 76 69 6e 65 5f 74 65 73 74 22 04 32 32 32 32 38 00 48 e3 dc 95 9b 06 50 00]

第四个:

[pssh] size=12+105
system_id = [ed ef 8b a9 79 d6 4a ce a3 c8 27 dc d5 1d 21 ed]
data_size = 85
data = [12 10 25 13 0c 50 f9 df 55 d7 be 7a a8 f8 9a fc 38 c7 12 10 72 25 2f 04 13 38 51 a3 b6 b1 10 4b 05 b5 28 9a 12 10 ab 13 be 44 68 e5 5f de be 90 18 d5 23 13 3e 75 1a 0d 77 69 64 65 76 69 6e 65 5f 74 65 73 74 22 04 32 32 32 32 38 01 48 e3 dc 95 9b 06 50 00]

可见,确实以三个分片为周期变化pssh信息。

按照前面的介绍,只要每次读到新的pssh就利用其中的信息初始化新的mediadrm并开始随后的流程即可,但是在android中有两个问题:

1.每一个mediadrm session的生命周期中,只可以send一次initial license request,新的request就要新的mediadrm session来完成

2.每个mediacodec实例在初始化的时候都是和一个mediadrm session绑定在一起的,要来一个新的session就要重新初始化mediacodec,这就势必会带来播放中的卡顿.

为了解决这两个问题,widevine drmplugin提供了session-sharing模式,在该模式下,由一个mediadrm实例派生出的所有session可以共享彼此的key,而形成一个key pool的概念,通过这种形式,就不用重新将mediacodec和其他mediadrm session绑定在一起,也可以读到其他session中的key信息.打开session sharing模式非常简单,只需要如下的代码

MediaDrm md;
md.setPropertyString(“sessionSharing”, “enable”);

打开session sharing后,整个key rotation的调用流程如下:


需要注意的是:初始化mediacodec用到的那个session要最后才能关闭.

欢迎关注我的公众号灰度五十,分享各类音视频、移动开发知识~

文章帮到你了?可以扫描如下二维码进行打赏,打赏多少您随意~

以上是关于深入理解DRM——直播流中的DRM的主要内容,如果未能解决你的问题,请参考以下文章

深入理解DRM——了解Widevine与OEMCrypto

深入理解DRM——MediaDRM和MediaCrypto

Azure 媒体服务 Fairplay V3 DRM 内容密钥策略

Nouveau源代码分析:NVIDIA设备初始化之nouveau_drm_probe

如何将破折号 DRM 许可证添加到 m3u 播放列表?

基于arm5718ARM-Linux开发DRM学习