Skip to content

Commit

Permalink
feat: Added all DASH Ed 6 elements and new test content
Browse files Browse the repository at this point in the history
Added elements from Ed 6 input to Jan. 2025 MPEG meeting.
Changed Duration to round to milliseconds unless time is less than millisecond
  • Loading branch information
tobbee committed Jan 24, 2025
1 parent 15766b9 commit c059b3e
Show file tree
Hide file tree
Showing 20 changed files with 697 additions and 89 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Nothing yet
### Changed

- Duration is now printed with millisecond accuracy unless value less than one millisecond
- PatchLocationType according to Ed. 6
- Location according to Ed. 6

### Added

- All elements according to DASH Ed. 6 contribution to Jan. 2025 MPEG meeting
- AlternativeMPD element according to Ed. 6
- ContentSteering according to Ed. 6
- ClientDataReporting according to Ed. 6
- SegmentSequenceProperties according to Ed. 6
- RunLengthType according to Ed. 6
- Pattern and PatternType according to Ed. 6
- SupVideoInfoType according to Ed. 6 xsd
- SapWithCadenceType according to Ed. 6
- Example DASHSchema content G.23 to G28.1, G28.2, and G.29
- Example DASGSchema content G.30-1 to G.30-5, G.31-1, G.31-2, G.32-1, G.32-2

## [0.12.0] - 2024-12-20

Expand Down
40 changes: 25 additions & 15 deletions mpd/duration.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mpd

import (
"math"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -64,33 +65,42 @@ func (d *Duration) UnmarshalXMLAttr(attr xml.Attr) error {
//
// It handles negative durations, although they should not occur.
// The highest output unit is hours (H).
// There is never more than 3 decimals to the seconds.
func (d *Duration) String() string {
// Largest time is 2540400h10m10.000000000s
// Largest time is 2540400h10m10.000s
var buf [32]byte
w := len(buf)

u := uint64(*d)
if u == 0 {
return "PT0S"
}
neg := *d < 0
if neg {
u = -u
}

if u < uint64(time.Second) {
var prec int
w--
buf[w] = 'S'
w--
if u == 0 {
return "PT0S"
}
w, u = fmtFrac(buf[:w], u, prec)
w = fmtInt(buf[:w], u)
} else {
w--
buf[w] = 'S'
s := u / uint64(time.Second)
ns := u - s*uint64(time.Second)
ms := uint64(math.Round(float64(ns) * 1.0e-6))

w, u = fmtFrac(buf[:w], u, 9)
w--
buf[w] = 'S' // End with Seconds

switch {
case s == 0 && ms == 0:
// Time smaller than ms, return higher precision
w, u = fmtFrac(buf[:w], u, 9)
w = fmtInt(buf[:w], u)
case s == 0:
// Time smaller than 1s, return ms
w, _ = fmtFrac(buf[:w], ms, 3)
w--
buf[w] = '0'
default:
// Time larger than 1s, return s and potentially ms
u = 1000*s + ms
w, u = fmtFrac(buf[:w], u, 3)
// u is now integer seconds
w = fmtInt(buf[:w], u%60)
u /= 60
Expand Down
20 changes: 20 additions & 0 deletions mpd/duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,23 @@ func TestParseBadDurations(t *testing.T) {
require.EqualError(t, err, msg, fmt.Sprintf("Expected an error for: %s", ins))
}
}

func TestUnMarshalReMarshalDuration(t *testing.T) {
cases := []string{
"PT0.0002S",
"PT0.334S",
"PT2.002S",
"PT2S",
"PT1M",
"PT0S",
}

for _, dur := range cases {
timeDur, err := ParseDuration(dur)
require.NoError(t, err)

tDur := Duration(timeDur)
outDur := tDur.String()
require.Equal(t, dur, outDur)
}
}
280 changes: 210 additions & 70 deletions mpd/mpd.go

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions mpd/mpd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ func TestDecodeEncodeMPDs(t *testing.T) {
}
}

func TestExtUrlQueryInfo(t *testing.T) {

cases := []struct {
name string
input string
}{
{
name: "example_G31.1 ExtUrlQueryInfo",
input: `<EssentialProperty schemeIdUri="urn:mpeg:dash:urlparam:2016"
xmlns:up="urn:mpeg:dash:schema:urlparam:2016">
<up:ExtUrlQueryInfo includeInRequests="altmpd"
queryTemplate="prta=$urn:mpeg:dash:state:execution-delta#42$" />
</EssentialProperty>`,
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ep := m.DescriptorType{}
err := xml.Unmarshal([]byte(tc.input), &ep)
require.NoError(t, err)

})
}
}

func BenchmarkUnmarshal(b *testing.B) {
data, err := os.ReadFile("testdata/schema-mpds/example_G15.mpd")
require.NoError(b, err)
Expand Down
2 changes: 1 addition & 1 deletion mpd/testdata/go-dash-fixtures/truncate.mpd
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</Representation>
</AdaptationSet>
</Period>
<Period id="1" start="PT31.421333333S">
<Period id="1" start="PT31.421S">
<AdaptationSet frameRate="90000/3000" id="0" segmentAlignment="true" maxWidth="720" contentType="video">
<Representation sar="1:1" mimeType="video/mp4" bandwidth="311792" codecs="avc1.42c01e" height="480" id="0" width="720">
<SegmentTemplate initialization="video_0/init.mp4" media="video_0/media_$Number$.m4s" startNumber="6" timescale="90000">
Expand Down
2 changes: 1 addition & 1 deletion mpd/testdata/go-dash-fixtures/truncate_short.mpd
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="dynamic" minBufferTime="PT2S" availabilityStartTime="2019-12-03T20:57:14Z" minimumUpdatePeriod="PT5S" publishTime="2019-12-03T21:05:05Z" timeShiftBufferDepth="PT2M">
<Period id="1" start="PT31.421333333S">
<Period id="1" start="PT31.421S">
<AdaptationSet frameRate="90000/3000" id="0" segmentAlignment="true" maxWidth="720" contentType="video">
<Representation sar="1:1" mimeType="video/mp4" bandwidth="311792" codecs="avc1.42c01e" height="480" id="0" width="720">
<SegmentTemplate initialization="video_0/init.mp4" media="video_0/media_$Number$.m4s" startNumber="6" timescale="90000">
Expand Down
2 changes: 1 addition & 1 deletion mpd/testdata/livesim/urlparams.mpd
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ publishTime="1970-01-01T00:00:00Z" timeShiftBufferDepth="PT5M" type="dynamic" xs
<Period id="p0" start="PT0S">
<AdaptationSet contentType="audio" lang="en" mimeType="audio/mp4" segmentAlignment="true" startWithSAP="1">
<EssentialProperty schemeIdUri="urn:mpeg:dash:urlparam:2016" xmlns:up="urn:mpeg:dash:schema:urlparam:2016">
<up:ExtendedUrlInfo queryTemplate="$querypart$" useMPDUrlQuery="true" headerParamSource="dashif.org"/>
<up:ExtUrlQueryInfo queryTemplate="$querypart$" useMPDUrlQuery="true" headerParamSource="dashif.org"/>
</EssentialProperty>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
<SegmentTemplate duration="2" initialization="$RepresentationID$/init.mp4" media="$RepresentationID$/$Number$.m4s" startNumber="0" />
Expand Down
64 changes: 64 additions & 0 deletions mpd/testdata/schema-mpds/example_G28.1.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="dynamic" id="7399610060681366163" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2.002S" maxSegmentDuration="PT2.002S" minimumUpdatePeriod="PT2.002S"
availabilityStartTime="1977-05-25T18:00:00.000Z" timeShiftBufferDepth="PT30S"
publishTime="2023-11-10T20:44:07.025Z"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd">

<Period id="817467999" start="PT389761H2M15.535S">

<AdaptationSet id="1" contentType="video" mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="video_fga"/>
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>

<SegmentTemplate initialization="$RepresentationID$/init.mp4" timeShiftBufferDepth="PT30S"
media="$RepresentationID$/segment_$Time$.mp4" timescale="90000" presentationTimeOffset="135158">

<SegmentTimeline>
<S t="546975158" d="172800" r="144"/>
</SegmentTimeline>

</SegmentTemplate>

<Representation id="540p" bandwidth="1502000"
codecs="hvc1.2.4.L93.B0" width="960" height="540" frameRate="50"/>
<Representation id="720p" bandwidth="2166000"
codecs="hvc1.2.4.L93.B0" width="1280" height="720" frameRate="50"/>
<Representation id="1080p" bandwidth="6202000"
codecs="hvc1.2.4.L123.B0" width="1920" height="1080" frameRate="50"/>
<Representation id="1440p" bandwidth="12741200"
codecs="hvc1.2.4.L153.B0" width="2560" height="1440" frameRate="50"/>
<Representation id="2160p" bandwidth="18667200"
codecs="hvc1.2.4.H153.B0" width="3840" height="2160" frameRate="50"/>

</AdaptationSet>

<AdaptationSet id="11" contentType="video" mimeType="video/mp4"
segmentAlignment="true" startWithSAP="1">
<EssentialProperty
schemeIdUri="urn:mpeg:dash:ssr:2023" value="video_primary"/>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016"
value="video_primary"/>


<SegmentTemplate initialization="$RepresentationID$/init.mp4"
media="$RepresentationID$/segment_$Time$_part_$SubNumber$.mp4"
timescale="90000" presentationTimeOffset="135158">

<SegmentTimeline>
<S t="546975158" d="172800" r="144" k="16"/>
</SegmentTimeline>

</SegmentTemplate>

<!-- Fine Granularity Access representations with 6-frame partial segments.
Each segment starts with IDR and can be used to start playback -->
<Representation id="join_6_540p" bandwidth="600000"
codecs="hvc1.2.4.L93.B0" width="960" height="540" frameRate="50"/>
<Representation id="join_6_1080p" bandwidth="1200000"
codecs="hvc1.2.4.L93.B0" width="1920" height="1080" frameRate="50"/>

</AdaptationSet>

</Period>

</MPD>
57 changes: 57 additions & 0 deletions mpd/testdata/schema-mpds/example_G28.2.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="dynamic" id="7399610060681366163" profiles="urn:mpeg:dash:profile:isoff-live:2011" minBufferTime="PT2S" maxSegmentDuration="PT2.016S" minimumUpdatePeriod="PT2.002S" availabilityStartTime="1977-05-25T18:00:00.000Z" timeShiftBufferDepth="PT30S" publishTime="2021-11-10T20:44:07.025Z"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd">

<ServiceDescription id="0">
<Latency min="750" max="4200" target="1250" referenceId="7"/>
<PlaybackRate min="0.96" max="1.04"/>
</ServiceDescription>

<Period id="817467999" start="PT389761H2M15.535S">

<AdaptationSet id="1" contentType="video" mimeType="video/mp4"
segmentAlignment="true">

<EssentialProperty schemeIdUri="urn:mpeg:dash:ssr:2023" />

<ProducerReferenceTime id="7" wallClockTime="2019-08-06T13:44:12Z"
presentationTime="158400"/>

<!-- Segment Sequence Representations where partial segments with subnumber > 1
are not expected to have any kind of random access / bitstream switching
The first partial segment starts with SAP = 1 -->

<SegmentSequenceProperties>
<SAP type="1"/>
</SegmentSequenceProperties>

<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>

<SegmentTemplate initialization="$RepresentationID$/init.mp4"
media="$RepresentationID$/segment_$Number$_part_$SubNumber$.mp4"
timescale="90000" startNumber="817472154"
presentationTimeOffset="135158">

<SegmentTimeline>
<!-- 1.92s segment with 6-frame partial segments, compatible with LL-HLS-->
<S t="546975158" d="172800" r="14" k="16"/>
</SegmentTimeline>

</SegmentTemplate>

<Representation id="l3d_540p" bandwidth="1502000" codecs="hvc1.2.4.L93.B0"
width="960" height="540" frameRate="50"/>
<Representation id="l3d_720p" bandwidth="2166000" codecs="hvc1.2.4.L93.B0"
width="1280" height="720" frameRate="50"/>
<Representation id="l3d_1080p" bandwidth="6202000" codecs="hvc1.2.4.L123.B0"
width="1920" height="1080" frameRate="50"/>
<Representation id="l3d_1440p" bandwidth="12741200" codecs="hvc1.2.4.L153.B0"
width="2560" height="1440" frameRate="50"/>
<Representation id="l3d_2160p" bandwidth="18667200" codecs="hvc1.2.4.H153.B0"
width="3840" height="2160" frameRate="50"/>

</AdaptationSet>

</Period>

</MPD>
36 changes: 36 additions & 0 deletions mpd/testdata/schema-mpds/example_G29.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="dynamic" id="7399610060681366163" profiles="urn:mpeg:dash:profile:isoff-live:2011"
minBufferTime="PT2S" maxSegmentDuration="PT2.016S" minimumUpdatePeriod="PT2.002S"
timeShiftBufferDepth="PT30S" publishTime="2021-11-10T20:44:07.025Z"
availabilityStartTime="1977-05-25T18:00:00.000Z"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd">

<Period id="817467999" start="PT389761H2M15.535S">
<AdaptationSet id="1" contentType="audio" mimeType="audio/mp4" segmentAlignment="true"
startWithSAP="1" audioSamplingRate="24000">

<EssentialProperty schemeIdUri="urn:mpeg:dash:pattern:2024"/>

<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>

<SegmentTemplate initialization="$RepresentationID$/init.mp4"
media="$RepresentationID$/segment_$Time$.mp4" timescale="90000"
startNumber="817472154" presentationTimeOffset="135158">

<SegmentTimeline>
<Pattern id="1">
<P d="180480" r="11"/>
<P d="176640"/>
</Pattern>
<S t="546975158" r="164" p="1" pE="3" d="0"/>
</SegmentTimeline>

</SegmentTemplate>

<Representation id="eng_2ch" bandwidth="112000" codecs="mp4a.40.5"/>

</AdaptationSet>

</Period>
</MPD>

18 changes: 18 additions & 0 deletions mpd/testdata/schema-mpds/example_G30-1.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?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 urn:mpeg:dash:schema:urlparam:2014 DASH-MPD-UP.xsd"

type="static" mediaPresentationDuration="PT54M16S" minBufferTime="PT1.2S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
<Period>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1" maxWidth="1280" maxHeight="720" maxFrameRate="25" par="16:9">
<EssentialProperty schemeIdUri="urn:mpeg:dash:urlparam:2014" xmlns:up="urn:mpeg:dash:schema:urlparam:2014">
<up:UrlQueryInfo queryTemplate="$querypart$" useMPDUrlQuery="true"/>
</EssentialProperty>
<SegmentTemplate duration="2" startNumber="1" media="video_$Number$_$Bandwidth$bps.mp4"/>
<Representation id="v0" codecs="avc3.4d401f" width="1280" height="720" frameRate="25" sar="1:1" bandwidth="3000000"/>
<Representation id="v1" codecs="avc3.4d401f" width="640" height="360" frameRate="25" sar="1:1" bandwidth="1500000"/>
</AdaptationSet>
</Period>
</MPD>
16 changes: 16 additions & 0 deletions mpd/testdata/schema-mpds/example_G30-2.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?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 urn:mpeg:dash:schema:urlparam:2014 DASH-MPD-UP.xsd" type="static" mediaPresentationDuration="PT54M16S" minBufferTime="PT1.2S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
<Period>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1" maxWidth="1280" maxHeight="720" maxFrameRate="25" par="16:9">
<EssentialProperty schemeIdUri="urn:mpeg:dash:urlparam:2014" xmlns:up="urn:mpeg:dash:schema:urlparam:2014">
<up:UrlQueryInfo xlink:href="http://www.example.com/dash/xlinked.mpd" xlink:actuate="onRequest" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</EssentialProperty>
<SegmentTemplate duration="2" startNumber="1" media="video_$Number$_$Bandwidth$bps.mp4"/>
<Representation id="v0" codecs="avc3.4d401f" width="1280" height="720" frameRate="25" sar="1:1" bandwidth="3000000"/>
<Representation id="v1" codecs="avc3.4d401f" width="640" height="360" frameRate="25" sar="1:1" bandwidth="1500000"/>
</AdaptationSet>
<SupplementalProperty schemeIdUri="urn:mpeg:dash:urlparam:2014" xmlns:up="urn:mpeg:dash:schema:urlparam:2014">
<up:UrlQueryInfo xmlns:up="urn:mpeg:dash:schema:urlparam:2014" queryTemplate="$querypart$" queryString="param=justintimecomputedvalue"/>
</SupplementalProperty>
</Period>
</MPD>
19 changes: 19 additions & 0 deletions mpd/testdata/schema-mpds/example_G30-3.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?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 urn:mpeg:dash:schema:urlparam:2014 DASH-MPD-UP.xsd"
type="static" mediaPresentationDuration="PT54M16S" minBufferTime="PT1.2S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
<Period>
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1" maxWidth="1280" maxHeight="720" maxFrameRate="25" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:dash:urlparam:2014" xmlns:up="urn:mpeg:dash:schema:urlparam:2014">
<up:UrlQueryInfo queryTemplate="$querypart$" useMPDUrlQuery="true"/>
</SupplementalProperty>
<SupplementalProperty schemeIdUri="urn:example:gps"/>
<SegmentTemplate duration="2" startNumber="1" media="video_$Number$_$Bandwidth$bps.mp4">
</SegmentTemplate>
<Representation id="v0" codecs="avc3.4d401f" width="1280" height="720" frameRate="25" sar="1:1" bandwidth="3000000"/>
<Representation id="v1" codecs="avc3.4d401f" width="640" height="360" frameRate="25" sar="1:1" bandwidth="1500000"/>
</AdaptationSet>
</Period>
</MPD>
Loading

0 comments on commit c059b3e

Please sign in to comment.