Skip to content

Commit 12a54ee

Browse files
miyukkistuarthicks
authored andcommitted
Support some MPD attributes to encode/decode (#51)
* Support some MPD attributes to encode/decode * Implement NewDynamicMPD to generate dynamic type MPD
1 parent 9b71037 commit 12a54ee

File tree

6 files changed

+228
-8
lines changed

6 files changed

+228
-8
lines changed

mpd/fixtures/live_profile.mpd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S">
2+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S" availabilityStartTime="1970-01-01T00:00:00Z">
33
<Period>
44
<AdaptationSet mimeType="audio/mp4" startWithSAP="1" id="7357" segmentAlignment="true" lang="en">
55
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>

mpd/fixtures/live_profile_dynamic.mpd

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="dynamic" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S" availabilityStartTime="1970-01-01T00:00:00Z" minimumUpdatePeriod="PT5S">
3+
<Period>
4+
<AdaptationSet mimeType="audio/mp4" startWithSAP="1" id="7357" segmentAlignment="true" lang="en">
5+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
6+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" xmlns:cenc="urn:mpeg:cenc:2013">
7+
<cenc:pssh>AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA==</cenc:pssh>
8+
</ContentProtection>
9+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mspr="urn:microsoft:playready">
10+
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
11+
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
12+
</ContentProtection>
13+
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
14+
<SegmentTemplate duration="1968" initialization="$RepresentationID$/audio/en/init.mp4" media="$RepresentationID$/audio/en/seg-$Number$.m4f" startNumber="0" timescale="1000"></SegmentTemplate>
15+
<Representation audioSamplingRate="44100" bandwidth="67095" codecs="mp4a.40.2" id="800"></Representation>
16+
</AdaptationSet>
17+
<AdaptationSet mimeType="video/mp4" startWithSAP="1" scanType="progressive" id="7357" segmentAlignment="true">
18+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
19+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" xmlns:cenc="urn:mpeg:cenc:2013">
20+
<cenc:pssh>AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA==</cenc:pssh>
21+
</ContentProtection>
22+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mspr="urn:microsoft:playready">
23+
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
24+
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
25+
</ContentProtection>
26+
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
27+
<SegmentTemplate duration="1968" initialization="$RepresentationID$/video/1/init.mp4" media="$RepresentationID$/video/1/seg-$Number$.m4f" startNumber="0" timescale="1000"></SegmentTemplate>
28+
<Representation bandwidth="1518664" codecs="avc1.4d401f" frameRate="30000/1001" height="540" id="800" width="960"></Representation>
29+
<Representation bandwidth="1911775" codecs="avc1.4d401f" frameRate="30000/1001" height="576" id="1000" width="1024"></Representation>
30+
<Representation bandwidth="2295158" codecs="avc1.4d401f" frameRate="30000/1001" height="576" id="1200" width="1024"></Representation>
31+
<Representation bandwidth="2780732" codecs="avc1.4d401f" frameRate="30000/1001" height="720" id="1500" width="1280"></Representation>
32+
</AdaptationSet>
33+
<AdaptationSet mimeType="text/vtt" id="7357" lang="en">
34+
<Representation bandwidth="256" id="subtitle_en">
35+
<BaseURL>http://example.com/content/sintel/subtitles/subtitles_en.vtt</BaseURL>
36+
</Representation>
37+
</AdaptationSet>
38+
</Period>
39+
</MPD>

mpd/mpd.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ type MPD struct {
6565
Type *string `xml:"type,attr"`
6666
MediaPresentationDuration *string `xml:"mediaPresentationDuration,attr"`
6767
MinBufferTime *string `xml:"minBufferTime,attr"`
68+
AvailabilityStartTime *string `xml:"availabilityStartTime,attr,omitempty"`
69+
MinimumUpdatePeriod *string `xml:"minimumUpdatePeriod,attr"`
6870
BaseURL string `xml:"BaseURL,omitempty"`
6971
period *Period
7072
Periods []*Period `xml:"Period,omitempty"`
@@ -216,13 +218,14 @@ type AudioChannelConfiguration struct {
216218
Value *string `xml:"value,attr"`
217219
}
218220

219-
// Creates a new MPD object.
221+
// Creates a new static MPD object.
220222
// profile - DASH Profile (Live or OnDemand).
221223
// mediaPresentationDuration - Media Presentation Duration (i.e. PT6M16S).
222224
// minBufferTime - Min Buffer Time (i.e. PT1.97S).
223-
func NewMPD(profile DashProfile, mediaPresentationDuration string, minBufferTime string) *MPD {
225+
// attributes - Other attributes (optional).
226+
func NewMPD(profile DashProfile, mediaPresentationDuration, minBufferTime string, attributes ...AttrMPD) *MPD {
224227
period := &Period{}
225-
return &MPD{
228+
mpd := &MPD{
226229
XMLNs: Strptr("urn:mpeg:dash:schema:mpd:2011"),
227230
Profiles: Strptr((string)(profile)),
228231
Type: Strptr("static"),
@@ -231,6 +234,44 @@ func NewMPD(profile DashProfile, mediaPresentationDuration string, minBufferTime
231234
period: period,
232235
Periods: []*Period{period},
233236
}
237+
238+
for i := range attributes {
239+
switch attr := attributes[i].(type) {
240+
case *attrAvailabilityStartTime:
241+
mpd.AvailabilityStartTime = attr.GetStrptr()
242+
}
243+
}
244+
245+
return mpd
246+
}
247+
248+
// Creates a new dynamic MPD object.
249+
// profile - DASH Profile (Live or OnDemand).
250+
// availabilityStartTime - anchor for the computation of the earliest availability time (in UTC).
251+
// minBufferTime - Min Buffer Time (i.e. PT1.97S).
252+
// attributes - Other attributes (optional).
253+
func NewDynamicMPD(profile DashProfile, availabilityStartTime, minBufferTime string, attributes ...AttrMPD) *MPD {
254+
period := &Period{}
255+
mpd := &MPD{
256+
XMLNs: Strptr("urn:mpeg:dash:schema:mpd:2011"),
257+
Profiles: Strptr((string)(profile)),
258+
Type: Strptr("dynamic"),
259+
AvailabilityStartTime: Strptr(availabilityStartTime),
260+
MinBufferTime: Strptr(minBufferTime),
261+
period: period,
262+
Periods: []*Period{period},
263+
}
264+
265+
for i := range attributes {
266+
switch attr := attributes[i].(type) {
267+
case *attrMinimumUpdatePeriod:
268+
mpd.MinimumUpdatePeriod = attr.GetStrptr()
269+
case *attrMediaPresentationDuration:
270+
mpd.MediaPresentationDuration = attr.GetStrptr()
271+
}
272+
}
273+
274+
return mpd
234275
}
235276

236277
// AddNewPeriod creates a new Period and make it the currently active one.

mpd/mpd_attr.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package mpd
2+
3+
type AttrMPD interface {
4+
GetStrptr() *string
5+
}
6+
7+
type attrAvailabilityStartTime struct {
8+
strptr *string
9+
}
10+
11+
func (attr *attrAvailabilityStartTime) GetStrptr() *string {
12+
return attr.strptr
13+
}
14+
15+
// AttrAvailabilityStartTime returns AttrMPD object for NewMPD
16+
func AttrAvailabilityStartTime(value string) AttrMPD {
17+
return &attrAvailabilityStartTime{strptr: &value}
18+
}
19+
20+
type attrMinimumUpdatePeriod struct {
21+
strptr *string
22+
}
23+
24+
func (attr *attrMinimumUpdatePeriod) GetStrptr() *string {
25+
return attr.strptr
26+
}
27+
28+
// AttrMinimumUpdatePeriod returns AttrMPD object for NewMPD
29+
func AttrMinimumUpdatePeriod(value string) AttrMPD {
30+
return &attrMinimumUpdatePeriod{strptr: &value}
31+
}
32+
33+
type attrMediaPresentationDuration struct {
34+
strptr *string
35+
}
36+
37+
func (attr *attrMediaPresentationDuration) GetStrptr() *string {
38+
return attr.strptr
39+
}
40+
41+
// AttrMediaPresentationDuration returns AttrMPD object for NewMPD
42+
func AttrMediaPresentationDuration(value string) AttrMPD {
43+
return &attrMediaPresentationDuration{strptr: &value}
44+
}

mpd/mpd_read_write_test.go

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,28 @@ func TestReadingManifests(t *testing.T) {
3939
}
4040

4141
func TestNewMPDLiveWriteToString(t *testing.T) {
42-
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME)
42+
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME,
43+
AttrAvailabilityStartTime(VALID_AVAILABILITY_START_TIME))
4344

4445
xmlStr, err := m.WriteToString()
4546
require.Nil(t, err)
4647
expectedXML := `<?xml version="1.0" encoding="UTF-8"?>
47-
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S">
48+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="static" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S" availabilityStartTime="1970-01-01T00:00:00Z">
49+
<Period></Period>
50+
</MPD>
51+
`
52+
require.Equal(t, expectedXML, xmlStr)
53+
}
54+
55+
func TestNewDynamicMPDLiveWriteToString(t *testing.T) {
56+
m := NewDynamicMPD(DASH_PROFILE_LIVE, VALID_AVAILABILITY_START_TIME, VALID_MIN_BUFFER_TIME,
57+
AttrMediaPresentationDuration(VALID_MEDIA_PRESENTATION_DURATION),
58+
AttrMinimumUpdatePeriod(VALID_MINIMUM_UPDATE_PERIOD))
59+
60+
xmlStr, err := m.WriteToString()
61+
require.Nil(t, err)
62+
expectedXML := `<?xml version="1.0" encoding="UTF-8"?>
63+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="dynamic" mediaPresentationDuration="PT6M16S" minBufferTime="PT1.97S" availabilityStartTime="1970-01-01T00:00:00Z" minimumUpdatePeriod="PT5S">
4864
<Period></Period>
4965
</MPD>
5066
`
@@ -143,7 +159,8 @@ func TestExampleAddNewPeriod(t *testing.T) {
143159
}
144160

145161
func LiveProfile() *MPD {
146-
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME)
162+
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME,
163+
AttrAvailabilityStartTime(VALID_AVAILABILITY_START_TIME))
147164

148165
audioAS, _ := m.AddNewAdaptationSetAudioWithID("7357", DASH_MIME_TYPE_AUDIO_MP4, VALID_SEGMENT_ALIGNMENT, VALID_START_WITH_SAP, VALID_LANG)
149166

@@ -196,6 +213,62 @@ func TestFullLiveProfileWriteToFile(t *testing.T) {
196213
require.Nil(t, err)
197214
}
198215

216+
func LiveProfileDynamic() *MPD {
217+
m := NewDynamicMPD(DASH_PROFILE_LIVE, VALID_AVAILABILITY_START_TIME, VALID_MIN_BUFFER_TIME,
218+
AttrMediaPresentationDuration(VALID_MEDIA_PRESENTATION_DURATION),
219+
AttrMinimumUpdatePeriod(VALID_MINIMUM_UPDATE_PERIOD))
220+
221+
audioAS, _ := m.AddNewAdaptationSetAudioWithID("7357", DASH_MIME_TYPE_AUDIO_MP4, VALID_SEGMENT_ALIGNMENT, VALID_START_WITH_SAP, VALID_LANG)
222+
223+
audioAS.AddNewContentProtectionRoot("08e367028f33436ca5dd60ffe5571e60")
224+
audioAS.AddNewContentProtectionSchemeWidevineWithPSSH(getValidWVHeaderBytes())
225+
audioAS.AddNewContentProtectionSchemePlayreadyWithPSSH(VALID_PLAYREADY_PRO)
226+
227+
audioAS.AddNewRole("urn:mpeg:dash:role:2011", VALID_ROLE)
228+
229+
audioAS.SetNewSegmentTemplate(1968, "$RepresentationID$/audio/en/init.mp4", "$RepresentationID$/audio/en/seg-$Number$.m4f", 0, 1000)
230+
audioAS.AddNewRepresentationAudio(44100, 67095, "mp4a.40.2", "800")
231+
232+
videoAS, _ := m.AddNewAdaptationSetVideoWithID("7357", DASH_MIME_TYPE_VIDEO_MP4, VALID_SCAN_TYPE, VALID_SEGMENT_ALIGNMENT, VALID_START_WITH_SAP)
233+
234+
videoAS.AddNewContentProtectionRoot("08e367028f33436ca5dd60ffe5571e60")
235+
videoAS.AddNewContentProtectionSchemeWidevineWithPSSH(getValidWVHeaderBytes())
236+
videoAS.AddNewContentProtectionSchemePlayreadyWithPSSH(VALID_PLAYREADY_PRO)
237+
238+
videoAS.AddNewRole("urn:mpeg:dash:role:2011", VALID_ROLE)
239+
240+
videoAS.SetNewSegmentTemplate(1968, "$RepresentationID$/video/1/init.mp4", "$RepresentationID$/video/1/seg-$Number$.m4f", 0, 1000)
241+
videoAS.AddNewRepresentationVideo(1518664, "avc1.4d401f", "800", "30000/1001", 960, 540)
242+
videoAS.AddNewRepresentationVideo(1911775, "avc1.4d401f", "1000", "30000/1001", 1024, 576)
243+
videoAS.AddNewRepresentationVideo(2295158, "avc1.4d401f", "1200", "30000/1001", 1024, 576)
244+
videoAS.AddNewRepresentationVideo(2780732, "avc1.4d401f", "1500", "30000/1001", 1280, 720)
245+
246+
subtitleAS, _ := m.AddNewAdaptationSetSubtitleWithID("7357", DASH_MIME_TYPE_SUBTITLE_VTT, VALID_LANG)
247+
subtitleRep, _ := subtitleAS.AddNewRepresentationSubtitle(VALID_SUBTITLE_BANDWIDTH, VALID_SUBTITLE_ID)
248+
subtitleRep.SetNewBaseURL(VALID_SUBTITLE_URL)
249+
250+
return m
251+
}
252+
253+
func TestFullLiveProfileDynamicWriteToString(t *testing.T) {
254+
m := LiveProfileDynamic()
255+
require.NotNil(t, m)
256+
xmlStr, err := m.WriteToString()
257+
require.Nil(t, err)
258+
testfixtures.CompareFixture(t, "fixtures/live_profile_dynamic.mpd", xmlStr)
259+
}
260+
261+
func TestFullLiveProfileDynamicWriteToFile(t *testing.T) {
262+
m := LiveProfileDynamic()
263+
require.NotNil(t, m)
264+
err := m.WriteToFile("test_live_dynamic.mpd")
265+
xmlStr := testfixtures.LoadFixture("test_live_dynamic.mpd")
266+
expectedXML := testfixtures.LoadFixture("fixtures/live_profile_dynamic.mpd")
267+
require.Equal(t, expectedXML, xmlStr)
268+
defer os.Remove("test_live_dynamic.mpd")
269+
require.Nil(t, err)
270+
}
271+
199272
func HbbTVProfile() *MPD {
200273
m := NewMPD(DASH_PROFILE_HBBTV_1_5_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME)
201274

mpd/mpd_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
const (
1313
VALID_MEDIA_PRESENTATION_DURATION string = "PT6M16S"
1414
VALID_MIN_BUFFER_TIME string = "PT1.97S"
15+
VALID_AVAILABILITY_START_TIME string = "1970-01-01T00:00:00Z"
16+
VALID_MINIMUM_UPDATE_PERIOD string = "PT5S"
1517
VALID_MIME_TYPE_VIDEO string = "video/mp4"
1618
VALID_MIME_TYPE_AUDIO string = "audio/mp4"
1719
VALID_MIME_TYPE_SUBTITLE_VTT string = "text/vtt"
@@ -49,14 +51,35 @@ const (
4951
)
5052

5153
func TestNewMPDLive(t *testing.T) {
52-
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME)
54+
m := NewMPD(DASH_PROFILE_LIVE, VALID_MEDIA_PRESENTATION_DURATION, VALID_MIN_BUFFER_TIME,
55+
AttrAvailabilityStartTime(VALID_AVAILABILITY_START_TIME))
5356
require.NotNil(t, m)
5457
expectedMPD := &MPD{
5558
XMLNs: Strptr("urn:mpeg:dash:schema:mpd:2011"),
5659
Profiles: Strptr((string)(DASH_PROFILE_LIVE)),
5760
Type: Strptr("static"),
5861
MediaPresentationDuration: Strptr(VALID_MEDIA_PRESENTATION_DURATION),
5962
MinBufferTime: Strptr(VALID_MIN_BUFFER_TIME),
63+
AvailabilityStartTime: Strptr(VALID_AVAILABILITY_START_TIME),
64+
period: &Period{},
65+
Periods: []*Period{{}},
66+
}
67+
require.Equal(t, expectedMPD, m)
68+
}
69+
70+
func TestNewDynamicMPDLive(t *testing.T) {
71+
m := NewDynamicMPD(DASH_PROFILE_LIVE, VALID_AVAILABILITY_START_TIME, VALID_MIN_BUFFER_TIME,
72+
AttrMediaPresentationDuration(VALID_MEDIA_PRESENTATION_DURATION),
73+
AttrMinimumUpdatePeriod(VALID_MINIMUM_UPDATE_PERIOD))
74+
require.NotNil(t, m)
75+
expectedMPD := &MPD{
76+
XMLNs: Strptr("urn:mpeg:dash:schema:mpd:2011"),
77+
Profiles: Strptr((string)(DASH_PROFILE_LIVE)),
78+
Type: Strptr("dynamic"),
79+
MediaPresentationDuration: Strptr(VALID_MEDIA_PRESENTATION_DURATION),
80+
MinBufferTime: Strptr(VALID_MIN_BUFFER_TIME),
81+
AvailabilityStartTime: Strptr(VALID_AVAILABILITY_START_TIME),
82+
MinimumUpdatePeriod: Strptr(VALID_MINIMUM_UPDATE_PERIOD),
6083
period: &Period{},
6184
Periods: []*Period{{}},
6285
}

0 commit comments

Comments
 (0)