Skip to content

Commit

Permalink
Merge pull request #190 from Dash-Industry-Forum/fix-multiperiod-segt…
Browse files Browse the repository at this point in the history
…imeline-patch

fix: multiperiod MPD patch response at new period start
  • Loading branch information
tobbee authored May 25, 2024
2 parents 20b324b + 8e8102a commit 5db86ec
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- correct low-latency MPD update time for SegmentTimeline
- fix patch response for multiperiod segment-timeline

## [1.3.0] - 2024-04-23

Expand Down
10 changes: 9 additions & 1 deletion pkg/patch/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,15 @@ func addLeafChanges(patchRoot, old, new *etree.Element, elemPath string) error {
func addLeafListChanges(patchRoot, old, new *etree.Element, elemPath string) error {
oldElems := old.ChildElements()
newElems := new.ChildElements()
tag := oldElems[0].Tag // Require that all are the same
var tag string // Require that all elements have same type
switch {
case len(oldElems) == 0 && len(newElems) == 0:
return nil
case len(oldElems) > 0:
tag = oldElems[0].Tag
default:
tag = newElems[0].Tag
}
for _, e := range oldElems {
if e.Tag != tag {
return fmt.Errorf("other tag %q in list of %q", e.Tag, tag)
Expand Down
7 changes: 7 additions & 0 deletions pkg/patch/patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ func TestDiff(t *testing.T) {
wantedDiffFile: "testdata/multiperiod_patch.mpp",
wantedExpiration: time.Date(2024, 4, 21, 6, 12, 8, 0, time.UTC),
},
{
desc: "multiPeriodPatch at period change",
oldMPD: "testdata/segtimeline_multiper_full_min.mpd",
newMPD: "testdata/segtimeline_multiper_after_full_min.mpd",
wantedDiffFile: "testdata/segtimeline_multiper_patch_after_full_min.mpp",
wantedExpiration: time.Date(2024, 5, 24, 15, 13, 10, 0, time.UTC),
},
{
desc: "too big publishTime diff vs ttl",
oldMPD: "testdata/testpic_2s_1.mpd",
Expand Down
67 changes: 67 additions & 0 deletions pkg/patch/testdata/segtimeline_multiper_after_full_min.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" id="auto-patch-id" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" type="dynamic" availabilityStartTime="1970-01-01T00:00:00Z" publishTime="2024-05-24T15:12:04Z" minimumUpdatePeriod="PT2S" minBufferTime="PT2S" timeShiftBufferDepth="PT1M" maxSegmentDuration="PT2S">
<ProgramInformation moreInformationURL="https://github.com/dash-Industry-Forum/livesim-content">
<Title>Basic MPD with 640x480@30 video at 300kbp and 48kbps audio</Title>
<Source>VoD source for DASH-IF livesim2</Source>
</ProgramInformation>
<PatchLocation ttl="60">/patch/livesim2/patch_60/periods_60/segtimeline_1/testpic_2s/Manifest.mpp?publishTime=2024-05-24T15%3A12%3A04Z</PatchLocation>
<Period id="P28609391" start="PT476823H11M">
<AdaptationSet id="2" lang="en" contentType="audio" segmentAlignment="true" mimeType="audio/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="48000" presentationTimeOffset="82395046080000">
<SegmentTimeline>
<S t="82395046176768" d="95232"></S>
<S t="82395046272000" d="96256" r="2"></S>
<S t="82395046560768" d="95232"></S>
<S t="82395046656000" d="96256" r="2"></S>
<S t="82395046944768" d="95232"></S>
<S t="82395047040000" d="96256" r="2"></S>
<S t="82395047328768" d="95232"></S>
<S t="82395047424000" d="96256" r="2"></S>
<S t="82395047712768" d="95232"></S>
<S t="82395047808000" d="96256" r="2"></S>
<S t="82395048096768" d="95232"></S>
<S t="82395048192000" d="96256" r="2"></S>
<S t="82395048480768" d="95232"></S>
<S t="82395048576000" d="96256" r="2"></S>
<S t="82395048864768" d="95232"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="A48" bandwidth="48000" audioSamplingRate="48000" codecs="mp4a.40.2">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" par="16:9" minWidth="640" maxWidth="640" minHeight="360" maxHeight="360" maxFrameRate="60/2" segmentAlignment="true" mimeType="video/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="90000" presentationTimeOffset="154490711400000">
<SegmentTimeline>
<S t="154490711580000" d="180000" r="28"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="V300" bandwidth="300000" width="640" height="360" sar="1:1" frameRate="60/2" codecs="avc1.64001e"></Representation>
</AdaptationSet>
</Period>
<Period id="P28609392" start="PT476823H12M">
<AdaptationSet id="2" lang="en" contentType="audio" segmentAlignment="true" mimeType="audio/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="48000" presentationTimeOffset="82395048960000">
<SegmentTimeline>
<S t="82395048960000" d="96256" r="1"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="A48" bandwidth="48000" audioSamplingRate="48000" codecs="mp4a.40.2">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" par="16:9" minWidth="640" maxWidth="640" minHeight="360" maxHeight="360" maxFrameRate="60/2" segmentAlignment="true" mimeType="video/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="90000" presentationTimeOffset="154490716800000">
<SegmentTimeline>
<S t="154490716800000" d="180000" r="1"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="V300" bandwidth="300000" width="640" height="360" sar="1:1" frameRate="60/2" codecs="avc1.64001e"></Representation>
</AdaptationSet>
</Period>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="https://time.akamai.com/?iso&amp;ms"></UTCTiming>
</MPD>
64 changes: 64 additions & 0 deletions pkg/patch/testdata/segtimeline_multiper_full_min.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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" id="auto-patch-id" profiles="urn:mpeg:dash:profile:isoff-live:2011,http://dashif.org/guidelines/dash-if-simple" type="dynamic" availabilityStartTime="1970-01-01T00:00:00Z" publishTime="2024-05-24T15:12:00Z" minimumUpdatePeriod="PT2S" minBufferTime="PT2S" timeShiftBufferDepth="PT1M" maxSegmentDuration="PT2S">
<ProgramInformation moreInformationURL="https://github.com/dash-Industry-Forum/livesim-content">
<Title>Basic MPD with 640x480@30 video at 300kbp and 48kbps audio</Title>
<Source>VoD source for DASH-IF livesim2</Source>
</ProgramInformation>
<PatchLocation ttl="60">/patch/livesim2/patch_60/periods_60/segtimeline_1/testpic_2s/Manifest.mpp?publishTime=2024-05-24T15%3A12%3A00Z</PatchLocation>
<Period id="P28609391" start="PT476823H11M">
<AdaptationSet id="2" lang="en" contentType="audio" segmentAlignment="true" mimeType="audio/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="48000" presentationTimeOffset="82395046080000">
<SegmentTimeline>
<S t="82395046080512" d="96256"></S>
<S t="82395046176768" d="95232"></S>
<S t="82395046272000" d="96256" r="2"></S>
<S t="82395046560768" d="95232"></S>
<S t="82395046656000" d="96256" r="2"></S>
<S t="82395046944768" d="95232"></S>
<S t="82395047040000" d="96256" r="2"></S>
<S t="82395047328768" d="95232"></S>
<S t="82395047424000" d="96256" r="2"></S>
<S t="82395047712768" d="95232"></S>
<S t="82395047808000" d="96256" r="2"></S>
<S t="82395048096768" d="95232"></S>
<S t="82395048192000" d="96256" r="2"></S>
<S t="82395048480768" d="95232"></S>
<S t="82395048576000" d="96256" r="2"></S>
<S t="82395048864768" d="95232"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="A48" bandwidth="48000" audioSamplingRate="48000" codecs="mp4a.40.2">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" par="16:9" minWidth="640" maxWidth="640" minHeight="360" maxHeight="360" maxFrameRate="60/2" segmentAlignment="true" mimeType="video/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="90000" presentationTimeOffset="154490711400000">
<SegmentTimeline>
<S t="154490711400000" d="180000" r="29"></S>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="V300" bandwidth="300000" width="640" height="360" sar="1:1" frameRate="60/2" codecs="avc1.64001e"></Representation>
</AdaptationSet>
</Period>
<Period id="P28609392" start="PT476823H12M">
<AdaptationSet id="2" lang="en" contentType="audio" segmentAlignment="true" mimeType="audio/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="48000" presentationTimeOffset="82395048960000">
<SegmentTimeline></SegmentTimeline>
</SegmentTemplate>
<Representation id="A48" bandwidth="48000" audioSamplingRate="48000" codecs="mp4a.40.2">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" par="16:9" minWidth="640" maxWidth="640" minHeight="360" maxHeight="360" maxFrameRate="60/2" segmentAlignment="true" mimeType="video/mp4" startWithSAP="1">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<SegmentTemplate media="$RepresentationID$/$Time$.m4s" initialization="$RepresentationID$/init.mp4" timescale="90000" presentationTimeOffset="154490716800000">
<SegmentTimeline></SegmentTimeline>
</SegmentTemplate>
<Representation id="V300" bandwidth="300000" width="640" height="360" sar="1:1" frameRate="60/2" codecs="avc1.64001e"></Representation>
</AdaptationSet>
</Period>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="https://time.akamai.com/?iso&amp;ms"></UTCTiming>
</MPD>
18 changes: 18 additions & 0 deletions pkg/patch/testdata/segtimeline_multiper_patch_after_full_min.mpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Patch xmlns="urn:mpeg:dash:schema:mpd-patch:2020" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd-patch:2020 DASH-MPD-PATCH.xsd" mpdId="auto-patch-id" originalPublishTime="2024-05-24T15:12:00Z" publishTime="2024-05-24T15:12:04Z">
<replace sel="/MPD/@publishTime">2024-05-24T15:12:04Z</replace>
<replace sel="/MPD/PatchLocation[1]">
<PatchLocation ttl="60">/patch/livesim2/patch_60/periods_60/segtimeline_1/testpic_2s/Manifest.mpp?publishTime=2024-05-24T15%3A12%3A04Z</PatchLocation>
</replace>
<remove sel="/MPD/Period[@id=&apos;P28609391&apos;]/AdaptationSet[@id=&apos;2&apos;]/SegmentTemplate/SegmentTimeline/S[1]"/>
<remove sel="/MPD/Period[@id=&apos;P28609391&apos;]/AdaptationSet[@id=&apos;1&apos;]/SegmentTemplate/SegmentTimeline/S[1]"/>
<add sel="/MPD/Period[@id=&apos;P28609391&apos;]/AdaptationSet[@id=&apos;1&apos;]/SegmentTemplate/SegmentTimeline" pos="prepend">
<S t="154490711580000" d="180000" r="28"/>
</add>
<add sel="/MPD/Period[@id=&apos;P28609392&apos;]/AdaptationSet[@id=&apos;2&apos;]/SegmentTemplate/SegmentTimeline" pos="prepend">
<S t="82395048960000" d="96256" r="1"/>
</add>
<add sel="/MPD/Period[@id=&apos;P28609392&apos;]/AdaptationSet[@id=&apos;1&apos;]/SegmentTemplate/SegmentTimeline" pos="prepend">
<S t="154490716800000" d="180000" r="1"/>
</add>
</Patch>

0 comments on commit 5db86ec

Please sign in to comment.