Closed winlinvip closed 1 year ago
DASH is becoming more and more popular in some countries.
SRS will support MPEG-DASH in this Chinese New Year holiday.
DASH in wikipedia. The segment of DASH can use MP4 or TS file. The DASH players include ExoPlayer for Android, MSE for H5(js), THEOPlayer, VIDEOJS, dash.js and dashif or dash industry forum. The Helix(RealNetwork), NGINX-RTMP and WOWZA servers already support transmux RTMP to DASH.
Remark: The VLC can't play DASH.
The dashif show us a example: http://dash.edgesuite.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd Or mirror on ossrs.net: http://ossrs.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd The dash.js mirror on ossrs.net: http://ossrs.net/dash.js/samples/dash-if-reference-player/
DASH HelloWorld, Use dash.js player to play:
http://ossrs.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd
http://ossrs.net/akamai/streamroot/050714/Spring_4Ktest.mpd
Most of these demos use mp4 format, not ts.
ISOM(ISO base media file): doc/ISO_IEC_14496-12-base-format-2012.pdf
DASH: doc/ISO_IEC_23009-1-DASH-2012.pdf
MP42(MP4 file format): doc/ISO_IEC_14496-14-MP4-2003.pdf
ESDS/ES_Descriptor: doc/ISO_IEC_14496-1-System-2010.pdf
M4V by Apple: qt
Remark: The mp4 14496-14-2003 is brand
mp42
, while FFMPEG useisom
which compatible withmp41
.
Part 1: Systems
Part 2: Visual
Part 3: Audio
Part 4: Conformance testing
Part 5: Reference software
Part 6: Delivery Multimedia Integration Framework (DMIF)
Part 7: Optimized reference software for coding of audio-visual objects
Part 8: Carriage of ISO/IEC 14496 contents over IP networks
Part 9: Reference hardware description
Part 10: Advanced Video Coding (AVC)
Part 11: Scene description and application engine
Part 12: ISO base media file format
Part 13: Intellectual Property Management and Protection (IPMP) extensions
Part 14: MP4 file format
Part 15: Advanced Video Coding (AVC) file format
Part 16: Animation Framework eXtension (AFX)
https://github.com/Bilibili/ijkplayer also supports dash and runs on iOS and Android, but offers a host of other functionality like RTMP seek.
We must fix #738 to support mp4 muxer first.
http://ossrs.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd
* 150kbps: ElephantsDream_H264BPL30_0100.264.dash
* 250kbps: ElephantsDream_H264BPL30_0175.264.dash
* 350kbps: ElephantsDream_H264BPL30_0250.264.dash
* 750kbps: ElephantsDream_H264BPL30_0500.264.dash
Use fmp4(fragmented mp4) for each stream is a big mp4 file.
http://ossrs.net/akamai/streamroot/050714/Spring_4Ktest.mpd
* 2.8mbps: Spring_3000k_track1_dashinit.mp4
* 4.8mbps: Spring_5000k_track1_dashinit.mp4
* 7.3mbps: Spring_7500k_track1_dashinit.mp4
* 9.6mbps: Spring_10000k_track1_dashinit.mp4
* 14.6mbps: Spring_15000k_track1_dashinit.mp4
* 19.6mbps: Spring_20000k_track1_dashinit.mp4
Each mp4 is big file using fmp4 format.
http://ossrs.net/dash/streams/gpac/mp4-main-multi-mpd-AV-NBS.mpd
mp4-main-multi-h264bl_low-.mp4 plus mp4-main-multi-h264bl_low-{1-60}.m4s
mp4-main-multi-h264bl_hd-.mp4 plus mp4-main-multi-h264bl_hd-{1-60}.m4s
mp4-main-multi-h264bl_full-.mp4 plus mp4-main-multi-h264bl_full-{1-60}.m4s
Each stream has a mp4 header file, and m4s stream files.
I found DASH use brand iso2
compatible with isom
and dash
, and use fmp4(fragmented mp4):
While FFMPEG use brand isom
compatible with iso2
:
The 'isom' requirements are a subset of the 'iso2' requirements.
I must support isom
for general mp4 format, then support dvr to mp4 file, then support fmp4, finally support dash over fmp4.
TRANS_BY_GPT3
Besides general mp4 format is fine(see #738), we can focus to fmp4 now.
About the DASH MPD:
G.2 Example for ISO Base media file format Live profile
ISO_IEC_23009-1-DASH-2012.pdf, page 126
<BaseURL>http://cdn1.example.com/</BaseURL>
<BaseURL>http://cdn2.example.com/</BaseURL>
Table 3 - Semantics of MPD element. BaseURL 0...N specifies a Base URL that can be used for reference resolution and alternative URL selection. For more details refer to the description in 5.6.
5.6.5 Alternative base URLs If alternative base URLs are provided through the BaseURL element at any level, identical Segments shall be accessible at multiple locations. In the absence of other criteria, the DASH Client may use the first BaseURL element as the "base URI". The DASH Client may use base URLs provided in the BaseURL element as the "base URI" and may implement any suitable action. algorithm to determine which URLs it uses for requests.
2. Timeshift:
G.2 Example for ISO Base media file format Live profile ISO_IEC_23009-1-DASH-2012.pdf, page 126 timeShiftBufferDepth="PT30M"
Table 3 - Meaning of MPD element. @timeShiftBufferDepth specifies the duration of the time shifting buffer that is guaranteed to be available for a Media Presentation with type 'dynamic'. When not present, the value is Infinite. This attribute value is not applicable if the type attribute is equal to 'static'.
To setup the playhead when startup:
G.2 Example for ISO Base media file format Live profile ISO_IEC_23009-1-DASH-2012.pdf, page 126 availabilityStartTime="2011-12-25T12:30:00"
At the time this MPD was fetched, 432 Segments of the dynamic presentation were available so the wall clock time must have been approximately 2011-12-25T12:44:24 UTC.
http://vm2.dashif.org/livesim/mup_30/testpic_2s/Manifest.mpd
<?xml version="1.0" encoding="utf-8"?>
<MPD availabilityStartTime="1970-01-01T00:00:00Z"
id="Config part of url maybe?" maxSegmentDuration="PT2S"
minBufferTime="PT2S" minimumUpdatePeriod="PT30S"
profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple"
publishTime="2017-02-18T07:03:07Z" timeShiftBufferDepth="PT5M"
type="dynamic" ns1:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance">
<ProgramInformation>
<Title>Media Presentation Description from DASHI-IF live simulator</Title>
</ProgramInformation>
<BaseURL>http://vm2.dashif.org/livesim/mup_30/testpic_2s/</BaseURL>
<Period id="p0" start="PT0S">
<AdaptationSet contentType="audio" lang="eng"
mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4"
media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation audioSamplingRate="48000" bandwidth="48000"
codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration value="2"
schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2"
maxHeight="360" maxWidth="640" mimeType="video/mp4"
minHeight="360" minWidth="640" par="16:9" segmentAlignment="true"
startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4"
media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation bandwidth="300000" codecs="avc1.64001e"
frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
</MPD>
http://ossrs.net/dash264/TestCases/1a/netflix/exMPD_BIP_TC1.mpd
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd"
type="static"
mediaPresentationDuration="PT654S"
minBufferTime="PT4S"
profiles="http://dashif.org/guidelines/dash264,urn:mpeg:dash:profile:isoff-on-demand:2011">
<BaseURL>http://ossrs.net/dash264/TestCases/1a/netflix/</BaseURL>
<Period>
<!-- English Audio -->
<AdaptationSet mimeType="audio/mp4" codecs="mp4a.40.5" lang="en" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
<Representation id="1" bandwidth="72000">
<BaseURL>ElephantsDream_AAC48K_064.mp4.dash</BaseURL>
</Representation>
</AdaptationSet>
<!-- Video -->
<AdaptationSet mimeType="video/mp4" codecs="avc1.42401E" subsegmentAlignment="true" subsegmentStartsWithSAP="1" contentType='video' maxWidth="480" maxHeight="360" maxFrameRate="24" par="4:3">
<Representation id="2" bandwidth="150000" width="480" height="360" frameRate="24" sar="1:1">
<BaseURL>ElephantsDream_H264BPL30_0100.264.dash</BaseURL>
</Representation>
<Representation id="3" bandwidth="250000" width="480" height="360" frameRate="24" sar="1:1">
<BaseURL>ElephantsDream_H264BPL30_0175.264.dash</BaseURL>
</Representation>
<Representation id="4" bandwidth="350000" width="480" height="360" frameRate="24" sar="1:1">
<BaseURL>ElephantsDream_H264BPL30_0250.264.dash</BaseURL>
</Representation>
<Representation id="5" bandwidth="750000" width="480" height="360" frameRate="24" sar="1:1">
<BaseURL>ElephantsDream_H264BPL30_0500.264.dash</BaseURL>
</Representation>
</AdaptationSet>
</Period>
</MPD>
http://ossrs.net/dash/streams/gpac/mp4-main-multi-mpd-AV-NBS.mpd
<?xml version="1.0"?>
<!-- MPD file Generated with GPAC version 0.5.1-DEV-rev4193 -->
<MPD type="static" xmlns="urn:mpeg:DASH:schema:MPD:2011" minBufferTime="PT1.5S" mediaPresentationDuration="PT0H10M0.00S" profiles="urn:mpeg:dash:profile:isoff-main:2011">
<ProgramInformation moreInformationURL="http://gpac.sourceforge.net">
<Title>mp4-main-multi-mpd-AV-NBS.mpd generated by GPAC</Title>
<Copyright>TelecomParisTech(c)2012</Copyright>
</ProgramInformation>
<Period start="PT0S" duration="PT0H10M0.00S">
<AdaptationSet segmentAlignment="true" maxWidth="1920" maxHeight="1080" maxFrameRate="25" par="16:9">
<ContentComponent id="1" contentType="video"/>
<Representation id="h264bl_low" mimeType="video/mp4" codecs="avc1.42c00d" width="320" height="180" frameRate="25" sar="1:1" startWithSAP="1" bandwidth="50877">
<SegmentList timescale="1000" duration="10000">
<Initialization sourceURL="mp4-main-multi-h264bl_low-.mp4"/>
<SegmentURL media="mp4-main-multi-h264bl_low-1.m4s"/>
<SegmentURL media="mp4-main-multi-h264bl_low-2.m4s"/>
</SegmentList>
</Representation>
<Representation id="h264bl_mid" mimeType="video/mp4" codecs="avc1.42c01e" width="640" height="360" frameRate="25" sar="1:1" startWithSAP="1" bandwidth="194870">
<SegmentList timescale="1000" duration="10000">
<Initialization sourceURL="mp4-main-multi-h264bl_mid-.mp4"/>
<SegmentURL media="mp4-main-multi-h264bl_mid-1.m4s"/>
<SegmentURL media="mp4-main-multi-h264bl_mid-2.m4s"/>
</SegmentList>
</Representation>
<Representation id="h264bl_hd" mimeType="video/mp4" codecs="avc1.42c01f" width="1280" height="720" frameRate="25" sar="1:1" startWithSAP="1" bandwidth="514828">
<SegmentList timescale="1000" duration="10000">
<Initialization sourceURL="mp4-main-multi-h264bl_hd-.mp4"/>
<SegmentURL media="mp4-main-multi-h264bl_hd-1.m4s"/>
<SegmentURL media="mp4-main-multi-h264bl_hd-2.m4s"/>
</SegmentList>
</Representation>
<Representation id="h264bl_full" mimeType="video/mp4" codecs="avc1.42c028" width="1920" height="1080" frameRate="25" sar="1:1" startWithSAP="1" bandwidth="770699">
<SegmentList timescale="1000" duration="10000">
<Initialization sourceURL="mp4-main-multi-h264bl_full-.mp4"/>
<SegmentURL media="mp4-main-multi-h264bl_full-1.m4s"/>
<SegmentURL media="mp4-main-multi-h264bl_full-2.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
<AdaptationSet segmentAlignment="true" lang="und">
<ContentComponent id="1" contentType="audio" lang="und"/>
<Representation id="aaclc_low" mimeType="audio/mp4" codecs="mp4a.40.2" audioSamplingRate="44100" lang="und" startWithSAP="1" bandwidth="19079">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="1"/>
<SegmentList timescale="1000" duration="9520">
<Initialization sourceURL="mp4-main-multi-aaclc_low-.mp4"/>
<SegmentURL media="mp4-main-multi-aaclc_low-1.m4s"/>
<SegmentURL media="mp4-main-multi-aaclc_low-2.m4s"/>
</SegmentList>
</Representation>
<Representation id="aaclc_high" mimeType="audio/mp4" codecs="mp4a.40.2" audioSamplingRate="44100" lang="und" startWithSAP="1" bandwidth="66378">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="1"/>
<SegmentList timescale="1000" duration="9520">
<Initialization sourceURL="mp4-main-multi-aaclc_high-.mp4"/>
<SegmentURL media="mp4-main-multi-aaclc_high-1.m4s"/>
<SegmentURL media="mp4-main-multi-aaclc_high-2.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
</Period>
</MPD>
http://ossrs.net/akamai/streamroot/050714/Spring_4Ktest.mpd
<?xml version="1.0"?>
<!-- MPD file Generated with GPAC version 0.5.1-DEV-rev5208 on 2014-05-08T15:14:47Z-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H2M45.76S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
<ProgramInformation moreInformationURL="http://gpac.sourceforge.net">
<Title>Spring_3000k_dash.mpd generated by GPAC</Title>
</ProgramInformation>
<Period id="" duration="PT0H2M45.76S">
<AdaptationSet segmentAlignment="true" maxWidth="3840" maxHeight="2160" maxFrameRate="24000/1001" par="16:9" subsegmentStartsWithSAP="1">
<Representation id="1" mimeType="video/mp4" codecs="avc1.640033" width="1280" height="720" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="2859078">
<BaseURL>Spring_3000k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="896-1419"/>
</Representation>
<Representation id="2" mimeType="video/mp4" codecs="avc1.640033" width="1920" height="1080" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="4872811">
<BaseURL>Spring_5000k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="896-1419"/>
</Representation>
<Representation id="3" mimeType="video/mp4" codecs="avc1.640033" width="2880" height="1620" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="7322004">
<BaseURL>Spring_7500k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="897-1420"/>
</Representation>
<Representation id="4" mimeType="video/mp4" codecs="avc1.640033" width="3840" height="2160" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="9604428">
<BaseURL>Spring_10000k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="896-1419"/>
</Representation>
<Representation id="5" mimeType="video/mp4" codecs="avc1.640033" width="3840" height="2160" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="14658452">
<BaseURL>Spring_15000k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="896-1419"/>
</Representation>
<Representation id="6" mimeType="video/mp4" codecs="avc1.640033" width="3840" height="2160" frameRate="24000/1001" sar="1:1" startWithSAP="1" bandwidth="19683583">
<BaseURL>Spring_20000k_track1_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="896-1419"/>
</Representation>
</AdaptationSet>
<AdaptationSet segmentAlignment="true" subsegmentStartsWithSAP="1">
<Representation id="7" mimeType="audio/mp4" codecs="mp4a.40.2" audioSamplingRate="48000" startWithSAP="1" bandwidth="193664">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>Spring_3000k_track2_dashinit.mp4</BaseURL>
<SegmentBase indexRangeExact="true" indexRange="823-1262"/>
</Representation>
</AdaptationSet>
</Period>
</MPD>
http://ossrs.net/livesim/mup_30/testpic_2s/Manifest.mpd
<?xml version="1.0" encoding="utf-8"?>
<MPD availabilityStartTime="1970-01-01T00:00:00Z" id="Config part of url maybe?" maxSegmentDuration="PT2S" minBufferTime="PT2S" minimumUpdatePeriod="PT30S" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" publishTime="2017-02-18T07:03:07Z" timeShiftBufferDepth="PT5M" type="dynamic" ns1:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance">
<ProgramInformation>
<Title>Media Presentation Description from DASHI-IF live simulator</Title>
</ProgramInformation>
<BaseURL>http://vm2.dashif.org/livesim/mup_30/testpic_2s/</BaseURL>
<Period id="p0" start="PT0S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
</MPD>
http://ossrs.net/loop/loop.isml/loop.mpd
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Unified Streaming Platform(version=1.7.27) -->
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:up="urn:mpeg:dash:schema:urlparam:2014"
type="dynamic"
availabilityStartTime="1970-01-01T00:00:00Z"
publishTime="2017-02-10T06:58:28.766121Z"
minimumUpdatePeriod="PT2S"
timeShiftBufferDepth="PT57.797098S"
maxSegmentDuration="PT4S"
minBufferTime="PT10S"
profiles="urn:mpeg:dash:profile:isoff-live:2011">
<EssentialProperty
schemeIdUri="urn:mpeg:dash:urlparam:2014">
<up:UrlQueryInfo
queryString="session_id=25020" />
</EssentialProperty>
<Period
id="1"
start="PT0S">
<BaseURL>dash/</BaseURL>
<AdaptationSet
group="1"
contentType="audio"
minBandwidth="128000"
maxBandwidth="128000"
segmentAlignment="true"
audioSamplingRate="44100"
mimeType="audio/mp4"
codecs="mp4a.40.2"
startWithSAP="1">
<AudioChannelConfiguration
schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
value="2">
</AudioChannelConfiguration>
<Role
schemeIdUri="urn:mpeg:dash:role:2011"
value="main">
</Role>
<SegmentTemplate
timescale="44100"
initialization="loop-$RepresentationID$.dash"
media="loop-$RepresentationID$-$Time$.dash">
<!-- 2017-02-09T16:01:11.196009Z / 1486656071 - 2017-02-09T16:02:08.993106Z -->
<SegmentTimeline>
<S t="65561532739744" d="169984" />
<S d="168960" r="1" />
<S d="169984" />
<S d="168960" />
<S d="169984" />
<S d="3072" />
<S t="65561533764428" d="169416" />
<S d="169984" />
<S d="168960" />
<S d="169984" />
<S d="168960" r="1" />
<S d="169984" />
<S d="168960" r="1" />
</SegmentTimeline>
</SegmentTemplate>
<Representation
id="audio=128000"
bandwidth="128000">
</Representation>
</AdaptationSet>
<AdaptationSet
group="2"
contentType="video"
par="16:9"
minBandwidth="412000"
maxBandwidth="2070000"
minWidth="400"
maxWidth="1280"
minHeight="225"
maxHeight="720"
segmentAlignment="true"
mimeType="video/mp4"
startWithSAP="1">
<Role
schemeIdUri="urn:mpeg:dash:role:2011"
value="main">
</Role>
<SegmentTemplate
timescale="1000"
initialization="loop-$RepresentationID$.dash"
media="loop-$RepresentationID$-$Time$.dash">
<!-- 2017-02-09T16:01:11.191000Z / 1486656071 - 2017-02-09T16:02:12.831000Z -->
<SegmentTimeline>
<S t="1486656071191" d="3840" r="5" />
<S d="200" />
<S d="3840" r="9" />
</SegmentTimeline>
</SegmentTemplate>
<Representation
id="video=412000"
bandwidth="412000"
width="400"
height="224"
sar="224:225"
codecs="avc1.42C014"
scanType="progressive">
</Representation>
<Representation
id="video=823000"
bandwidth="823000"
width="704"
height="396"
sar="1:1"
codecs="avc1.42C01E"
scanType="progressive">
</Representation>
<Representation
id="video=2070000"
bandwidth="2070000"
width="1280"
height="720"
sar="1:1"
codecs="avc1.42C01F"
scanType="progressive">
</Representation>
</AdaptationSet>
</Period>
</MPD>
The Media Presentation conforms to the ISO Base media file format Live profile in 8.4.
<?xml version="1.0"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:DASH:schema:MPD:2011" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" type="dynamic"
minimumUpdatePeriod="PT2S" timeShiftBufferDepth="PT30M" availabilityStartTime="2011-12-25T12:30:00" minBufferTime="PT4S" profiles="urn:mpeg:dash:profile:isoff-live:2011">
<BaseURL>http://cdn1.example.com/</BaseURL> <BaseURL>http://cdn2.example.com/</BaseURL>
<Period>
<!-- Video -->
<AdaptationSet
mimeType="video/mp4"
codecs="avc1.4D401F"
frameRate="30000/1001"
segmentAlignment="true"
startWithSAP="1">
<BaseURL>video/</BaseURL>
<SegmentTemplate timescale="90000" initialization="$Bandwidth%/init.mp4v"
media="$Bandwidth%/$Time$.mp4v"> <SegmentTimeline>
<S t="0" d="180180" r="432"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="v0" width="320" height="240" bandwidth="250000"/> <Representation id="v1" width="640" height="480" bandwidth="500000"/> <Representation id="v2" width="960" height="720" bandwidth="1000000"/>
</AdaptationSet>
<!-- English Audio -->
<AdaptationSet mimeType="audio/mp4" codecs="mp4a.0x40" lang="en" segmentAlignment="0" startWithSAP="1">
<SegmentTemplate timescale="48000" initialization="audio/en/init.mp4a" media="audio/en/$Time$.mp4a">
<SegmentTimeline>
<S t="0" d="96000" r="432"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="a0" bandwidth="64000" />
</AdaptationSet>
<!-- French Audio -->
<AdaptationSet mimeType="audio/mp4" codecs="mp4a.0x40" lang="fr" segmentAlignment="0" startWithSAP="1">
<SegmentTemplate timescale="48000" initialization="audio/fr/init.mp4a" media="audio/fr/$Time$.mp4a">
<SegmentTimeline>
<S t="0" d="96000" r="432"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="a0" bandwidth="64000" />
</AdaptationSet> </Period>
</MPD>
There is no mp4 parser CLI, I must write one, to show each box, to analysis whether mp4 structure is fine.f
👍
The init.mp4 and *.m2ts segment files, we can parse by the CLI:
./objs/srs_mp4_parser html/dash/testpic_2s/V300/743408904.m4s
html/dash/testpic_2s/V300/743408904.m4s
styp, 24B, brands:msdh,0(msdh,dash)
moof, 1048B, 2 boxes
mfhd, 16B, FB(4B), sequence=743408904
traf, 1024B, 3 boxes
tfhd, 16B, FB(4B,V0,0x20000), track=2, moof-base
tfdt, 20B, FB(4B,V1,0x00), bmdt=133813602720000
trun, 980B, FB(4B,V0,0xf01), samples=60, data-offset=1056
duration=3000, size=7319, flags=33554432, cts=6000
duration=3000, size=597, flags=16777216, cts=15000
duration=3000, size=371, flags=16777216, cts=6000
duration=3000, size=218, flags=16777216, cts=0
duration=3000, size=266, flags=16777216, cts=3000
duration=3000, size=438, flags=16777216, cts=15000
duration=3000, size=327, flags=16777216, cts=6000
duration=3000, size=297, flags=16777216, cts=0
mdat, 37692B, total 37684 bytes
To show all samples of trun:
./objs/srs_mp4_parser html/dash/testpic_2s/V300/743408904.m4s -v 2>&1|grep size
duration=3000, size=7319, flags=33554432, cts=6000
duration=3000, size=597, flags=16777216, cts=15000
duration=3000, size=371, flags=16777216, cts=6000
...............................................................
duration=3000, size=270, flags=16777216, cts=6000
duration=3000, size=307, flags=16777216, cts=0
Sum the size:
./objs/srs_mp4_parser html/dash/testpic_2s/V300/743408904.m4s \
-v 2>&1|grep size|awk '{print $2}'|awk -F '=' '{print $2}'|\
awk -F ',' '{print $1}'|awk '{s+=$1}END{print s}'
37684
So each one of samples is described in trun. For writing MP4 mdat, read https://github.com/ossrs/srs/issues/738#issuecomment-306014068.
Use SRS3+, config is:
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_server {
enabled on;
listen 8080;
}
vhost __defaultVhost__ {
ingest livestream {
enabled on;
input {
type file;
url ./doc/source.200kbps.768x320.flv;
}
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
engine {
enabled off;
output rtmp://127.0.0.1:[port]/live?vhost=[vhost]/livestream;
}
}
dash {
enabled on;
dash_fragment 30;
dash_update_period 150;
dash_timeshift 300;
}
}
Use player: http://ossrs.net/dash.js/samples/dash-if-reference-player/ Play url: http://localhost:8080/live/livestream.mpd
Or open the player: http://ossrs.net/dash.js/samples/dash-if-reference-player/?url=http://localhost:8080/live/livestream.mpd
The player reports the error, but it's very hard to trace it:
Seeking to: 1496576739
Top qualityaudio index has changed from undefined to 0
AbrController (audio) stay on 0/0 (buffer: 0)
Getting the request for audio time : 1496576739
Index for audio time 1496576739 is 498858912
SegmentTemplate: 1496576736 / Infinity
Video Element Error: MEDIA_ERR_DECODE
[object MediaError]
Schedule controller stopping for video
Schedule controller stopping for audio
I release this feature as Experimental
, util anyone who can fix the issue of player(or indicates what happened and how to fix the fmp4 encoder)
Live example from FFMPEG#7382:
https://livesim.dashif.org/livesim/periods_60/continuous_1/testpic_2s/Manifest.mpd
<?xml version="1.0" encoding="utf-8"?>
<MPD availabilityStartTime="1970-01-01T00:00:00Z" id="Config part of url maybe?" maxSegmentDuration="PT2S" minBufferTime="PT2S" minimumUpdatePeriod="PT25S" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" publishTime="2019-12-27T03:27:37Z" timeShiftBufferDepth="PT5M" type="dynamic" ns1:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance">
<ProgramInformation>
<Title>Media Presentation Description from DASH-IF live simulator</Title>
</ProgramInformation>
<BaseURL>https://livesim.dashif.org/livesim/sts_1577417238/sid_4a6eb645/periods_60/continuous_1/testpic_2s/</BaseURL>
<Period id="p26290282" start="PT1577416920S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577416920" startNumber="788708460" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577416920" startNumber="788708460" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290283" start="PT1577416980S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290282" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577416980" startNumber="788708490" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290282" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577416980" startNumber="788708490" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290284" start="PT1577417040S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290283" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417040" startNumber="788708520" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290283" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417040" startNumber="788708520" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290285" start="PT1577417100S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290284" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417100" startNumber="788708550" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290284" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417100" startNumber="788708550" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290286" start="PT1577417160S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290285" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417160" startNumber="788708580" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290285" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417160" startNumber="788708580" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290287" start="PT1577417220S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290286" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417220" startNumber="788708610" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290286" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417220" startNumber="788708610" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
<Period id="p26290288" start="PT1577417280S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290287" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417280" startNumber="788708640" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:period_continuity:2014" value="p26290287" />
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" presentationTimeOffset="1577417280" startNumber="788708640" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
</MPD>
Live stream:
https://livesim.dashif.org/livesim/testpic_2s/Manifest.mpd
https://livesim.dashif.org/livesim/sts_1577417658/sid_6953a24f/testpic_2s/Manifest.mpd
<?xml version="1.0" encoding="utf-8"?>
<MPD availabilityStartTime="1970-01-01T00:00:00Z" id="Config part of url maybe?" maxSegmentDuration="PT2S" minBufferTime="PT2S" minimumUpdatePeriod="P100Y" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" publishTime="2019-12-27T03:34:28Z" timeShiftBufferDepth="PT5M" type="dynamic" ns1:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance">
<ProgramInformation>
<Title>Media Presentation Description from DASH-IF live simulator</Title>
</ProgramInformation>
<BaseURL>https://livesim.dashif.org/livesim/sts_1577417658/sid_6953a24f/testpic_2s/</BaseURL>
<Period id="p0" start="PT0S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
</MPD>
Use online mp4box to parse fmp4/m4s: http://download.tsi.telecom-paristech.fr/gpac/mp4box.js/filereader.html
https://livesim.dashif.org/livesim/mup_30/testpic_2s/Manifest.mpd
https://livesim.dashif.org/livesim/sts_1577438849/sid_24086ba5/mup_30/testpic_2s/Manifest.mpd
<?xml version="1.0" encoding="utf-8"?>
<MPD availabilityStartTime="1970-01-01T00:00:00Z" id="Config part of url maybe?" maxSegmentDuration="PT2S" minBufferTime="PT2S" minimumUpdatePeriod="PT30S" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" publishTime="2019-12-27T09:27:48Z" timeShiftBufferDepth="PT5M" type="dynamic" ns1:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:ns1="http://www.w3.org/2001/XMLSchema-instance">
<ProgramInformation>
<Title>Media Presentation Description from DASH-IF live simulator</Title>
</ProgramInformation>
<BaseURL>https://livesim.dashif.org/livesim/sts_1577438849/sid_24086ba5/mup_30/testpic_2s/</BaseURL>
<Period id="p0" start="PT0S">
<AdaptationSet contentType="audio" lang="eng" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation audioSamplingRate="48000" bandwidth="48000" codecs="mp4a.40.2" id="A48">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
</Representation>
</AdaptationSet>
<AdaptationSet contentType="video" maxFrameRate="60/2" maxHeight="360" maxWidth="640" mimeType="video/mp4" minHeight="360" minWidth="640" par="16:9" segmentAlignment="true" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
<Representation bandwidth="300000" codecs="avc1.64001e" frameRate="60/2" height="360" id="V300" sar="1:1" width="640" />
</AdaptationSet>
</Period>
</MPD>
The main reason for the DASH failure before discovery in SRS is the data offset of the turn box, which actually only includes the length of the moof and mdat headers.
Thanks to Master Brother's FFMPEG, for example, the segments generated by ffmpeg:
09d8d5e3210 ffmpeg]# /tmp/srs/trunk/objs/srs_mp4_parser chunk-stream0-00002.m4s
styp, 24B, brands:msdh,0(msdh,msix)
sidx, 52B, v1, flags=0, refs#1, TBN=12800, ePTS=189517
#0, ref=0/301000, duration=149504, SAP=1/0/0
moof, 3604B, 2 boxes
mfhd, 16B, FB(4B), sequence=2
traf, 3580B, 3 boxes
tfhd, 28B, FB(4B,V0,0x20038), track=1, dsu=512, dss=3685, dsf=16842752, moof-base
tfdt, 20B, FB(4B,V1,0x00), bmdt=188928
trun, 3524B, FB(4B,V0,0xe01), samples=292, data-offset=3612
, size=3685, flags=33554432, cts=1024
, size=1768, flags=16842752, cts=1024
, size=1928, flags=16842752, cts=1024
, size=1678, flags=16842752, cts=1024
, size=113, flags=16842752, cts=1024
, size=1227, flags=16842752, cts=1024
, size=1808, flags=16842752, cts=1024
, size=1170, flags=16842752, cts=1024
mdat, 297396B, total 297388 bytes
Its data_offset is 3612 = moof (3604B) + mdat-header (8B).
It can be played after modification.
Additionally, another issue has been fixed. Slices need to be continuous, previously there were occasional timestamp alignment issues with slice numbers, resulting in jumps and causing failures for dash.js to locate the slice. However, it can easily lead to AV (audio-visual) synchronization issues, so this problem still needs to be further addressed and fixed in detail.
Of course, several DASH bugs have also been fixed, including a crash. Currently, after these changes (sidx box synchronization still needs to be added), DASH has basically met the requirements for Experimental features. https://github.com/ossrs/srs/commit/d11a7b2e00792c46dcc4d9a8e4041c4db092e787
TRANS_BY_GPT3
sidx box has been added, and when the slice is large, the slice continuity and av synchronization issues are not significant. For the protocol of separating av slicing, as well as the protocol that the player strictly relies on the continuity of slicing numbers, these two stupid restrictions make av synchronization and slicing mechanism more complex.
TRANS_BY_GPT3
At present, the main issue with DASH is that there is a problem with finding a slice. This is because DASH live streaming generates slice file names based on time and sometimes there can be cumulative errors, which result in the inability to generate a file at a specific time point.
HLS solves this problem using m3u8, which does not correspond to time.
Perhaps it is better to generate empty segments, as the player will freeze if it cannot find any segments.
DASH is really ridiculous.
TRANS_BY_GPT3
Segment has three XML formats, which are BaseURL (single segment representation), SegmentList (segment list), and SegmentTemplate (segment template). Among them, BaseURL and SegmentList are not suitable for live streaming due to their designed formats, so SegmentTemplate is commonly used for live streaming.
SegmentTemplate supports two modes, one is the $Number$ mode, and the other is the $Time$ mode. The $Number$ mode requires the player's system clock to be consistent with the server's system clock. If they are not synchronized, it may result in playback failure or excessive content delay. Therefore, the commonly used mode is the $Time$ mode.
<MPD availabilityStartTime="2021-10-01T00:00:00Z" ...omission>
<Period ...omission>
<AdaptationSet ...omission>
<Representation ...omission>
<SegmentTemplate timescale="90000" duration="180000" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0"/>
</Representation>
</AdaptationSet>
...omission
</Period>
</MPD>
The format of the $Number$ pattern is shown above. To calculate the $Number$ value of the Segment, it relies on the current system time of the player, availabilityStartTime, timescale, duration, and startNumber fields. The current value of $Number$ is calculated as ((current system time of the player - availabilityStartTime)/(duration/timescale))+startNumber.
According to the calculation rules, it can be understood that if the player's system time is too small/slightly small/too large compared to the server, it will result in problems such as inability to calculate/requesting an outdated segment/requesting a future segment, etc.
<MPD ...omitted>
<Period ...omitted>
<AdaptationSet ...omitted>
<Representation ...omitted>
<SegmentTemplate initialization="$RepresentationID$_init.m4s" media="$RepresentationID$_t$Time$.m4s" timescale="90000">
<SegmentTimeline>
<S d="178470" t="147060849589200" />
<S d="178470" t="147060849767670" />
<S d="178380" t="147060849946140" />
</SegmentTimeline>
</Representation>
</AdaptationSet>
...omitted
</Period>
</MPD>
The format of the $Time$ mode is as shown above. Each S under SegmentTimeline corresponds to a Segment. The $Time$ value of its fragments is the t value in S. Not only is it simple, but it also only requires the MPD content to calculate the filename of each fragment, without relying on the player's segment system clock. Therefore, the $Time$ mode is more commonly used.
Previously, we were using the Number mode, which caused some issues. Switching to the Time mode solved the problem.
Update: Zhihong Master said that the compatibility of the Time mode is also not good. Currently, the issue of not being able to find the slice has been fixed under the Number mode.
TRANS_BY_GPT3
Give a simple explanation of some key points about DASH, mainly the daunting mpd file with numerous fields and combinations.
One major feature of the DASH protocol is mapping the time slices of audio and video to UTC time, allowing for real-time streaming and the selection of appropriate segments for playback.
<?xml version="1.0" encoding="utf-8"?>
<MPD ...>
<Period start="PT0S">
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="audio" bandwidth="48000" codecs="mp4a.40.2">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Number$.m4s" duration="5000" timescale="1000">
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="video" bandwidth="800000" codecs="avc1.64001e" width="1280" height="720">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Number$.m4s" duration="5000" timescale="1000">
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
In this kind of MPD, since there is no explicit indication of segment information, the player needs to calculate the current segment number.
$Number$ = (currentUTCTime - availabilityStartTime) * timesacle / duration + startNumber
Due to inaccuracies in the clock or deviations caused by differences between the declared and actual segment durations, long-term streaming may result in audio-video desynchronization or incorrect calculation of segment numbers.
<?xml version="1.0" encoding="utf-8"?>
<MPD ...>
<Period start="PT0S">
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="audio" bandwidth="48000" codecs="mp4a.40.2">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Number$.m4s" startNumber="2898" timescale="1000">
<SegmentTimeline>
<S t="100" d="4907" />
<S t="5007" d="5013" />
<S t="10020" d="4992" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="video" bandwidth="800000" codecs="avc1.64001e" width="1280" height="720">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Number$.m4s" startNumber="2898" timescale="1000">
<SegmentTimeline>
<S t="0" d="5000" />
<S t="5000" d="5000" />
<S t="10000" d="5000" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
This MPD is similar to the previous one, with the difference that it includes a SegmentTimeline. According to the standard, in this case, the SegmentTemplate should not include a duration. Each segment's duration and start time are represented by the line <S t="0", d="5000" />
, which means the segment starts playing at availabilityStartTime + t and has a duration of 5000/timescale seconds. With this precise indication, the player selects segments from the SegmentTimeline list that fall within the current playback window [availabilityStartTime + t ~ availabilityStartTime + t + duration]. The placeholder $Number$
is replaced with the line number + startNumber of the segment being played.
<?xml version="1.0" encoding="utf-8"?>
<MPD ...>
<Period start="PT0S">
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="audio" bandwidth="48000" codecs="mp4a.40.2">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Time$.m4s" timescale="1000">
<SegmentTimeline>
<S t="100" d="4907" />
<S t="5007" d="5013" />
<S t="10020" d="4992" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="video" bandwidth="800000" codecs="avc1.64001e" width="1280" height="720">
<SegmentTemplate initialization="$RepresentationID$-init.mp4" media="$RepresentationID$-$Time$.m4s" timescale="1000">
<SegmentTimeline>
<S t="0" d="5000" />
<S t="5000" d="5000" />
<S t="10000" d="5000" />
</SegmentTimeline>
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
</MPD>
Similar to the segment selection logic above, just replace $Time$
with the t
value of the selected segment.
<?xml version="1.0" encoding="utf-8"?>
<MPD ...>
<Period start="PT0S">
<AdaptationSet mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="audio" bandwidth="48000" codecs="mp4a.40.2">
<SegmentList duration="5">
<SegmentURL media="video-1.m4s"/>
<SegmentURL media="video-2.m4s"/>
<SegmentURL media="video-3.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<Representation id="video" bandwidth="800000" codecs="avc1.64001e" width="1280" height="720">
<SegmentList duration="5">
<SegmentURL media="audio-1.m4s"/>
<SegmentURL media="audio-2.m4s"/>
<SegmentURL media="audio-3.m4s"/>
</SegmentList>
</Representation>
</AdaptationSet>
</Period>
</MPD>
This type of MPD is relatively rare in live streaming, so we won't discuss it in detail for now.
This field indicates the earliest UTC time to start playing all slices.
Since DASH plays strictly according to UTC time, it is necessary to map media time to UTC time. Generally, mapping is done according to the following logic. availabilityStartTime = firstFrameRecvTime - firstFrameTimestamp This way, all subsequent segments can calculate the corresponding UTC time for playback.
This field is relatively easy to understand, it represents the window time of the player, which can play segments up to the length of timeShiftBufferDepth in the past.
This field is also easily understood. It represents the minimum update frequency of the MPD. For MPDs that use SegmentTimeline, the update frequency is typically set to the duration of the latest segment to ensure that the player can refresh the MPD in a timely manner and obtain the latest segment for playback.
Minimum buffer time: The player must ensure that it has data exceeding this buffer length in order to start the playback.
The generation time of MPD at the source station needs to be rewritten every time the MPD is refreshed, and CDN can be used to refresh the cache.
When using SegmentTimeline and replacing with $Time$, there is an issue with VLC 3.0.17 playback, while VLC 4.0 works normally. With the help of Zhili, the VLC bug has been located. The PR is here
When reconnecting and re-pushing the stream, HLS can use the EXT-X-DISCONTINUITY
tag to concatenate the new segments at the end of the m3u8 file. Mainstream players such as hls.js, VLC, and ffplay can play it seamlessly.
However, DASH does not have a similar tag. According to the standard documentation, using a new Period can be attempted to solve this issue, but currently, it still cannot be played successfully.
The solution used by SRS is to regenerate a new MPD file after re-pushing while discarding the old MPD. In terms of player behavior, dash.js can restart the player and continue playing, while VLC will freeze abnormally and stop.
DASH is a fancy protocol that considers many aspects. It needs to support both video-on-demand and live streaming, while also compressing the MPD file to reduce its size. This makes DASH very complex in design and use. It is undeniable that it is a great design but it can be challenging for developers. Compared to HLS, it has a higher level of complexity, which is why there are currently fewer vendors using DASH. The standard documentation for DASH is also very cumbersome, lacking clear explanations and rich examples. Due to these various reasons, DASH has become a protocol that is excellent but not user-friendly.
TRANS_BY_GPT3
SRS selects SegmentTemplate with SegmentTimeline and uses $Number
as the URL substitution symbol, mainly considering the compatibility issues of current mainstream players.
TRANS_BY_GPT3
Fixed in v5.0.96
Usage
Make sure your SRS version is
SRS 5.0.96+
.Build SRS and run:
Publish by FFmpeg:
Play by
ffplay http://localhost:8080/live/livestream.mpd
http://localhost:8080/live/livestream.mpd