@@ -132,6 +132,129 @@ type AdaptationSet struct {
132132 Representations []* Representation `xml:"Representation,omitempty"`
133133}
134134
135+ func (as * AdaptationSet ) UnmarshalXML (d * xml.Decoder , start xml.StartElement ) error {
136+
137+ adaptationSet := struct {
138+ CommonAttributesAndElements
139+ XMLName xml.Name `xml:"AdaptationSet"`
140+ ID * string `xml:"id,attr"`
141+ SegmentAlignment * bool `xml:"segmentAlignment,attr"`
142+ Lang * string `xml:"lang,attr"`
143+ Group * string `xml:"group,attr"`
144+ PAR * string `xml:"par,attr"`
145+ MinBandwidth * string `xml:"minBandwidth,attr"`
146+ MaxBandwidth * string `xml:"maxBandwidth,attr"`
147+ MinWidth * string `xml:"minWidth,attr"`
148+ MaxWidth * string `xml:"maxWidth,attr"`
149+ ContentProtection []ContentProtectioner `xml:"ContentProtection,omitempty"` // Common attribute, can be deprecated here
150+ Roles []* Role `xml:"Role,omitempty"`
151+ SegmentBase * SegmentBase `xml:"SegmentBase,omitempty"`
152+ SegmentList * SegmentList `xml:"SegmentList,omitempty"`
153+ SegmentTemplate * SegmentTemplate `xml:"SegmentTemplate,omitempty"` // Live Profile Only
154+ Representations []* Representation `xml:"Representation,omitempty"`
155+ }{}
156+
157+ var (
158+ contentProtectionTags []ContentProtectioner
159+ roles []* Role
160+ segmentBase * SegmentBase
161+ segmentList * SegmentList
162+ segmentTemplate * SegmentTemplate
163+ representations []* Representation
164+ )
165+
166+ // decode inner elements
167+ for {
168+ t , err := d .Token ()
169+ if err != nil {
170+ return err
171+ }
172+
173+ switch tt := t .(type ) {
174+ case xml.StartElement :
175+ switch tt .Name .Local {
176+ case "ContentProtection" :
177+ var (
178+ schemeUri string
179+ cp ContentProtectioner
180+ )
181+
182+ for _ , attr := range tt .Attr {
183+ if attr .Name .Local == "schemeIdUri" {
184+ schemeUri = attr .Value
185+ }
186+ }
187+ switch schemeUri {
188+ case CONTENT_PROTECTION_ROOT_SCHEME_ID_URI :
189+ cp = new (CENCContentProtection )
190+ case CONTENT_PROTECTION_PLAYREADY_SCHEME_ID :
191+ cp = new (PlayreadyContentProtection )
192+ case CONTENT_PROTECTION_WIDEVINE_SCHEME_ID :
193+ cp = new (WidevineContentProtection )
194+ default :
195+ cp = new (ContentProtection )
196+ }
197+
198+ err = d .DecodeElement (cp , & tt )
199+ if err != nil {
200+ return err
201+ }
202+ contentProtectionTags = append (contentProtectionTags , cp )
203+ case "Role" :
204+ rl := new (Role )
205+ err = d .DecodeElement (rl , & tt )
206+ if err != nil {
207+ return err
208+ }
209+ roles = append (roles , rl )
210+ case "SegmentBase" :
211+ sb := new (SegmentBase )
212+ err = d .DecodeElement (sb , & tt )
213+ if err != nil {
214+ return err
215+ }
216+ segmentBase = sb
217+ case "SegmentList" :
218+ sl := new (SegmentList )
219+ err = d .DecodeElement (sl , & tt )
220+ if err != nil {
221+ return err
222+ }
223+ segmentList = sl
224+ case "SegmentTemplate" :
225+ st := new (SegmentTemplate )
226+ err = d .DecodeElement (st , & tt )
227+ if err != nil {
228+ return err
229+ }
230+ segmentTemplate = st
231+ case "Representation" :
232+ rp := new (Representation )
233+ err = d .DecodeElement (rp , & tt )
234+ if err != nil {
235+ return err
236+ }
237+ representations = append (representations , rp )
238+ default :
239+ return errors .New ("Unrecognized element in AdaptationSet" )
240+ }
241+ case xml.EndElement :
242+ if tt == start .End () {
243+ d .DecodeElement (& adaptationSet , & start )
244+ * as = adaptationSet
245+ as .ContentProtection = contentProtectionTags
246+ as .Roles = roles
247+ as .SegmentBase = segmentBase
248+ as .SegmentList = segmentList
249+ as .SegmentTemplate = segmentTemplate
250+ as .Representations = representations
251+ return nil
252+ }
253+ }
254+
255+ }
256+ }
257+
135258// Constants for DRM / ContentProtection
136259const (
137260 CONTENT_PROTECTION_ROOT_SCHEME_ID_URI = "urn:mpeg:dash:mp4protection:2011"
@@ -154,29 +277,118 @@ type ContentProtection struct {
154277 AdaptationSet * AdaptationSet `xml:"-"`
155278 XMLName xml.Name `xml:"ContentProtection"`
156279 SchemeIDURI * string `xml:"schemeIdUri,attr"` // Default: urn:mpeg:dash:mp4protection:2011
157- XMLNS * string `xml:"xmlns: cenc,attr"` // Default: urn:mpeg:cenc:2013
280+ XMLNS * string `xml:"cenc,attr"` // Default: urn:mpeg:cenc:2013
158281}
159282
160283type CENCContentProtection struct {
161284 ContentProtection
162- DefaultKID * string `xml:"cenc: default_KID,attr"`
285+ DefaultKID * string `xml:"default_KID,attr"`
163286 Value * string `xml:"value,attr"` // Default: cenc
164287}
165288
166289type PlayreadyContentProtection struct {
167290 ContentProtection
291+ PlayreadyXMLNS * string `xml:"mspr,attr,omitempty"`
292+ PRO * string `xml:"pro,omitempty"`
293+ PSSH * string `xml:"pssh,omitempty"`
294+ }
295+
296+ type WidevineContentProtection struct {
297+ ContentProtection
298+ PSSH * string `xml:"pssh,omitempty"`
299+ }
300+
301+ type ContentProtectionMarshal struct {
302+ AdaptationSet * AdaptationSet `xml:"-"`
303+ XMLName xml.Name `xml:"ContentProtection"`
304+ SchemeIDURI * string `xml:"schemeIdUri,attr"` // Default: urn:mpeg:dash:mp4protection:2011
305+ XMLNS * string `xml:"xmlns:cenc,attr"` // Default: urn:mpeg:cenc:2013
306+ }
307+
308+ type CENCContentProtectionMarshal struct {
309+ ContentProtectionMarshal
310+ DefaultKID * string `xml:"cenc:default_KID,attr"`
311+ Value * string `xml:"value,attr"` // Default: cenc
312+ }
313+
314+ type PlayreadyContentProtectionMarshal struct {
315+ ContentProtectionMarshal
168316 PlayreadyXMLNS * string `xml:"xmlns:mspr,attr,omitempty"`
169317 PRO * string `xml:"mspr:pro,omitempty"`
170318 PSSH * string `xml:"cenc:pssh,omitempty"`
171319}
172320
173- type WidevineContentProtection struct {
174- ContentProtection
321+ type WidevineContentProtectionMarshal struct {
322+ ContentProtectionMarshal
175323 PSSH * string `xml:"cenc:pssh,omitempty"`
176324}
177325
178326func (s ContentProtection ) ContentProtected () {}
179327
328+ func (s ContentProtection ) MarshalXML (e * xml.Encoder , start xml.StartElement ) error {
329+ err := e .Encode (& ContentProtectionMarshal {
330+ s .AdaptationSet ,
331+ s .XMLName ,
332+ s .SchemeIDURI ,
333+ s .XMLNS ,
334+ })
335+ if err != nil {
336+ return err
337+ }
338+ return nil
339+ }
340+
341+ func (s CENCContentProtection ) MarshalXML (e * xml.Encoder , start xml.StartElement ) error {
342+ err := e .Encode (& CENCContentProtectionMarshal {
343+ ContentProtectionMarshal {
344+ s .AdaptationSet ,
345+ s .XMLName ,
346+ s .SchemeIDURI ,
347+ s .XMLNS ,
348+ },
349+ s .DefaultKID ,
350+ s .Value ,
351+ })
352+ if err != nil {
353+ return err
354+ }
355+ return nil
356+ }
357+
358+ func (s PlayreadyContentProtection ) MarshalXML (e * xml.Encoder , start xml.StartElement ) error {
359+ err := e .Encode (& PlayreadyContentProtectionMarshal {
360+ ContentProtectionMarshal {
361+ s .AdaptationSet ,
362+ s .XMLName ,
363+ s .SchemeIDURI ,
364+ s .XMLNS ,
365+ },
366+ s .PlayreadyXMLNS ,
367+ s .PRO ,
368+ s .PSSH ,
369+ })
370+ if err != nil {
371+ return err
372+ }
373+ return nil
374+ }
375+
376+ func (s WidevineContentProtection ) MarshalXML (e * xml.Encoder , start xml.StartElement ) error {
377+ err := e .Encode (& WidevineContentProtectionMarshal {
378+ ContentProtectionMarshal {
379+ s .AdaptationSet ,
380+ s .XMLName ,
381+ s .SchemeIDURI ,
382+ s .XMLNS ,
383+ },
384+ s .PSSH ,
385+ })
386+ if err != nil {
387+ return err
388+ }
389+ return nil
390+ }
391+
180392type Role struct {
181393 AdaptationSet * AdaptationSet `xml:"-"`
182394 SchemeIDURI * string `xml:"schemeIdUri,attr"`
0 commit comments