Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7b7c37d

Browse filesBrowse files
Merge pull request #9 from cbsinteractive/scte35-splice-insert
Support Scte35 Splice Inserts in EventStream.
2 parents e1a70e6 + 8beae51 commit 7b7c37d
Copy full SHA for 7b7c37d

File tree

6 files changed

+382
-66
lines changed
Filter options

6 files changed

+382
-66
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ go get -u github.com/zencoder/go-dash
2121
* DRM (ContentProtection)
2222
* PlayReady
2323
* Widevine
24+
* Scte35 Splice Insert
2425

2526
## Known Limitations (for now) (PRs welcome)
2627

2728
* No PSSH/PRO generation
2829
* Limited Profile Support
30+
* Scte35 Time Signal
2931

3032
## Example Usage
3133

‎mpd/events.go

Copy file name to clipboardExpand all lines: mpd/events.go
+5-4Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ type EventStream struct {
1111
}
1212

1313
type Event struct {
14-
XMLName xml.Name `xml:"Event"`
15-
ID *string `xml:"id,attr,omitempty"`
16-
PresentationTime *int64 `xml:"presentationTime,attr,omitempty"`
17-
Duration *int64 `xml:"duration,attr,omitempty"`
14+
XMLName xml.Name `xml:"Event"`
15+
ID *string `xml:"id,attr,omitempty"`
16+
SpliceInfoSection *Scte35SpliceInfoSection `xml:"SpliceInfoSection,omitempty"`
17+
PresentationTime *int64 `xml:"presentationTime,attr,omitempty"`
18+
Duration *int64 `xml:"duration,attr,omitempty"`
1819
}

‎mpd/fixtures/scte35.mpd

Copy file name to clipboard
+55Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:scte35="urn:scte:scte35:2013:xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-live:2011" type="dynamic" minBufferTime="PT30S" availabilityStartTime="2020-10-26T20:23:21.839000+00:00" minimumUpdatePeriod="PT15S" publishTime="2020-10-26T21:31:19" timeShiftBufferDepth="PT118.999S" suggestedPresentationDelay="PT25S" id="201">
3+
<Period id="545" start="PT32.808S">
4+
<SupplementalProperty schemeIdUri="urn:scte:dash:utc-time" value="2020-10-26T00:54:05.508Z"></SupplementalProperty>
5+
<AdaptationSet mimeType="video/mp4" startWithSAP="1" subsegmentStartsWithSAP="1" segmentAlignment="true" subsegmentAlignment="true" bitstreamSwitching="true">
6+
<Representation bandwidth="249984" codecs="avc1.64000D" frameRate="30000/1001" height="224" id="1" width="400">
7+
<SegmentTemplate presentationTimeOffset="97434268" initialization="manifest_video_1_0_init.mp4?m=1603743253" media="manifest_video_1_0_$Number$.mp4?m=1603743253" startNumber="665" timescale="30000">
8+
<SegmentTimeline>
9+
<S t="118867680" d="180180" r="19"></S>
10+
</SegmentTimeline>
11+
</SegmentTemplate>
12+
</Representation>
13+
</AdaptationSet>
14+
<AdaptationSet mimeType="audio/mp4" segmentAlignment="false" lang="und">
15+
<Representation audioSamplingRate="48000" bandwidth="66574" codecs="mp4a.40.2" id="8">
16+
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"></AudioChannelConfiguration>
17+
<SegmentTemplate presentationTimeOffset="155895040" initialization="manifest_audio_2_0_init.mp4?m=1603743253" media="manifest_audio_2_0_$Number$.mp4?m=1603743253" startNumber="665" timescale="48000">
18+
<SegmentTimeline>
19+
<S t="190188800" d="288768"></S>
20+
<S t="190477568" d="287744"></S>
21+
<S t="190765312" d="288768"></S>
22+
<S t="191054080" d="287744"></S>
23+
<S t="191341824" d="288768"></S>
24+
<S t="191630592" d="287744"></S>
25+
<S t="191918336" d="288768"></S>
26+
<S t="192207104" d="287744"></S>
27+
<S t="192494848" d="288768"></S>
28+
<S t="192783616" d="287744"></S>
29+
<S t="193071360" d="288768"></S>
30+
<S t="193360128" d="287744"></S>
31+
<S t="193647872" d="288768"></S>
32+
<S t="193936640" d="287744"></S>
33+
<S t="194224384" d="288768"></S>
34+
<S t="194513152" d="287744"></S>
35+
<S t="194800896" d="288768" r="1"></S>
36+
<S t="195378432" d="287744"></S>
37+
<S t="195666176" d="288768"></S>
38+
</SegmentTimeline>
39+
</SegmentTemplate>
40+
</Representation>
41+
</AdaptationSet>
42+
<EventStream schemeIdUri="urn:scte:scte35:2013:xml" timescale="90000">
43+
<Event duration="4051047">
44+
<scte35:SpliceInfoSection protocolVersion="0" ptsAdjustment="207000" tier="4095">
45+
<scte35:SpliceInsert spliceEventId="1603904856" spliceEventCancelIndicator="false" outOfNetworkIndicator="true" spliceImmediateFlag="false" uniqueProgramId="1" availNum="1" availsExpected="1">
46+
<scte35:Program>
47+
<scte35:SpliceTime ptsTime="5905840702"></scte35:SpliceTime>
48+
</scte35:Program>
49+
<scte35:BreakDuration autoReturn="true" duration="4051047"></scte35:BreakDuration>
50+
</scte35:SpliceInsert>
51+
</scte35:SpliceInfoSection>
52+
</Event>
53+
</EventStream>
54+
</Period>
55+
</MPD>

‎mpd/mpd.go

Copy file name to clipboardExpand all lines: mpd/mpd.go
+73-29Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ var (
6868

6969
type MPD struct {
7070
XMLNs *string `xml:"xmlns,attr"`
71+
Scte35NS *Scte35NS `xml:"scte35,attr,omitempty"`
72+
XsiNS *XsiNS `xml:"xsi,attr,omitempty"`
73+
XsiSchemaLocation *XsiSL `xml:"schemaLocation,attr,omitempty"`
7174
Profiles *string `xml:"profiles,attr"`
7275
Type *string `xml:"type,attr"`
7376
MediaPresentationDuration *string `xml:"mediaPresentationDuration,attr"`
@@ -82,18 +85,56 @@ type MPD struct {
8285
period *Period
8386
Periods []*Period `xml:"Period,omitempty"`
8487
UTCTiming *DescriptorType `xml:"UTCTiming,omitempty"`
88+
ID string `xml:"id,attr,omitempty"`
89+
}
90+
91+
type XsiNS struct {
92+
XmlName xml.Name
93+
Value string
94+
}
95+
96+
func (s *XsiNS) UnmarshalXMLAttr(attr xml.Attr) error {
97+
s.XmlName = attr.Name
98+
s.Value = attr.Value
99+
return nil
100+
}
101+
102+
func (s *XsiNS) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
103+
if strings.Contains(s.XmlName.Local, "xsi") {
104+
return xml.Attr{Name: xml.Name{Local: "xmlns:xsi"}, Value: s.Value}, nil
105+
}
106+
return xml.Attr{}, nil
107+
}
108+
109+
type XsiSL struct {
110+
XmlName xml.Name
111+
Value string
112+
}
113+
114+
func (s *XsiSL) UnmarshalXMLAttr(attr xml.Attr) error {
115+
s.XmlName = attr.Name
116+
s.Value = attr.Value
117+
return nil
118+
}
119+
120+
func (s *XsiSL) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
121+
if strings.Contains(s.XmlName.Local, "schemaLocation") {
122+
return xml.Attr{Name: xml.Name{Local: "xsi:schemaLocation"}, Value: s.Value}, nil
123+
}
124+
return xml.Attr{}, nil
85125
}
86126

87127
type Period struct {
88-
ID string `xml:"id,attr,omitempty"`
89-
Duration Duration `xml:"duration,attr,omitempty"`
90-
Start *Duration `xml:"start,attr,omitempty"`
91-
BaseURL string `xml:"BaseURL,omitempty"`
92-
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
93-
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
94-
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"`
95-
AdaptationSets []*AdaptationSet `xml:"AdaptationSet,omitempty"`
96-
EventStreams []EventStream `xml:"EventStream,omitempty"`
128+
SupplementalProperty []DescriptorType `xml:"SupplementalProperty,omitempty"`
129+
ID string `xml:"id,attr,omitempty"`
130+
Duration Duration `xml:"duration,attr,omitempty"`
131+
Start *Duration `xml:"start,attr,omitempty"`
132+
BaseURL string `xml:"BaseURL,omitempty"`
133+
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
134+
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
135+
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"`
136+
AdaptationSets []*AdaptationSet `xml:"AdaptationSet,omitempty"`
137+
EventStreams []EventStream `xml:"EventStream,omitempty"`
97138
}
98139

99140
type DescriptorType struct {
@@ -115,6 +156,7 @@ type CommonAttributesAndElements struct {
115156
Codecs *string `xml:"codecs,attr"`
116157
MaximumSAPPeriod *string `xml:"maximumSAPPeriod,attr"`
117158
StartWithSAP *int64 `xml:"startWithSAP,attr"`
159+
SubsegmentStartsWithSAP *int64 `xml:"subsegmentStartsWithSAP,attr,omitempty"`
118160
MaxPlayoutRate *string `xml:"maxPlayoutRate,attr"`
119161
ScanType *string `xml:"scanType,attr"`
120162
FramePacking []DescriptorType `xml:"FramePacking,omitempty"`
@@ -167,26 +209,28 @@ type dtoAdaptationSet struct {
167209

168210
type AdaptationSet struct {
169211
CommonAttributesAndElements
170-
XMLName xml.Name `xml:"AdaptationSet"`
171-
ID *string `xml:"id,attr"`
172-
SegmentAlignment *bool `xml:"segmentAlignment,attr"`
173-
Lang *string `xml:"lang,attr"`
174-
Group *string `xml:"group,attr"`
175-
PAR *string `xml:"par,attr"`
176-
MinBandwidth *string `xml:"minBandwidth,attr"`
177-
MaxBandwidth *string `xml:"maxBandwidth,attr"`
178-
MinWidth *string `xml:"minWidth,attr"`
179-
MaxWidth *string `xml:"maxWidth,attr"`
180-
MinHeight *string `xml:"minHeight,attr"`
181-
MaxHeight *string `xml:"maxHeight,attr"`
182-
ContentType *string `xml:"contentType,attr"`
183-
SelectionPriority *uint64 `xml:"selectionPriority,attr"`
184-
Roles []*Role `xml:"Role,omitempty"`
185-
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
186-
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
187-
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
188-
Representations []*Representation `xml:"Representation,omitempty"`
189-
AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"`
212+
XMLName xml.Name `xml:"AdaptationSet"`
213+
ID *string `xml:"id,attr"`
214+
SegmentAlignment *bool `xml:"segmentAlignment,attr"`
215+
SubsegmentAlignment *bool `xml:"subsegmentAlignment,attr,omitempty"`
216+
BitstreamSwitching *bool `xml:"bitstreamSwitching,attr,omitempty"`
217+
Lang *string `xml:"lang,attr"`
218+
Group *string `xml:"group,attr"`
219+
PAR *string `xml:"par,attr"`
220+
MinBandwidth *string `xml:"minBandwidth,attr"`
221+
MaxBandwidth *string `xml:"maxBandwidth,attr"`
222+
MinWidth *string `xml:"minWidth,attr"`
223+
MaxWidth *string `xml:"maxWidth,attr"`
224+
MinHeight *string `xml:"minHeight,attr"`
225+
MaxHeight *string `xml:"maxHeight,attr"`
226+
ContentType *string `xml:"contentType,attr"`
227+
SelectionPriority *uint64 `xml:"selectionPriority,attr"`
228+
Roles []*Role `xml:"Role,omitempty"`
229+
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
230+
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
231+
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
232+
Representations []*Representation `xml:"Representation,omitempty"`
233+
AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"`
190234
}
191235

192236
func (as *AdaptationSet) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {

‎mpd/mpd_test.go

Copy file name to clipboardExpand all lines: mpd/mpd_test.go
+33-33Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,39 @@ import (
1111
)
1212

1313
const (
14-
VALID_MEDIA_PRESENTATION_DURATION string = "PT6M16S"
15-
VALID_MIN_BUFFER_TIME string = "PT1.97S"
16-
VALID_AVAILABILITY_START_TIME string = "1970-01-01T00:00:00Z"
17-
VALID_MINIMUM_UPDATE_PERIOD string = "PT5S"
18-
VALID_SCAN_TYPE string = "progressive"
19-
VALID_SEGMENT_ALIGNMENT bool = true
20-
VALID_START_WITH_SAP int64 = 1
21-
VALID_LANG string = "en"
22-
VALID_DURATION int64 = 1968
23-
VALID_INIT_PATH_AUDIO string = "$RepresentationID$/audio/en/init.mp4"
24-
VALID_MEDIA_PATH_AUDIO string = "$RepresentationID$/audio/en/seg-$Number$.m4f"
25-
VALID_START_NUMBER int64 = 0
26-
VALID_TIMESCALE int64 = 1000
27-
VALID_AUDIO_SAMPLE_RATE int64 = 44100
28-
VALID_AUDIO_BITRATE int64 = 67095
29-
VALID_AUDIO_CODEC string = "mp4a.40.2"
30-
VALID_AUDIO_ID string = "800"
31-
VALID_VIDEO_BITRATE int64 = 1518664
32-
VALID_VIDEO_CODEC string = "avc1.4d401f"
33-
VALID_VIDEO_ID string = "800"
34-
VALID_VIDEO_FRAMERATE string = "30000/1001"
35-
VALID_VIDEO_WIDTH int64 = 960
36-
VALID_VIDEO_HEIGHT int64 = 540
37-
VALID_BASE_URL_VIDEO string = "800k/output-video-1.mp4"
38-
VALID_INDEX_RANGE string = "629-756"
39-
VALID_INIT_RANGE string = "0-628"
40-
VALID_PLAYREADY_PRO string = "BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA="
41-
VALID_WV_HEADER string = "CAESEFq91S9VSk8quNBh92FCUVUaCGNhc3RsYWJzIhhXcjNWTDFWS1R5cTQwR0gzWVVKUlZRPT0yB2RlZmF1bHQ="
42-
VALID_SUBTITLE_BANDWIDTH int64 = 256
43-
VALID_SUBTITLE_ID string = "subtitle_en"
44-
VALID_SUBTITLE_URL string = "http://example.com/content/sintel/subtitles/subtitles_en.vtt"
45-
VALID_ROLE string = "main"
46-
VALID_LOCATION string = "https://example.com/location.mpd"
14+
VALID_MEDIA_PRESENTATION_DURATION string = "PT6M16S"
15+
VALID_MIN_BUFFER_TIME string = "PT1.97S"
16+
VALID_AVAILABILITY_START_TIME string = "1970-01-01T00:00:00Z"
17+
VALID_MINIMUM_UPDATE_PERIOD string = "PT5S"
18+
VALID_SCAN_TYPE string = "progressive"
19+
VALID_SEGMENT_ALIGNMENT bool = true
20+
VALID_START_WITH_SAP int64 = 1
21+
VALID_LANG string = "en"
22+
VALID_DURATION float64 = 1968.0
23+
VALID_INIT_PATH_AUDIO string = "$RepresentationID$/audio/en/init.mp4"
24+
VALID_MEDIA_PATH_AUDIO string = "$RepresentationID$/audio/en/seg-$Number$.m4f"
25+
VALID_START_NUMBER int64 = 0
26+
VALID_TIMESCALE int64 = 1000
27+
VALID_AUDIO_SAMPLE_RATE int64 = 44100
28+
VALID_AUDIO_BITRATE int64 = 67095
29+
VALID_AUDIO_CODEC string = "mp4a.40.2"
30+
VALID_AUDIO_ID string = "800"
31+
VALID_VIDEO_BITRATE int64 = 1518664
32+
VALID_VIDEO_CODEC string = "avc1.4d401f"
33+
VALID_VIDEO_ID string = "800"
34+
VALID_VIDEO_FRAMERATE string = "30000/1001"
35+
VALID_VIDEO_WIDTH int64 = 960
36+
VALID_VIDEO_HEIGHT int64 = 540
37+
VALID_BASE_URL_VIDEO string = "800k/output-video-1.mp4"
38+
VALID_INDEX_RANGE string = "629-756"
39+
VALID_INIT_RANGE string = "0-628"
40+
VALID_PLAYREADY_PRO string = "BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA="
41+
VALID_WV_HEADER string = "CAESEFq91S9VSk8quNBh92FCUVUaCGNhc3RsYWJzIhhXcjNWTDFWS1R5cTQwR0gzWVVKUlZRPT0yB2RlZmF1bHQ="
42+
VALID_SUBTITLE_BANDWIDTH int64 = 256
43+
VALID_SUBTITLE_ID string = "subtitle_en"
44+
VALID_SUBTITLE_URL string = "http://example.com/content/sintel/subtitles/subtitles_en.vtt"
45+
VALID_ROLE string = "main"
46+
VALID_LOCATION string = "https://example.com/location.mpd"
4747
)
4848

4949
func TestNewMPDLive(t *testing.T) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.