Skip to content

Commit ac2f9cc

Browse files
authored
Merge pull request #77 from zencoder/cleanup-attempt
Remove crazy nested Unmarshal
2 parents 42b9329 + 4442d1c commit ac2f9cc

File tree

2 files changed

+84
-160
lines changed

2 files changed

+84
-160
lines changed

mpd/fixtures/adaptationset_switching.mpd

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
</Representation>
1313
</AdaptationSet>
1414
<AdaptationSet mimeType="video/mp4" startWithSAP="1" scanType="progressive" id="2" segmentAlignment="true">
15+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
16+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" xmlns:cenc="urn:mpeg:cenc:2013">
17+
<cenc:pssh>AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA==</cenc:pssh>
18+
</ContentProtection>
19+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mspr="urn:microsoft:playready">
20+
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
21+
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
22+
</ContentProtection>
1523
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="3"></SupplementalProperty>
1624
<Representation bandwidth="4172274" codecs="avc1.640028" frameRate="30000/1001" height="720" id="video_1" width="1280">
1725
<SegmentList timescale="30000" duration="225120">
@@ -21,6 +29,14 @@
2129
</Representation>
2230
</AdaptationSet>
2331
<AdaptationSet mimeType="video/hevc" startWithSAP="1" scanType="progressive" id="3" segmentAlignment="true">
32+
<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" xmlns:cenc="urn:mpeg:cenc:2013" cenc:default_KID="08e36702-8f33-436c-a5dd-60ffe5571e60" value="cenc"></ContentProtection>
33+
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" xmlns:cenc="urn:mpeg:cenc:2013">
34+
<cenc:pssh>AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQWr3VL1VKTyq40GH3YUJRVRoIY2FzdGxhYnMiGFdyM1ZMMVZLVHlxNDBHSDNZVUpSVlE9PTIHZGVmYXVsdA==</cenc:pssh>
35+
</ContentProtection>
36+
<ContentProtection schemeIdUri="urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95" xmlns:cenc="urn:mpeg:cenc:2013" xmlns:mspr="urn:microsoft:playready">
37+
<mspr:pro>BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4ATAA5AFcAOQBXAGsAcABWAEsAawArADQAMABHAEgAMwBZAFUASgBSAFYAUQA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgBJAEsAegBZADIASABaAEwAQQBsAEkAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
38+
<cenc:pssh>AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBMADkAVwA5AFcAawBwAFYASwBrACsANAAwAEcASAAzAFkAVQBKAFIAVgBRAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+AEkASwB6AFkAMgBIAFoATABBAGwASQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
39+
</ContentProtection>
2440
<SupplementalProperty schemeIdUri="urn:mpeg:dash:adaptation-set-switching:2016" value="2"></SupplementalProperty>
2541
<Representation bandwidth="4172274" codecs="avc1.640028" frameRate="30000/1001" height="720" id="video_1" width="1280">
2642
<SegmentList timescale="30000" duration="225120">

mpd/mpd.go

Lines changed: 68 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/hex"
66
"encoding/xml"
77
"errors"
8-
"fmt"
98
"strings"
109
"time"
1110

@@ -126,171 +125,80 @@ type CommonAttributesAndElements struct {
126125
InbandEventStream *DescriptorType `xml:"inbandEventStream,attr"`
127126
}
128127

128+
type contentProtections []ContentProtectioner
129+
130+
func (as *contentProtections) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
131+
var scheme string
132+
for _, a := range start.Attr {
133+
if a.Name.Local == "schemeIdUri" {
134+
scheme = a.Value
135+
break
136+
}
137+
}
138+
var target ContentProtectioner
139+
switch scheme {
140+
case CONTENT_PROTECTION_ROOT_SCHEME_ID_URI:
141+
target = &CENCContentProtection{}
142+
case CONTENT_PROTECTION_PLAYREADY_SCHEME_ID:
143+
target = &PlayreadyContentProtection{}
144+
case CONTENT_PROTECTION_WIDEVINE_SCHEME_ID:
145+
target = &WidevineContentProtection{}
146+
default:
147+
target = &ContentProtection{}
148+
}
149+
if err := d.DecodeElement(target, &start); err != nil {
150+
return err
151+
}
152+
*as = append(*as, target)
153+
return nil
154+
}
155+
156+
// wrappedAdaptationSet provides the default xml unmarshal
157+
// to take care of the majority of our unmarshalling
158+
type wrappedAdaptationSet AdaptationSet
159+
160+
// dtoAdaptationSet parses the items out of AdaptationSet
161+
// that give us trouble:
162+
// * Content Protection interface
163+
type dtoAdaptationSet struct {
164+
wrappedAdaptationSet
165+
ContentProtection contentProtections `xml:"ContentProtection,omitempty"`
166+
}
167+
129168
type AdaptationSet struct {
130169
CommonAttributesAndElements
131-
XMLName xml.Name `xml:"AdaptationSet"`
132-
ID *string `xml:"id,attr"`
133-
SegmentAlignment *bool `xml:"segmentAlignment,attr"`
134-
Lang *string `xml:"lang,attr"`
135-
Group *string `xml:"group,attr"`
136-
PAR *string `xml:"par,attr"`
137-
MinBandwidth *string `xml:"minBandwidth,attr"`
138-
MaxBandwidth *string `xml:"maxBandwidth,attr"`
139-
MinWidth *string `xml:"minWidth,attr"`
140-
MaxWidth *string `xml:"maxWidth,attr"`
141-
MinHeight *string `xml:"minHeight,attr"`
142-
MaxHeight *string `xml:"maxHeight,attr"`
143-
ContentType *string `xml:"contentType,attr"`
144-
ContentProtection []ContentProtectioner `xml:"ContentProtection,omitempty"` // Common attribute, can be deprecated here
145-
Roles []*Role `xml:"Role,omitempty"`
146-
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
147-
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
148-
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
149-
Representations []*Representation `xml:"Representation,omitempty"`
150-
AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"`
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+
Roles []*Role `xml:"Role,omitempty"`
184+
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
185+
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
186+
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
187+
Representations []*Representation `xml:"Representation,omitempty"`
188+
AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"`
151189
}
152190

153191
func (as *AdaptationSet) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
154-
var (
155-
adaptationSet struct {
156-
CommonAttributesAndElements
157-
XMLName xml.Name `xml:"AdaptationSet"`
158-
ID *string `xml:"id,attr"`
159-
SegmentAlignment *bool `xml:"segmentAlignment,attr"`
160-
Lang *string `xml:"lang,attr"`
161-
Group *string `xml:"group,attr"`
162-
PAR *string `xml:"par,attr"`
163-
MinBandwidth *string `xml:"minBandwidth,attr"`
164-
MaxBandwidth *string `xml:"maxBandwidth,attr"`
165-
MinWidth *string `xml:"minWidth,attr"`
166-
MaxWidth *string `xml:"maxWidth,attr"`
167-
MinHeight *string `xml:"minHeight,attr"`
168-
MaxHeight *string `xml:"maxHeight,attr"`
169-
ContentType *string `xml:"contentType,attr"`
170-
ContentProtection []ContentProtectioner `xml:"ContentProtection,omitempty"` // Common attribute, can be deprecated here
171-
Roles []*Role `xml:"Role,omitempty"`
172-
SegmentBase *SegmentBase `xml:"SegmentBase,omitempty"`
173-
SegmentList *SegmentList `xml:"SegmentList,omitempty"`
174-
SegmentTemplate *SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
175-
Representations []*Representation `xml:"Representation,omitempty"`
176-
AccessibilityElems []*Accessibility `xml:"Accessibility,omitempty"`
177-
}
178-
contentProtectionTags []ContentProtectioner
179-
roles []*Role
180-
segmentBase *SegmentBase
181-
segmentList *SegmentList
182-
segmentTemplate *SegmentTemplate
183-
representations []*Representation
184-
)
185-
186-
// decode inner elements
187-
for {
188-
t, err := d.Token()
189-
if err != nil {
190-
return err
191-
}
192-
193-
switch tt := t.(type) {
194-
case xml.StartElement:
195-
switch tt.Name.Local {
196-
case "ContentProtection":
197-
var (
198-
schemeUri string
199-
cp ContentProtectioner
200-
)
201-
202-
for _, attr := range tt.Attr {
203-
if attr.Name.Local == "schemeIdUri" {
204-
schemeUri = attr.Value
205-
}
206-
}
207-
switch schemeUri {
208-
case CONTENT_PROTECTION_ROOT_SCHEME_ID_URI:
209-
cp = new(CENCContentProtection)
210-
case CONTENT_PROTECTION_PLAYREADY_SCHEME_ID:
211-
cp = new(PlayreadyContentProtection)
212-
case CONTENT_PROTECTION_WIDEVINE_SCHEME_ID:
213-
cp = new(WidevineContentProtection)
214-
default:
215-
cp = new(ContentProtection)
216-
}
217-
218-
err = d.DecodeElement(cp, &tt)
219-
if err != nil {
220-
return err
221-
}
222-
contentProtectionTags = append(contentProtectionTags, cp)
223-
case "Role":
224-
rl := new(Role)
225-
err = d.DecodeElement(rl, &tt)
226-
if err != nil {
227-
return err
228-
}
229-
roles = append(roles, rl)
230-
case "SegmentBase":
231-
sb := new(SegmentBase)
232-
err = d.DecodeElement(sb, &tt)
233-
if err != nil {
234-
return err
235-
}
236-
segmentBase = sb
237-
case "SegmentList":
238-
sl := new(SegmentList)
239-
err = d.DecodeElement(sl, &tt)
240-
if err != nil {
241-
return err
242-
}
243-
segmentList = sl
244-
case "SegmentTemplate":
245-
st := new(SegmentTemplate)
246-
err = d.DecodeElement(st, &tt)
247-
if err != nil {
248-
return err
249-
}
250-
segmentTemplate = st
251-
case "Representation":
252-
rp := new(Representation)
253-
err = d.DecodeElement(rp, &tt)
254-
if err != nil {
255-
return err
256-
}
257-
representations = append(representations, rp)
258-
case "Accessibility":
259-
var a Accessibility
260-
adaptationSet.AccessibilityElems = append(adaptationSet.AccessibilityElems, &a)
261-
if err = d.DecodeElement(&a, &tt); err != nil {
262-
return err
263-
}
264-
case "AudioChannelConfiguration":
265-
var dt DescriptorType
266-
if err = d.DecodeElement(&dt, &tt); err != nil {
267-
return err
268-
}
269-
adaptationSet.AudioChannelConfiguration = append(adaptationSet.AudioChannelConfiguration, dt)
270-
case "SupplementalProperty":
271-
var dt DescriptorType
272-
if err = d.DecodeElement(&dt, &tt); err != nil {
273-
return err
274-
}
275-
adaptationSet.SupplementalProperty = append(adaptationSet.SupplementalProperty, dt)
276-
default:
277-
return fmt.Errorf("unrecognized element in AdaptationSet %q", tt.Name.Local)
278-
}
279-
case xml.EndElement:
280-
if tt == start.End() {
281-
_ = d.DecodeElement(&adaptationSet, &start)
282-
*as = adaptationSet
283-
as.ContentProtection = contentProtectionTags
284-
as.Roles = roles
285-
as.SegmentBase = segmentBase
286-
as.SegmentList = segmentList
287-
as.SegmentTemplate = segmentTemplate
288-
as.Representations = representations
289-
return nil
290-
}
291-
}
292-
192+
var n dtoAdaptationSet
193+
if err := d.DecodeElement(&n, &start); err != nil {
194+
return err
293195
}
196+
*as = AdaptationSet(n.wrappedAdaptationSet)
197+
as.ContentProtection = make([]ContentProtectioner, len(n.ContentProtection))
198+
for i := range n.ContentProtection {
199+
as.ContentProtection[i] = n.ContentProtection[i]
200+
}
201+
return nil
294202
}
295203

296204
// Constants for DRM / ContentProtection

0 commit comments

Comments
 (0)