diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..9046565 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,24 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.16 + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Regenerate and Test + run: | + make clean fmt + make generate diff --git a/Makefile b/Makefile index 4606220..76ee3cf 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ endif .DEFAULT_GOAL := all .PHONY: all -all: test +all: clean fmt test .PHONY: test test: diff --git a/README.md b/README.md index 89887f0..673fde4 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,13 @@ go get -u github.com/zencoder/go-dash * DRM (ContentProtection) * PlayReady * Widevine +* Scte35 Splice Insert ## Known Limitations (for now) (PRs welcome) * No PSSH/PRO generation * Limited Profile Support +* Scte35 Time Signal ## Example Usage diff --git a/examples/live.go b/examples/live.go index dd955a6..f18ae1f 100644 --- a/examples/live.go +++ b/examples/live.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/zencoder/go-dash/v3/mpd" + "github.com/cbsinteractive/go-dash/v3/mpd" ) func main() { diff --git a/examples/ondemand.go b/examples/ondemand.go index 54463f2..cf95c04 100644 --- a/examples/ondemand.go +++ b/examples/ondemand.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/zencoder/go-dash/v3/mpd" + "github.com/cbsinteractive/go-dash/v3/mpd" ) func exampleOndemand() { diff --git a/go.mod b/go.mod index da472a9..d60a7c1 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/zencoder/go-dash/v3 +module github.com/cbsinteractive/go-dash/v3 -go 1.13 +go 1.16 diff --git a/helpers/require/require.go b/helpers/require/require.go index 58c5fbc..b32c62f 100644 --- a/helpers/require/require.go +++ b/helpers/require/require.go @@ -95,6 +95,7 @@ func EqualStringPtr(t *testing.T, expected, actual *string, msgs ...string) { } func EqualString(t *testing.T, expected, actual string, msgs ...string) { + t.Helper() if expected != actual { t.Errorf("Expected %s but got %s", expected, actual) for _, msg := range msgs { diff --git a/helpers/testfixtures/testfixtures.go b/helpers/testfixtures/testfixtures.go index 754f80d..d00a071 100644 --- a/helpers/testfixtures/testfixtures.go +++ b/helpers/testfixtures/testfixtures.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "github.com/zencoder/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/require" ) // Load test fixture from path relative to fixtures directory @@ -19,6 +19,7 @@ func LoadFixture(path string) (js string) { } func CompareFixture(t *testing.T, fixturePath string, actualContent string) { + t.Helper() expectedContent := LoadFixture(fixturePath) if os.Getenv("GENERATE_FIXTURES") != "" { _ = ioutil.WriteFile(fixturePath, []byte(actualContent), os.ModePerm) diff --git a/mpd/duration.go b/mpd/duration.go index 8ebc870..9baacf3 100644 --- a/mpd/duration.go +++ b/mpd/duration.go @@ -54,29 +54,16 @@ func (d *Duration) String() string { if u < uint64(time.Second) { // Special case: if duration is smaller than a second, // use smaller units, like 1.2ms - var prec int - w-- - buf[w] = 'S' - w-- + // time.Duration & zerocoder packages convert seconds to nano ('nS'), micro ('µS') or milliseconds ('mS') with corresponding designation + // Fix for "Duration must be in the format: P[nD][T[nH][nM][nS]]" error is to keep seconds. if u == 0 { return "PT0S" + } else { + du := float64(u) / float64(time.Second) + s := fmt.Sprintf("%2f", du) + sf := strings.TrimRight(s, "0") + return fmt.Sprintf("PT%sS", sf) } - /* - switch { - case u < uint64(Millisecond): - // print microseconds - prec = 3 - // U+00B5 'µ' micro sign == 0xC2 0xB5 - w-- // Need room for two bytes. - copy(buf[w:], "µ") - default: - // print milliseconds - prec = 6 - buf[w] = 'm' - } - */ - w, u = fmtFrac(buf[:w], u, prec) - w = fmtInt(buf[:w], u) } else { w-- buf[w] = 'S' diff --git a/mpd/duration_test.go b/mpd/duration_test.go index edd29b6..15b7695 100644 --- a/mpd/duration_test.go +++ b/mpd/duration_test.go @@ -5,14 +5,18 @@ import ( "testing" "time" - "github.com/zencoder/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/require" ) func TestDuration(t *testing.T) { in := map[string]string{ - "0s": "PT0S", - "6m16s": "PT6M16S", - "1.97s": "PT1.97S", + "0s": "PT0S", + "6m16s": "PT6M16S", + "1.97s": "PT1.97S", + "1.0s": "PT1S", + "0.0021s": "PT0.0021S", + "0.0000021s": "PT0.000002S", + "0.021s": "PT0.021S", } for ins, ex := range in { timeDur, err := time.ParseDuration(ins) diff --git a/mpd/events.go b/mpd/events.go index 0962918..e937c56 100644 --- a/mpd/events.go +++ b/mpd/events.go @@ -6,13 +6,15 @@ type EventStream struct { XMLName xml.Name `xml:"EventStream"` SchemeIDURI *string `xml:"schemeIdUri,attr"` Value *string `xml:"value,attr,omitempty"` - Timescale *uint `xml:"timescale,attr"` + Timescale *uint64 `xml:"timescale,attr"` Events []Event `xml:"Event,omitempty"` } type Event struct { - XMLName xml.Name `xml:"Event"` - ID *string `xml:"id,attr,omitempty"` - PresentationTime *uint64 `xml:"presentationTime,attr,omitempty"` - Duration *uint64 `xml:"duration,attr,omitempty"` + XMLName xml.Name `xml:"Event"` + ID *string `xml:"id,attr,omitempty"` + SpliceInfoSection *Scte35SpliceInfoSection `xml:"SpliceInfoSection,omitempty"` + PresentationTime *int64 `xml:"presentationTime,attr,omitempty"` + Duration *int64 `xml:"duration,attr,omitempty"` + MessageData *string `xml:"messageData,attr,omitempty"` } diff --git a/mpd/events_test.go b/mpd/events_test.go index 4aa230b..6028e10 100644 --- a/mpd/events_test.go +++ b/mpd/events_test.go @@ -3,15 +3,15 @@ package mpd import ( "testing" - "github.com/zencoder/go-dash/v3/helpers/ptrs" - "github.com/zencoder/go-dash/v3/helpers/require" - "github.com/zencoder/go-dash/v3/helpers/testfixtures" + "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" + "github.com/cbsinteractive/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/testfixtures" ) const ( - VALID_EVENT_STREAM_SCHEME_ID_URI = "urn:example:eventstream" - VALID_EVENT_STREAM_VALUE = "eventstream" - VALID_EVENT_STREAM_TIMESCALE uint = 10 + VALID_EVENT_STREAM_SCHEME_ID_URI = "urn:example:eventstream" + VALID_EVENT_STREAM_VALUE = "eventstream" + VALID_EVENT_STREAM_TIMESCALE uint64 = 10 ) func newEventStreamMPD() *MPD { @@ -25,19 +25,19 @@ func newEventStreamMPD() *MPD { es := EventStream{ SchemeIDURI: ptrs.Strptr(VALID_EVENT_STREAM_SCHEME_ID_URI), Value: ptrs.Strptr(VALID_EVENT_STREAM_VALUE), - Timescale: ptrs.Uintptr(VALID_EVENT_STREAM_TIMESCALE), + Timescale: ptrs.Uint64ptr(VALID_EVENT_STREAM_TIMESCALE), } e0 := Event{ ID: ptrs.Strptr("event-0"), - PresentationTime: ptrs.Uint64ptr(100), - Duration: ptrs.Uint64ptr(50), + PresentationTime: ptrs.Int64ptr(100), + Duration: ptrs.Int64ptr(50), } e1 := Event{ ID: ptrs.Strptr("event-1"), - PresentationTime: ptrs.Uint64ptr(200), - Duration: ptrs.Uint64ptr(50), + PresentationTime: ptrs.Int64ptr(200), + Duration: ptrs.Int64ptr(50), } es.Events = append(es.Events, e0, e1) diff --git a/mpd/fixtures/comment.mpd b/mpd/fixtures/comment.mpd new file mode 100644 index 0000000..d8b1c73 --- /dev/null +++ b/mpd/fixtures/comment.mpd @@ -0,0 +1,3 @@ + + + diff --git a/mpd/fixtures/hbbtv_profile.mpd b/mpd/fixtures/hbbtv_profile.mpd index cc67050..5a87626 100644 --- a/mpd/fixtures/hbbtv_profile.mpd +++ b/mpd/fixtures/hbbtv_profile.mpd @@ -4,11 +4,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -20,11 +20,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -34,10 +34,10 @@ + http://example.com/content/sintel/subtitles/subtitles_en.vtt - diff --git a/mpd/fixtures/live_profile.mpd b/mpd/fixtures/live_profile.mpd index 9a5d844..118c99e 100644 --- a/mpd/fixtures/live_profile.mpd +++ b/mpd/fixtures/live_profile.mpd @@ -4,11 +4,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -18,11 +18,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -32,10 +32,10 @@ + http://example.com/content/sintel/subtitles/subtitles_en.vtt - diff --git a/mpd/fixtures/live_profile_dynamic.mpd b/mpd/fixtures/live_profile_dynamic.mpd index ee34d17..55ce628 100644 --- a/mpd/fixtures/live_profile_dynamic.mpd +++ b/mpd/fixtures/live_profile_dynamic.mpd @@ -4,11 +4,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -18,11 +18,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -32,10 +32,10 @@ + http://example.com/content/sintel/subtitles/subtitles_en.vtt - diff --git a/mpd/fixtures/live_profile_multi_base_url.mpd b/mpd/fixtures/live_profile_multi_base_url.mpd index 6c85d13..a8fda87 100644 --- a/mpd/fixtures/live_profile_multi_base_url.mpd +++ b/mpd/fixtures/live_profile_multi_base_url.mpd @@ -7,11 +7,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -21,11 +21,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== @@ -35,10 +35,10 @@ + http://example.com/content/sintel/subtitles/subtitles_en.vtt - diff --git a/mpd/fixtures/ondemand_profile.mpd b/mpd/fixtures/ondemand_profile.mpd index 58415f7..adeb578 100644 --- a/mpd/fixtures/ondemand_profile.mpd +++ b/mpd/fixtures/ondemand_profile.mpd @@ -1,14 +1,14 @@ - + - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== 800k/output-audio-und.mp4 @@ -21,11 +21,11 @@ - AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== + AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA== BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= - AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== 800k/output-video-1.mp4 @@ -41,10 +41,10 @@ + http://example.com/content/sintel/subtitles/subtitles_en.vtt - diff --git a/mpd/fixtures/scte35.mpd b/mpd/fixtures/scte35.mpd new file mode 100644 index 0000000..b0f7f44 --- /dev/null +++ b/mpd/fixtures/scte35.mpd @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpd/fixtures/segment_list.mpd b/mpd/fixtures/segment_list.mpd index 57aed4d..2fc7de9 100644 --- a/mpd/fixtures/segment_list.mpd +++ b/mpd/fixtures/segment_list.mpd @@ -1,4 +1,5 @@ + http://localhost:8002/dash/ diff --git a/mpd/fixtures/truncate.mpd b/mpd/fixtures/truncate.mpd index 0b1be61..bf92528 100644 --- a/mpd/fixtures/truncate.mpd +++ b/mpd/fixtures/truncate.mpd @@ -1,4 +1,5 @@ + diff --git a/mpd/mpd.go b/mpd/mpd.go index 9972443..b9c1bcf 100644 --- a/mpd/mpd.go +++ b/mpd/mpd.go @@ -5,10 +5,11 @@ import ( "encoding/hex" "encoding/xml" "errors" + "fmt" "strings" "time" - . "github.com/zencoder/go-dash/v3/helpers/ptrs" + . "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" ) // Type definition for DASH profiles @@ -70,34 +71,77 @@ var ( ) type MPD struct { - XMLNs *string `xml:"xmlns,attr"` - XMLNsDolby *string `xml:"xmlns:dolby,attr"` - Profiles *string `xml:"profiles,attr"` - Type *string `xml:"type,attr"` - MediaPresentationDuration *string `xml:"mediaPresentationDuration,attr"` - MinBufferTime *string `xml:"minBufferTime,attr"` - AvailabilityStartTime *string `xml:"availabilityStartTime,attr,omitempty"` - MinimumUpdatePeriod *string `xml:"minimumUpdatePeriod,attr"` - PublishTime *string `xml:"publishTime,attr"` - TimeShiftBufferDepth *string `xml:"timeShiftBufferDepth,attr"` - SuggestedPresentationDelay *Duration `xml:"suggestedPresentationDelay,attr,omitempty"` - BaseURL []string `xml:"BaseURL,omitempty"` - Location string `xml:"Location,omitempty"` + XMLNs *string `xml:"xmlns,attr"` + XMLNsDolby *string `xml:"xmlns:dolby,attr"` + Scte35NS *Scte35NS `xml:"scte35,attr,omitempty"` + XsiNS *XmlnsAttr `xml:"xsi,attr,omitempty"` + XsiSchemaLocation *XsiSL `xml:"schemaLocation,attr,omitempty"` + XsiCENC *XmlnsAttr `xml:"cenc,attr,omitempty"` + XsiMSPR *XmlnsAttr `xml:"mspr,attr,omitempty"` + Profiles *string `xml:"profiles,attr"` + Type *string `xml:"type,attr"` + MediaPresentationDuration *string `xml:"mediaPresentationDuration,attr"` + MinBufferTime *string `xml:"minBufferTime,attr"` + AvailabilityStartTime *string `xml:"availabilityStartTime,attr,omitempty"` + MinimumUpdatePeriod *string `xml:"minimumUpdatePeriod,attr"` + PublishTime *string `xml:"publishTime,attr"` + TimeShiftBufferDepth *string `xml:"timeShiftBufferDepth,attr"` + SuggestedPresentationDelay *Duration `xml:"suggestedPresentationDelay,attr,omitempty"` + BaseURL []string `xml:"BaseURL,omitempty"` + Location string `xml:"Location,omitempty"` period *Period Periods []*Period `xml:"Period,omitempty"` UTCTiming *DescriptorType `xml:"UTCTiming,omitempty"` + ID string `xml:"id,attr,omitempty"` + Comment string `xml:"-"` +} + +type XmlnsAttr struct { + XmlName xml.Name + Value string +} + +func (s *XmlnsAttr) UnmarshalXMLAttr(attr xml.Attr) error { + s.XmlName = attr.Name + s.Value = attr.Value + return nil +} + +func (s *XmlnsAttr) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { + return xml.Attr{Name: xml.Name{Local: fmt.Sprintf("xmlns:%s", s.XmlName.Local)}, Value: s.Value}, nil +} + +type XsiSL struct { + XmlName xml.Name + Value string +} + +func (s *XsiSL) UnmarshalXMLAttr(attr xml.Attr) error { + s.XmlName = attr.Name + s.Value = attr.Value + return nil +} + +func (s *XsiSL) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { + if strings.Contains(s.XmlName.Local, "schemaLocation") { + return xml.Attr{Name: xml.Name{Local: "xsi:schemaLocation"}, Value: s.Value}, nil + } + return xml.Attr{}, nil } type Period struct { - ID string `xml:"id,attr,omitempty"` - Duration Duration `xml:"duration,attr,omitempty"` - Start *Duration `xml:"start,attr,omitempty"` - BaseURL []string `xml:"BaseURL,omitempty"` - SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"` - SegmentList *SegmentList `xml:"SegmentList,omitempty"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` - AdaptationSets []*AdaptationSet `xml:"AdaptationSet,omitempty"` - EventStreams []EventStream `xml:"EventStream,omitempty"` + SupplementalProperty []DescriptorType `xml:"SupplementalProperty,omitempty"` + ID string `xml:"id,attr,omitempty"` + XlinkHref string `xml:"xlink:href,attr,omitempty"` + XlinkActuate string `xml:"xlink:actuate,attr,omitempty"` + Duration Duration `xml:"duration,attr,omitempty"` + Start *Duration `xml:"start,attr,omitempty"` + BaseURL []string `xml:"BaseURL,omitempty"` + SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"` + SegmentList *SegmentList `xml:"SegmentList,omitempty"` + SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` + AdaptationSets []*AdaptationSet `xml:"AdaptationSet,omitempty"` + EventStreams []EventStream `xml:"EventStream,omitempty"` } type DescriptorType struct { @@ -108,25 +152,26 @@ type DescriptorType struct { // ISO 23009-1-2014 5.3.7 type CommonAttributesAndElements struct { - Profiles *string `xml:"profiles,attr"` - Width *string `xml:"width,attr"` - Height *string `xml:"height,attr"` - Sar *string `xml:"sar,attr"` - FrameRate *string `xml:"frameRate,attr"` - AudioSamplingRate *string `xml:"audioSamplingRate,attr"` - MimeType *string `xml:"mimeType,attr"` - SegmentProfiles *string `xml:"segmentProfiles,attr"` - Codecs *string `xml:"codecs,attr"` - MaximumSAPPeriod *string `xml:"maximumSAPPeriod,attr"` - StartWithSAP *int64 `xml:"startWithSAP,attr"` - MaxPlayoutRate *string `xml:"maxPlayoutRate,attr"` - ScanType *string `xml:"scanType,attr"` - FramePacking []DescriptorType `xml:"FramePacking,omitempty"` - AudioChannelConfiguration []DescriptorType `xml:"AudioChannelConfiguration,omitempty"` - ContentProtection []ContentProtectioner `xml:"ContentProtection,omitempty"` - EssentialProperty []DescriptorType `xml:"EssentialProperty,omitempty"` - SupplementalProperty []DescriptorType `xml:"SupplementalProperty,omitempty"` - InbandEventStream []DescriptorType `xml:"InbandEventStream,omitempty"` + Profiles *string `xml:"profiles,attr"` + Width *string `xml:"width,attr"` + Height *string `xml:"height,attr"` + Sar *string `xml:"sar,attr"` + FrameRate *string `xml:"frameRate,attr"` + AudioSamplingRate *string `xml:"audioSamplingRate,attr"` + MimeType *string `xml:"mimeType,attr"` + SegmentProfiles *string `xml:"segmentProfiles,attr"` + Codecs *string `xml:"codecs,attr"` + MaximumSAPPeriod *string `xml:"maximumSAPPeriod,attr"` + StartWithSAP *int64 `xml:"startWithSAP,attr"` + SubsegmentStartsWithSAP *int64 `xml:"subsegmentStartsWithSAP,attr,omitempty"` + MaxPlayoutRate *string `xml:"maxPlayoutRate,attr"` + ScanType *string `xml:"scanType,attr"` + FramePacking []DescriptorType `xml:"FramePacking,omitempty"` + AudioChannelConfiguration []DescriptorType `xml:"AudioChannelConfiguration,omitempty"` + ContentProtection contentProtections `xml:"ContentProtection,omitempty"` + EssentialProperty []DescriptorType `xml:"EssentialProperty,omitempty"` + SupplementalProperty []DescriptorType `xml:"SupplementalProperty,omitempty"` + InbandEventStream []DescriptorType `xml:"InbandEventStream,omitempty"` } type contentProtections []ContentProtectioner @@ -171,27 +216,30 @@ type dtoAdaptationSet struct { type AdaptationSet struct { CommonAttributesAndElements - XMLName xml.Name `xml:"AdaptationSet"` - ID *string `xml:"id,attr"` - SegmentAlignment *bool `xml:"segmentAlignment,attr"` - Lang *string `xml:"lang,attr"` - Group *string `xml:"group,attr"` - PAR *string `xml:"par,attr"` - MinBandwidth *string `xml:"minBandwidth,attr"` - MaxBandwidth *string `xml:"maxBandwidth,attr"` - MinWidth *string `xml:"minWidth,attr"` - MaxWidth *string `xml:"maxWidth,attr"` - MinHeight *string `xml:"minHeight,attr"` - MaxHeight *string `xml:"maxHeight,attr"` - ContentType *string `xml:"contentType,attr"` - Roles []*Role `xml:"Role,omitempty"` - SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"` - SegmentList *SegmentList `xml:"SegmentList,omitempty"` - SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only - Representations []*Representation `xml:"Representation,omitempty"` - AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"` - Labels []string `xml:"Label,omitempty"` - BaseURL []string `xml:"BaseURL,omitempty"` + XMLName xml.Name `xml:"AdaptationSet"` + ID *string `xml:"id,attr"` + SegmentAlignment *bool `xml:"segmentAlignment,attr"` + SubsegmentAlignment *bool `xml:"subsegmentAlignment,attr,omitempty"` + BitstreamSwitching *bool `xml:"bitstreamSwitching,attr,omitempty"` + Lang *string `xml:"lang,attr"` + Group *string `xml:"group,attr"` + PAR *string `xml:"par,attr"` + MinBandwidth *string `xml:"minBandwidth,attr"` + MaxBandwidth *string `xml:"maxBandwidth,attr"` + MinWidth *string `xml:"minWidth,attr"` + MaxWidth *string `xml:"maxWidth,attr"` + MinHeight *string `xml:"minHeight,attr"` + MaxHeight *string `xml:"maxHeight,attr"` + ContentType *string `xml:"contentType,attr"` + SelectionPriority *uint64 `xml:"selectionPriority,attr"` + Roles []*Role `xml:"Role,omitempty"` + SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"` + SegmentList *SegmentList `xml:"SegmentList,omitempty"` + SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only + Labels []string `xml:"Label,omitempty"` + Representations []*Representation `xml:"Representation,omitempty"` + AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"` + BaseURL []string `xml:"BaseURL,omitempty"` } func (as *AdaptationSet) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { @@ -239,16 +287,21 @@ type CENCContentProtection struct { Value *string `xml:"value,attr"` // Default: cenc } +type PSSH struct { + XMLNS *string `xml:"cenc,attr"` + Value *string `xml:",chardata"` +} + type PlayreadyContentProtection struct { ContentProtection PlayreadyXMLNS *string `xml:"mspr,attr,omitempty"` PRO *string `xml:"pro,omitempty"` - PSSH *string `xml:"pssh,omitempty"` + PSSH *PSSH `xml:"pssh,omitempty"` } type WidevineContentProtection struct { ContentProtection - PSSH *string `xml:"pssh,omitempty"` + PSSH *PSSH `xml:"pssh,omitempty"` } type ContentProtectionMarshal struct { @@ -265,16 +318,29 @@ type CENCContentProtectionMarshal struct { Value *string `xml:"value,attr"` // Default: cenc } +type PSSHMarshal struct { + XMLNS *string `xml:"xmlns:cenc,attr"` + Value *string `xml:",chardata"` +} + +func psshToMarshal(pssh *PSSH) *PSSHMarshal { + if pssh == nil { + return nil + } + + return &PSSHMarshal{XMLNS: pssh.XMLNS, Value: pssh.Value} +} + type PlayreadyContentProtectionMarshal struct { ContentProtectionMarshal - PlayreadyXMLNS *string `xml:"xmlns:mspr,attr,omitempty"` - PRO *string `xml:"mspr:pro,omitempty"` - PSSH *string `xml:"cenc:pssh,omitempty"` + PlayreadyXMLNS *string `xml:"xmlns:mspr,attr,omitempty"` + PRO *string `xml:"mspr:pro,omitempty"` + PSSH *PSSHMarshal `xml:"cenc:pssh,omitempty"` } type WidevineContentProtectionMarshal struct { ContentProtectionMarshal - PSSH *string `xml:"cenc:pssh,omitempty"` + PSSH *PSSHMarshal `xml:"cenc:pssh,omitempty"` } func (s ContentProtection) ContentProtected() {} @@ -322,8 +388,9 @@ func (s PlayreadyContentProtection) MarshalXML(e *xml.Encoder, start xml.StartEl }, s.PlayreadyXMLNS, s.PRO, - s.PSSH, + psshToMarshal(s.PSSH), }) + if err != nil { return err } @@ -339,7 +406,7 @@ func (s WidevineContentProtection) MarshalXML(e *xml.Encoder, start xml.StartEle s.XMLNS, s.Attrs, }, - s.PSSH, + psshToMarshal(s.PSSH), }) if err != nil { return err @@ -358,7 +425,7 @@ type SegmentTemplate struct { AdaptationSet *AdaptationSet `xml:"-"` SegmentTimeline *SegmentTimeline `xml:"SegmentTimeline,omitempty"` PresentationTimeOffset *uint64 `xml:"presentationTimeOffset,attr,omitempty"` - Duration *int64 `xml:"duration,attr"` + Duration *float64 `xml:"duration,attr"` Initialization *string `xml:"initialization,attr"` Media *string `xml:"media,attr"` StartNumber *int64 `xml:"startNumber,attr"` @@ -801,7 +868,7 @@ func NewWidevineContentProtection(wvHeader []byte) (*WidevineContentProtection, } psshB64 := base64.StdEncoding.EncodeToString(psshBox) - cp.PSSH = &psshB64 + cp.PSSH = &PSSH{Value: &psshB64, XMLNS: Strptr(CENC_XMLNS)} } return cp, nil } @@ -873,7 +940,7 @@ func (as *AdaptationSet) AddNewContentProtectionSchemePlayreadyWithPSSH(pro stri if err != nil { return nil, err } - cp.PSSH = Strptr(base64.StdEncoding.EncodeToString(psshBox)) + cp.PSSH = &PSSH{Value: Strptr(base64.StdEncoding.EncodeToString(psshBox)), XMLNS: Strptr(CENC_XMLNS)} err = as.AddContentProtection(cp) if err != nil { @@ -905,7 +972,7 @@ func (as *AdaptationSet) AddNewContentProtectionSchemePlayreadyV10WithPSSH(pro s if err != nil { return nil, err } - cp.PSSH = Strptr(base64.StdEncoding.EncodeToString(psshBox)) + cp.PSSH = &PSSH{Value: Strptr(base64.StdEncoding.EncodeToString(psshBox)), XMLNS: Strptr(CENC_XMLNS)} err = as.AddContentProtection(cp) if err != nil { @@ -930,9 +997,9 @@ func (as *AdaptationSet) AddContentProtection(cp ContentProtectioner) error { // media - template string for media segments. // startNumber - the number to start segments from ($Number$) (i.e. 0). // timescale - sets the timescale for duration (i.e. 1000, represents milliseconds). -func (as *AdaptationSet) SetNewSegmentTemplate(duration int64, init string, media string, startNumber int64, timescale int64) (*SegmentTemplate, error) { +func (as *AdaptationSet) SetNewSegmentTemplate(duration float64, init string, media string, startNumber int64, timescale int64) (*SegmentTemplate, error) { st := &SegmentTemplate{ - Duration: Int64ptr(duration), + Duration: Float64ptr(duration), Initialization: Strptr(init), Media: Strptr(media), StartNumber: Int64ptr(startNumber), @@ -961,9 +1028,9 @@ func (as *AdaptationSet) setSegmentTemplate(st *SegmentTemplate) error { // media - template string for media segments. // startNumber - the number to start segments from ($Number$) (i.e. 0). // timescale - sets the timescale for duration (i.e. 1000, represents milliseconds). -func (as *AdaptationSet) SetNewSegmentTemplateThumbnails(duration int64, media string, startNumber int64, timescale int64) (*SegmentTemplate, error) { +func (as *AdaptationSet) SetNewSegmentTemplateThumbnails(duration float64, media string, startNumber int64, timescale int64) (*SegmentTemplate, error) { st := &SegmentTemplate{ - Duration: Int64ptr(duration), + Duration: Float64ptr(duration), Media: Strptr(media), StartNumber: Int64ptr(startNumber), Timescale: Int64ptr(timescale), diff --git a/mpd/mpd_read_write.go b/mpd/mpd_read_write.go index 35d3f9f..dd9e41e 100644 --- a/mpd/mpd_read_write.go +++ b/mpd/mpd_read_write.go @@ -32,7 +32,24 @@ func ReadFromString(xmlStr string) (*MPD, error) { func Read(r io.Reader) (*MPD, error) { var mpd MPD d := xml.NewDecoder(r) - err := d.Decode(&mpd) + var start *xml.StartElement + for { + token, err := d.Token() + if err != nil { + return nil, err + } + switch token := token.(type) { + case xml.Comment: + mpd.Comment = string(token.Copy()) + case xml.StartElement: + start = &token + default: + } + if start != nil { + break + } + } + err := d.DecodeElement(&mpd, start) if err != nil { return nil, err } @@ -75,13 +92,26 @@ func (m *MPD) WriteToString() (string, error) { // Writes an MPD object to an io.Writer interface // w - Must implement the io.Writer interface. func (m *MPD) Write(w io.Writer) error { - b, err := xml.MarshalIndent(m, "", " ") + _, err := w.Write([]byte(xml.Header)) if err != nil { return err } - - _, _ = w.Write([]byte(xml.Header)) - _, _ = w.Write(b) - _, _ = w.Write([]byte("\n")) - return nil + e := xml.NewEncoder(w) + e.Indent("", " ") + if string(m.Comment) != "" { + if err := e.EncodeToken(xml.Comment(m.Comment)); err != nil { + return err + } + if err := e.Flush(); err != nil { + return err + } + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + } + if err := e.Encode(m); err != nil { + return err + } + _, err = w.Write([]byte("\n")) + return err } diff --git a/mpd/mpd_read_write_test.go b/mpd/mpd_read_write_test.go index 80981b3..6934faf 100644 --- a/mpd/mpd_read_write_test.go +++ b/mpd/mpd_read_write_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" - "github.com/zencoder/go-dash/v3/helpers/ptrs" - "github.com/zencoder/go-dash/v3/helpers/require" - "github.com/zencoder/go-dash/v3/helpers/testfixtures" + "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" + "github.com/cbsinteractive/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/testfixtures" ) func TestReadingManifests(t *testing.T) { @@ -150,13 +150,14 @@ func TestAddNewAdaptationSetVideoWriteToString(t *testing.T) { as.MaxWidth = ptrs.Strptr("720") as.MinHeight = ptrs.Strptr("480") as.MaxHeight = ptrs.Strptr("480") + as.SelectionPriority = ptrs.Uint64ptr(5) xmlStr, err := m.WriteToString() require.NoError(t, err) expectedXML := ` - + ` @@ -426,6 +427,7 @@ func OnDemandProfile() *MPD { _, _ = audioAS.AddNewContentProtectionSchemeWidevineWithPSSH(getValidWVHeaderBytes()) _, _ = audioAS.AddNewContentProtectionSchemePlayreadyWithPSSH(VALID_PLAYREADY_PRO) _, _ = audioAS.AddNewAccessibilityElement(ACCESSIBILITY_ELEMENT_SCHEME_DESCRIPTIVE_AUDIO, "1") + audioAS.SelectionPriority = ptrs.Uint64ptr(3) audioRep, _ := audioAS.AddNewRepresentationAudio(44100, 128558, "mp4a.40.5", "800k/audio-und") _ = audioRep.SetNewBaseURL("800k/output-audio-und.mp4") @@ -500,3 +502,20 @@ func TestWriteToFileTruncate(t *testing.T) { xmlStr = testfixtures.LoadFixture(out) testfixtures.CompareFixture(t, "fixtures/truncate_short.mpd", xmlStr) } + +func TestReadComment(t *testing.T) { + m, err := ReadFromFile("fixtures/comment.mpd") + require.NoError(t, err) + require.EqualString(t, "Generated with https://github.com/shaka-project/shaka-packager version 288eddc863-release", string(m.Comment)) +} + +func TestWriteComment(t *testing.T) { + m := MPD{Comment: "Leading Comment"} + s, err := m.WriteToString() + require.NoError(t, err) + answer := ` + + +` + require.EqualString(t, answer, s) +} diff --git a/mpd/mpd_test.go b/mpd/mpd_test.go index 19ab6c1..39d4146 100644 --- a/mpd/mpd_test.go +++ b/mpd/mpd_test.go @@ -6,48 +6,48 @@ import ( "strconv" "testing" - . "github.com/zencoder/go-dash/v3/helpers/ptrs" - "github.com/zencoder/go-dash/v3/helpers/require" - "github.com/zencoder/go-dash/v3/helpers/testfixtures" + . "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" + "github.com/cbsinteractive/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/testfixtures" ) const ( - VALID_MEDIA_PRESENTATION_DURATION string = "PT6M16S" - VALID_MIN_BUFFER_TIME string = "PT1.97S" - VALID_AVAILABILITY_START_TIME string = "1970-01-01T00:00:00Z" - VALID_PUBLISH_TIME string = "2020-03-12T10:39:45Z" - VALID_MINIMUM_UPDATE_PERIOD string = "PT5S" - VALID_SCAN_TYPE string = "progressive" - VALID_SEGMENT_ALIGNMENT bool = true - VALID_START_WITH_SAP int64 = 1 - VALID_LANG string = "en" - VALID_DURATION int64 = 1968 - VALID_INIT_PATH_AUDIO string = "$RepresentationID$/audio/en/init.mp4" - VALID_MEDIA_PATH_AUDIO string = "$RepresentationID$/audio/en/seg-$Number$.m4f" - VALID_START_NUMBER int64 = 0 - VALID_TIMESCALE int64 = 1000 - VALID_AUDIO_SAMPLE_RATE int64 = 44100 - VALID_AUDIO_BITRATE int64 = 67095 - VALID_AUDIO_CODEC string = "mp4a.40.2" - VALID_AUDIO_ID string = "800" - VALID_VIDEO_BITRATE int64 = 1518664 - VALID_VIDEO_CODEC string = "avc1.4d401f" - VALID_VIDEO_ID string = "800" - VALID_VIDEO_FRAMERATE string = "30000/1001" - VALID_VIDEO_WIDTH int64 = 960 - VALID_VIDEO_HEIGHT int64 = 540 - VALID_BASE_URL_VIDEO string = "800k/output-video-1.mp4" - VALID_INDEX_RANGE string = "629-756" - VALID_INIT_RANGE string = "0-628" - VALID_PLAYREADY_PRO string = "BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=" - VALID_WV_HEADER string = "CAESEFq91S9VSk8quNBh92FCUVUaCGNhc3RsYWJzIhhXcjNWTDFWS1R5cTQwR0gzWVVKUlZRPT0yB2RlZmF1bHQ=" - VALID_SUBTITLE_BANDWIDTH int64 = 256 - VALID_SUBTITLE_ID string = "subtitle_en" - VALID_SUBTITLE_LABEL string = "Subtitle (En)" - VALID_SUBTITLE_URL string = "http://example.com/content/sintel/subtitles/subtitles_en.vtt" - VALID_ROLE string = "main" - VALID_LOCATION string = "https://example.com/location.mpd" - VALID_SCHEME_ID_URI string = "https://aomedia.org/emsg/ID3" + VALID_MEDIA_PRESENTATION_DURATION string = "PT6M16S" + VALID_MIN_BUFFER_TIME string = "PT1.97S" + VALID_AVAILABILITY_START_TIME string = "1970-01-01T00:00:00Z" + VALID_MINIMUM_UPDATE_PERIOD string = "PT5S" + VALID_SCAN_TYPE string = "progressive" + VALID_SEGMENT_ALIGNMENT bool = true + VALID_START_WITH_SAP int64 = 1 + VALID_LANG string = "en" + VALID_DURATION float64 = 1968.0 + VALID_INIT_PATH_AUDIO string = "$RepresentationID$/audio/en/init.mp4" + VALID_MEDIA_PATH_AUDIO string = "$RepresentationID$/audio/en/seg-$Number$.m4f" + VALID_START_NUMBER int64 = 0 + VALID_TIMESCALE int64 = 1000 + VALID_AUDIO_SAMPLE_RATE int64 = 44100 + VALID_AUDIO_BITRATE int64 = 67095 + VALID_AUDIO_CODEC string = "mp4a.40.2" + VALID_AUDIO_ID string = "800" + VALID_VIDEO_BITRATE int64 = 1518664 + VALID_VIDEO_CODEC string = "avc1.4d401f" + VALID_VIDEO_ID string = "800" + VALID_VIDEO_FRAMERATE string = "30000/1001" + VALID_VIDEO_WIDTH int64 = 960 + VALID_VIDEO_HEIGHT int64 = 540 + VALID_BASE_URL_VIDEO string = "800k/output-video-1.mp4" + VALID_INDEX_RANGE string = "629-756" + VALID_INIT_RANGE string = "0-628" + VALID_PLAYREADY_PRO string = "BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=" + VALID_WV_HEADER string = "CAESEFq91S9VSk8quNBh92FCUVUaCGNhc3RsYWJzIhhXcjNWTDFWS1R5cTQwR0gzWVVKUlZRPT0yB2RlZmF1bHQ=" + VALID_SUBTITLE_BANDWIDTH int64 = 256 + VALID_SUBTITLE_ID string = "subtitle_en" + VALID_SUBTITLE_URL string = "http://example.com/content/sintel/subtitles/subtitles_en.vtt" + VALID_ROLE string = "main" + VALID_LOCATION string = "https://example.com/location.mpd" + VALID_PUBLISH_TIME string = "2020-03-12T10:39:45Z" + VALID_SUBTITLE_LABEL string = "Subtitle (En)" + VALID_SCHEME_ID_URI string = "https://aomedia.org/emsg/ID3" ) func TestNewMPDLive(t *testing.T) { diff --git a/mpd/pssh_test.go b/mpd/pssh_test.go index a681194..e531c1c 100644 --- a/mpd/pssh_test.go +++ b/mpd/pssh_test.go @@ -3,7 +3,7 @@ package mpd import ( "encoding/base64" "encoding/hex" - "github.com/zencoder/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/require" "testing" ) diff --git a/mpd/scte35.go b/mpd/scte35.go new file mode 100644 index 0000000..defbb2f --- /dev/null +++ b/mpd/scte35.go @@ -0,0 +1,214 @@ +package mpd + +import ( + "encoding/xml" + "strings" +) + +type Scte35NS struct { + XmlName xml.Name + Value string +} + +func (s *Scte35NS) UnmarshalXMLAttr(attr xml.Attr) error { + s.XmlName = attr.Name + s.Value = attr.Value + return nil +} + +func (s *Scte35NS) MarshalXMLAttr(name xml.Name) (xml.Attr, error) { + if strings.Contains(s.XmlName.Local, "scte35") { + return xml.Attr{Name: xml.Name{Local: "xmlns:scte35"}, Value: s.Value}, nil + } + return xml.Attr{}, nil +} + +type Scte35SpliceInfoSection struct { + ProtocolVersion *string `xml:"protocolVersion,attr,omitempty"` + PtsAdjustment *int64 `xml:"ptsAdjustment,attr,omitempty"` + Tier *int64 `xml:"tier,attr,omitempty"` + Scte35SpliceInsert *Scte35SpliceInsert `xml:"SpliceInsert,omitempty"` +} + +type Scte35SpliceInsert struct { + SpliceEventId *string `xml:"spliceEventId,attr,omitempty"` + SpliceEventCancelIndicator bool `xml:"spliceEventCancelIndicator,attr"` + OutOfNetworkIndicator bool `xml:"outOfNetworkIndicator,attr,omitempty"` + SpliceImmediateFlag bool `xml:"spliceImmediateFlag,attr"` + UniqueProgramId *string `xml:"uniqueProgramId,attr,omitempty"` + AvailNum *int64 `xml:"availNum,attr,omitempty"` + AvailsExpected *int64 `xml:"availsExpected,attr,omitempty"` + Program *Scte35Program `xml:"Program,omitempty"` + BreakDuration *Scte35BreakDuration `xml:"BreakDuration,omitempty"` +} + +type Scte35Program struct { + Scte35SpliceTime *Scte35SpliceTime `xml:"SpliceTime,omitempty"` +} + +type Scte35SpliceTime struct { + PtsTime *int64 `xml:"ptsTime,attr,omitempty"` +} + +type Scte35BreakDuration struct { + AutoReturn bool `xml:"autoReturn,attr,omitempty"` + Duration *int64 `xml:"duration,attr,omitempty"` +} + +// Wrappers for handlings unmarshalling, since golang's xml namespace handling is horrifying. +type wrappedScte35Program Scte35Program +type wrappedScte35SpliceTime Scte35SpliceTime +type wrappedScte35BreakDuration Scte35BreakDuration +type wrappedScte35SpliceInsert Scte35SpliceInsert +type wrappedScte35SpliceInfoSection Scte35SpliceInfoSection + +type dtoScte35Program struct { + wrappedScte35Program +} + +type dtoScte35SpliceTime struct { + wrappedScte35SpliceTime +} + +type dtoScte35BreakDuration struct { + wrappedScte35BreakDuration +} + +type dtoScte35SpliceInsert struct { + wrappedScte35SpliceInsert +} + +type dtoScte35SpliceInfoSection struct { + wrappedScte35SpliceInfoSection +} + +// Wrappers for handling marshalling, since golangs xml namespace handling is horrifying. +type Scte35ProgramMarshal struct { + XMLName xml.Name + Scte35SpliceTime *Scte35SpliceTime `xml:",omitempty"` +} + +type Scte35SpliceTimeMarshal struct { + XMLName xml.Name + PtsTime *int64 `xml:"ptsTime,attr,omitempty"` +} + +type Scte35BreakDurationMarshal struct { + XMLName xml.Name + AutoReturn bool `xml:"autoReturn,attr,omitempty"` + Duration *int64 `xml:"duration,attr,omitempty"` +} + +type Scte35SpliceInfoSectionMarshal struct { + XMLName xml.Name + ProtocolVersion *string `xml:"protocolVersion,attr,omitempty"` + PtsAdjustment *int64 `xml:"ptsAdjustment,attr,omitempty"` + Tier *int64 `xml:"tier,attr,omitempty"` + Scte35SpliceInsert *Scte35SpliceInsert `xml:"SpliceInsert,omitempty"` +} + +type Scte35SpliceInsertMarshal struct { + XMLName xml.Name + SpliceEventId *string `xml:"spliceEventId,attr,omitempty"` + SpliceEventCancelIndicator bool `xml:"spliceEventCancelIndicator,attr"` + OutOfNetworkIndicator bool `xml:"outOfNetworkIndicator,attr,omitempty"` + SpliceImmediateFlag bool `xml:"spliceImmediateFlag,attr"` + UniqueProgramId *string `xml:"uniqueProgramId,attr,omitempty"` + AvailNum *int64 `xml:"availNum,attr,omitempty"` + AvailsExpected *int64 `xml:"availsExpected,attr,omitempty"` + Program *Scte35Program `xml:"Program,omitempty"` + BreakDuration *Scte35BreakDuration `xml:"BreakDuration,omitempty"` +} + +// unmarshal/marshal functions for Scte35 structures +func (s *Scte35Program) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var _s dtoScte35Program + if err := d.DecodeElement(&_s, &start); err != nil { + return err + } + *s = Scte35Program(_s.wrappedScte35Program) + return nil +} + +func (s *Scte35Program) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(&Scte35ProgramMarshal{ + XMLName: xml.Name{Local: "scte35:Program"}, + Scte35SpliceTime: s.Scte35SpliceTime, + }) +} + +func (s *Scte35SpliceTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var _s dtoScte35SpliceTime + if err := d.DecodeElement(&_s, &start); err != nil { + return err + } + *s = Scte35SpliceTime(_s.wrappedScte35SpliceTime) + return nil +} + +func (s *Scte35SpliceTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(&Scte35SpliceTimeMarshal{ + XMLName: xml.Name{Local: "scte35:SpliceTime"}, + PtsTime: s.PtsTime, + }) +} + +func (s *Scte35BreakDuration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var _s dtoScte35BreakDuration + if err := d.DecodeElement(&_s, &start); err != nil { + return err + } + *s = Scte35BreakDuration(_s.wrappedScte35BreakDuration) + return nil +} + +func (s *Scte35BreakDuration) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(&Scte35BreakDurationMarshal{ + XMLName: xml.Name{Local: "scte35:BreakDuration"}, + AutoReturn: s.AutoReturn, + Duration: s.Duration, + }) +} + +func (s *Scte35SpliceInsert) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var _s dtoScte35SpliceInsert + if err := d.DecodeElement(&_s, &start); err != nil { + return err + } + *s = Scte35SpliceInsert(_s.wrappedScte35SpliceInsert) + return nil +} + +func (s *Scte35SpliceInsert) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(&Scte35SpliceInsertMarshal{ + XMLName: xml.Name{Local: "scte35:SpliceInsert"}, + SpliceEventId: s.SpliceEventId, + SpliceEventCancelIndicator: s.SpliceEventCancelIndicator, + OutOfNetworkIndicator: s.OutOfNetworkIndicator, + SpliceImmediateFlag: s.SpliceImmediateFlag, + UniqueProgramId: s.UniqueProgramId, + AvailNum: s.AvailNum, + AvailsExpected: s.AvailsExpected, + Program: s.Program, + BreakDuration: s.BreakDuration, + }) +} + +func (s *Scte35SpliceInfoSection) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var _s dtoScte35SpliceInfoSection + if err := d.DecodeElement(&_s, &start); err != nil { + return err + } + *s = Scte35SpliceInfoSection(_s.wrappedScte35SpliceInfoSection) + return nil +} + +func (s *Scte35SpliceInfoSection) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(&Scte35SpliceInfoSectionMarshal{ + XMLName: xml.Name{Local: "scte35:SpliceInfoSection"}, + ProtocolVersion: s.ProtocolVersion, + PtsAdjustment: s.PtsAdjustment, + Tier: s.Tier, + Scte35SpliceInsert: s.Scte35SpliceInsert, + }) +} diff --git a/mpd/segment_list_test.go b/mpd/segment_list_test.go index 40cf500..49f364d 100644 --- a/mpd/segment_list_test.go +++ b/mpd/segment_list_test.go @@ -3,9 +3,9 @@ package mpd import ( "testing" - "github.com/zencoder/go-dash/v3/helpers/ptrs" - "github.com/zencoder/go-dash/v3/helpers/require" - "github.com/zencoder/go-dash/v3/helpers/testfixtures" + "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" + "github.com/cbsinteractive/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/testfixtures" ) func TestSegmentListSerialization(t *testing.T) { @@ -23,6 +23,7 @@ func TestSegmentListDeserialization(t *testing.T) { if err == nil { expected := getSegmentListMPD() + require.EqualString(t, m.Comment, "Generated with https://github.com/shaka-project/shaka-packager version 288eddc863-release") require.EqualStringSlice(t, expected.Periods[0].BaseURL, m.Periods[0].BaseURL) expectedAudioSegList := expected.Periods[0].AdaptationSets[0].Representations[0].SegmentList @@ -60,6 +61,7 @@ func TestSegmentListDeserialization(t *testing.T) { func getSegmentListMPD() *MPD { m := NewMPD(DASH_PROFILE_LIVE, "PT30.016S", "PT2.000S") m.period.BaseURL = []string{"http://localhost:8002/dash/"} + m.Comment = "Generated with https://github.com/shaka-project/shaka-packager version 288eddc863-release" aas, _ := m.AddNewAdaptationSetAudioWithID("1", "audio/mp4", true, 1, "English") ra, _ := aas.AddNewRepresentationAudio(48000, 255000, "mp4a.40.2", "audio_1") diff --git a/mpd/segment_timeline_test.go b/mpd/segment_timeline_test.go index 1e9ee1d..29997e8 100644 --- a/mpd/segment_timeline_test.go +++ b/mpd/segment_timeline_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" - "github.com/zencoder/go-dash/v3/helpers/ptrs" - "github.com/zencoder/go-dash/v3/helpers/require" - "github.com/zencoder/go-dash/v3/helpers/testfixtures" + "github.com/cbsinteractive/go-dash/v3/helpers/ptrs" + "github.com/cbsinteractive/go-dash/v3/helpers/require" + "github.com/cbsinteractive/go-dash/v3/helpers/testfixtures" ) func TestSegmentTimelineSerialization(t *testing.T) {