@@ -132,6 +132,129 @@ type AdaptationSet struct {
132
132
Representations []* Representation `xml:"Representation,omitempty"`
133
133
}
134
134
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
+
135
258
// Constants for DRM / ContentProtection
136
259
const (
137
260
CONTENT_PROTECTION_ROOT_SCHEME_ID_URI = "urn:mpeg:dash:mp4protection:2011"
@@ -154,29 +277,118 @@ type ContentProtection struct {
154
277
AdaptationSet * AdaptationSet `xml:"-"`
155
278
XMLName xml.Name `xml:"ContentProtection"`
156
279
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
158
281
}
159
282
160
283
type CENCContentProtection struct {
161
284
ContentProtection
162
- DefaultKID * string `xml:"cenc: default_KID,attr"`
285
+ DefaultKID * string `xml:"default_KID,attr"`
163
286
Value * string `xml:"value,attr"` // Default: cenc
164
287
}
165
288
166
289
type PlayreadyContentProtection struct {
167
290
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
168
316
PlayreadyXMLNS * string `xml:"xmlns:mspr,attr,omitempty"`
169
317
PRO * string `xml:"mspr:pro,omitempty"`
170
318
PSSH * string `xml:"cenc:pssh,omitempty"`
171
319
}
172
320
173
- type WidevineContentProtection struct {
174
- ContentProtection
321
+ type WidevineContentProtectionMarshal struct {
322
+ ContentProtectionMarshal
175
323
PSSH * string `xml:"cenc:pssh,omitempty"`
176
324
}
177
325
178
326
func (s ContentProtection ) ContentProtected () {}
179
327
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
+
180
392
type Role struct {
181
393
AdaptationSet * AdaptationSet `xml:"-"`
182
394
SchemeIDURI * string `xml:"schemeIdUri,attr"`
0 commit comments