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+
129172type AdaptationSet struct {
130173 CommonAttributesAndElements
131174 XMLName xml.Name `xml:"AdaptationSet"`
@@ -151,146 +194,28 @@ type AdaptationSet struct {
151194}
152195
153196func (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