Skip to content

Commit abb263c

Browse files
committed
Remove crazy nested Unmarshal
1 parent 42b9329 commit abb263c

File tree

1 file changed

+65
-140
lines changed

1 file changed

+65
-140
lines changed

mpd/mpd.go

Lines changed: 65 additions & 140 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,6 +125,50 @@ 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+
// * slices of pointers
163+
// * Content Protection interface
164+
type dtoAdaptationSet struct {
165+
wrappedAdaptationSet
166+
Roles []Role `xml:"Role,omitempty"`
167+
Representations []Representation `xml:"Representation,omitempty"`
168+
AccessibilityElems []Accessibility `xml:"Accessibility,omitempty"`
169+
ContentProtection contentProtections `xml:"ContentProtection,omitempty"`
170+
}
171+
129172
type AdaptationSet struct {
130173
CommonAttributesAndElements
131174
XMLName xml.Name `xml:"AdaptationSet"`
@@ -151,146 +194,28 @@ type AdaptationSet struct {
151194
}
152195

153196
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-
197+
var n dtoAdaptationSet
198+
if err := d.DecodeElement(&n, &start); err != nil {
199+
return err
293200
}
201+
*as = AdaptationSet(n.wrappedAdaptationSet)
202+
as.Roles = make([]*Role, len(n.Roles))
203+
for i := range n.Roles {
204+
as.Roles[i] = &n.Roles[i]
205+
}
206+
as.Representations = make([]*Representation, len(n.Representations))
207+
for i := range n.Representations {
208+
as.Representations[i] = &n.Representations[i]
209+
}
210+
as.AccessibilityElems = make([]*Accessibility, len(n.AccessibilityElems))
211+
for i := range n.AccessibilityElems {
212+
as.AccessibilityElems[i] = &n.AccessibilityElems[i]
213+
}
214+
as.ContentProtection = make([]ContentProtectioner, len(n.ContentProtection))
215+
for i := range n.ContentProtection {
216+
as.ContentProtection[i] = n.ContentProtection[i]
217+
}
218+
return nil
294219
}
295220

296221
// Constants for DRM / ContentProtection

0 commit comments

Comments
 (0)