MPD-DASH文件的结构

December 19, 2015

Periods

Periods包含在MPD元素的第一层,它用开始时间和持续时间来描述内容的一部分。一个场景或章节里可以有多个Periods, 也可以用来分离广告和正文内容。

Adaptation Sets

Adaptation Set 包含了一个媒体流或者一组媒体流,最简单的情况下,一个Period用一个Adaptation Set包含所有的视频和音频,但是为了减少带宽每个流可以分到独立的Adaptation Set里。常见做法就是一个视频流,多个音频流(多语言)。Adaptation Set也可以包含字母或者Arbitrary元信息。

Representation

Representation可以让一个Adaptation Set 通过不同的方式包含同一个内容。大部分情况下Representation用来提供不同屏幕尺寸和带宽,这样就可以让客户端在不缓冲的情况下选择最高的画质,并且不会浪费带宽来获取不需要的分辨率(720P的屏幕不需要1080P的画质)。Representation还可以用不同的编码,允许不同的客户端选择其支持的编码格式(比如浏览器中,有些支持MPEG-4AVC/H.264,另一些支持VP8),或者提供更高的质量的Representation给更新客户端,并且同时还支持老的(比如同时提供H264和H265)。多个编码格式在需要省电的设备上也很有用,有些设备可能会选择老的编码,因为它可以硬解(即便它可以软解更新的编码格式)。

Representation一般都是自动选择的,但是一些播放器允许用户指定他们的选择(特别是分辨率)。如果用户不想浪费带宽在某个视频上,可以选择他们想要的Representation(可能他只关注音频),或者他希望暂停视频来缓冲更高画质的视频。

SubRepresentation

SubRepresentation包含只应用到Representation中一个媒体流上的的信息。例如,如果一个Representation又有音频又有视频,那么它可以包含一个SubRepresentation来指定额外的只应用到音频上的信息。这些额外的信息可以是特定编码,采样率,嵌入字幕等。SubRepresentation也可以提供从多个容器里抽取一个流的必要信息,或者抽取出一个流的低质量版(比如只在快进模式下有用的I帧)

Media Segment

Media Segment是DASH客户端实际播放的媒体文件, 通常是一个接一个地播放,就好像他们是同一个文件一样(当然在切换Representation时要复杂的多)。格式问题会在我的另一篇关于profiles的文章中讲到,但是MPEG中描述的两个容器:ISO Base Media File Format(ISOBMFF)是和MPEG-4类似的容器格式;MPEG-TS。Dash里的WebM在这里描述http://wiki.webmproject.org/adaptive-streaming/webm-dash-specification

Media Segment的地址可以用BaseURL来描述一个单段Representation,Segment的列表或者模版(SegmentTemplate)。SegmentBase里的信息会应用到所有的segment上。Segment开始时间和持续时间可以用SegmentTimeline来描述(对于直播流特别重要,使客户端可以快速决定最新的一段)。这个信息也可以在MPD的更高层出现,这种情况下,这个信息主要提供的是默认的信息,除非XML结构的底层覆盖了这个信息。这一点是SegmentTemplate最有用的地方。

Segment可以在不同的文件里(直播中常用),也可以在一个文件里的字节范围(静态的”on-demand“常用)

Index Segment

Index Segment有两种类型:一个Representation用一个Presentation Index Segment,或者一个Media Segment配一个Single Index Segment。Presentation Index Segment永远是一个单独的文件,而Single Index Segment可以是同和Media Segment同一个文件的字节范围。

例子:

结束之间给一个注释过的MPD的例子,看看这些部分是怎么合在一起的:

<?xml version="1.0"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:full:2011" minBufferTime="PT1.5S">
    <!-- Ad -->
    <Period duration="PT30S">
        <BaseURL>ad/</BaseURL>
        <!-- Everything in one Adaptation Set -->
        <AdaptationSet mimeType="video/mp2t">
            <!-- 720p Representation at 3.2 Mbps -->
            <Representation id="720p" bandwidth="3200000" width="1280" height="720">
                <!-- Just use one segment, since the ad is only 30 seconds long -->
                <BaseURL>720p.ts</BaseURL>
                <SegmentBase>
                    <RepresentationIndex sourceURL="720p.sidx"/>
                </SegmentBase>
            </Representation>
            <!-- 1080p Representation at 6.8 Mbps -->
            <Representation id="1080p" bandwidth="6800000" width="1920" height="1080">
                <BaseURL>1080p.ts</BaseURL>
                <SegmentBase>
                    <RepresentationIndex sourceURL="1080p.sidx"/>
                </SegmentBase>
            </Representation>
        </AdaptationSet>
    </Period>
    <!-- Normal Content -->
    <Period duration="PT5M">
        <BaseURL>main/</BaseURL>
        <!-- Just the video -->
        <AdaptationSet mimeType="video/mp2t">
            <BaseURL>video/</BaseURL>
            <!-- 720p Representation at 3.2 Mbps -->
            <Representation id="720p" bandwidth="3200000" width="1280" height="720">
                <BaseURL>720p/</BaseURL>
                <!-- First, we'll just list all of the segments -->
                <!-- Timescale is "ticks per second", so each segment is 1 minute long -->
                <SegmentList timescale="90000" duration="5400000">
                    <RepresentationIndex sourceURL="representation-index.sidx"/>
                    <SegmentURL media="segment-1.ts"/>
                    <SegmentURL media="segment-2.ts"/>
                    <SegmentURL media="segment-3.ts"/>
                    <SegmentURL media="segment-4.ts"/>
                    <SegmentURL media="segment-5.ts"/>
                    <SegmentURL media="segment-6.ts"/>
                    <SegmentURL media="segment-7.ts"/>
                    <SegmentURL media="segment-8.ts"/>
                    <SegmentURL media="segment-9.ts"/>
                    <SegmentURL media="segment-10.ts"/>
                </SegmentList>
            </Representation>
            <!-- 1080p Representation at 6.8 Mbps -->
            <Representation id="1080p" bandwidth="6800000" width="1920" height="1080">
                <BaseURL>1080/</BaseURL>
                <!-- Since all of our segments have similar names, this time we'll use a SegmentTemplate -->
                <SegmentTemplate media="segment-$Number$.ts" timescale="90000">
                    <RepresentationIndex sourceURL="representation-index.sidx"/>
                    <!-- Let's add a SegmentTimeline so the client can easily see how many segments there are
                         -->
                    <SegmentTimeline>
                        <!-- This reads: Starting from time 0, there are 10 segments with a duration of
                             (5400000 / @timescale) seconds -->
                        <S t="0" r="10" d="5400000"/>
                    </SegmentTimeline>
                </SegmentTemplate>
            </Representation>
        </AdaptationSet>
        <!-- Just the audio -->
        <AdaptationSet mimeType="audio/mp2t">
            <BaseURL>audio/</BaseURL>
            <!-- We're just going to offer one audio representation, since audio bandwidth isn't very
                 important. -->
            <Representation id="audio" bandwidth="128000">
                <SegmentTemplate media="segment-$Number$.ts" timescale="90000">
                    <RepresentationIndex sourceURL="representation-index.sidx"/>
                    <SegmentTimeline>
                        <S t="0" r="10" d="5400000"/>
                    </SegmentTimeline>
                </SegmentTemplate>
            </Representation>
        </AdaptationSet>
    </Period>

</MPD>

总结

本文提供了足够的信息让你理解一个MPD文件的结构,以及一个DASH客户端工作的基本思想。下次,我会讨论一些额外的元数据,可以让客户端更加智能,并提供更好的用户体验。