@@ -10,8 +10,19 @@ use std::io::{Cursor, Read};
10
10
use std:: fs:: File ;
11
11
12
12
static MINI_MP4 : & ' static str = "tests/minimal.mp4" ;
13
- static AUDIO_EME_MP4 : & ' static str = "tests/bipbop-cenc-audioinit.mp4" ;
14
- static VIDEO_EME_MP4 : & ' static str = "tests/bipbop_480wp_1001kbps-cenc-video-key1-init.mp4" ;
13
+ static AUDIO_EME_CENC_MP4 : & ' static str = "tests/bipbop-cenc-audioinit.mp4" ;
14
+ static VIDEO_EME_CENC_MP4 : & ' static str = "tests/bipbop_480wp_1001kbps-cenc-video-key1-init.mp4" ;
15
+ // The cbcs files were created via shaka-packager from Firefox's test suite's bipbop.mp4 using:
16
+ // packager-win.exe
17
+ // in=bipbop.mp4,stream=audio,init_segment=bipbop_cbcs_audio_init.mp4,segment_template=bipbop_cbcs_audio_$Number$.m4s
18
+ // in=bipbop.mp4,stream=video,init_segment=bipbop_cbcs_video_init.mp4,segment_template=bipbop_cbcs_video_$Number$.m4s
19
+ // --protection_scheme cbcs --enable_raw_key_encryption
20
+ // --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421
21
+ // --iv 11223344556677889900112233445566
22
+ // --generate_static_mpd --mpd_output bipbop_cbcs.mpd
23
+ // note: only the init files are needed for these tests
24
+ static AUDIO_EME_CBCS_MP4 : & ' static str = "tests/bipbop_cbcs_audio_init.mp4" ;
25
+ static VIDEO_EME_CBCS_MP4 : & ' static str = "tests/bipbop_cbcs_video_init.mp4" ;
15
26
static VIDEO_AV1_MP4 : & ' static str = "tests/tiny_av1.mp4" ;
16
27
17
28
// Adapted from https://github.com/GuillaumeGomez/audio-video-metadata/blob/9dff40f565af71d5502e03a2e78ae63df95cfd40/src/metadata.rs#L53
@@ -135,7 +146,7 @@ fn public_audio_tenc() {
135
146
vec ! [ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ,
136
147
0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ] ;
137
148
138
- let mut fd = File :: open ( AUDIO_EME_MP4 ) . expect ( "Unknown file" ) ;
149
+ let mut fd = File :: open ( AUDIO_EME_CENC_MP4 ) . expect ( "Unknown file" ) ;
139
150
let mut buf = Vec :: new ( ) ;
140
151
fd. read_to_end ( & mut buf) . expect ( "File error" ) ;
141
152
@@ -189,7 +200,7 @@ fn public_video_cenc() {
189
200
0x7e , 0x57 , 0x1d , 0x03 , 0x7e , 0x57 , 0x1d , 0x11 ,
190
201
0x00 , 0x00 , 0x00 , 0x00 ] ;
191
202
192
- let mut fd = File :: open ( VIDEO_EME_MP4 ) . expect ( "Unknown file" ) ;
203
+ let mut fd = File :: open ( VIDEO_EME_CENC_MP4 ) . expect ( "Unknown file" ) ;
193
204
let mut buf = Vec :: new ( ) ;
194
205
fd. read_to_end ( & mut buf) . expect ( "File error" ) ;
195
206
@@ -233,6 +244,153 @@ fn public_video_cenc() {
233
244
}
234
245
}
235
246
247
+ #[ test]
248
+ fn publicaudio_cbcs ( ) {
249
+ let system_id =
250
+ vec ! [ 0x10 , 0x77 , 0xef , 0xec , 0xc0 , 0xb2 , 0x4d , 0x02 ,
251
+ 0xac , 0xe3 , 0x3c , 0x1e , 0x52 , 0xe2 , 0xfb , 0x4b ] ;
252
+
253
+ let kid =
254
+ vec ! [ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ,
255
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x21 ] ;
256
+
257
+ let default_iv =
258
+ vec ! [ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 ,
259
+ 0x99 , 0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 ] ;
260
+
261
+ let pssh_box =
262
+ vec ! [ 0x00 , 0x00 , 0x00 , 0x34 , 0x70 , 0x73 , 0x73 , 0x68 ,
263
+ 0x01 , 0x00 , 0x00 , 0x00 , 0x10 , 0x77 , 0xef , 0xec ,
264
+ 0xc0 , 0xb2 , 0x4d , 0x02 , 0xac , 0xe3 , 0x3c , 0x1e ,
265
+ 0x52 , 0xe2 , 0xfb , 0x4b , 0x00 , 0x00 , 0x00 , 0x01 ,
266
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ,
267
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x21 ,
268
+ 0x00 , 0x00 , 0x00 , 0x00 ] ;
269
+
270
+ let mut fd = File :: open ( AUDIO_EME_CBCS_MP4 ) . expect ( "Unknown file" ) ;
271
+ let mut buf = Vec :: new ( ) ;
272
+ fd. read_to_end ( & mut buf) . expect ( "File error" ) ;
273
+
274
+ let mut c = Cursor :: new ( & buf) ;
275
+ let mut context = mp4:: MediaContext :: new ( ) ;
276
+ mp4:: read_mp4 ( & mut c, & mut context) . expect ( "read_mp4 failed" ) ;
277
+ for track in context. tracks {
278
+ let stsd = track. stsd . expect ( "expected an stsd" ) ;
279
+ assert_eq ! ( stsd. descriptions. len( ) , 2 ) ;
280
+ let mut found_encrypted_sample_description = false ;
281
+ for description in stsd. descriptions {
282
+ match description {
283
+ mp4:: SampleEntry :: Audio ( ref a) => {
284
+ if let Some ( p) = a. protection_info . iter ( ) . find ( |sinf| sinf. tenc . is_some ( ) ) {
285
+ found_encrypted_sample_description = true ;
286
+ assert_eq ! ( p. code_name, "mp4a" ) ;
287
+ if let Some ( ref tenc) = p. tenc {
288
+ assert ! ( tenc. is_encrypted > 0 ) ;
289
+ assert_eq ! ( tenc. iv_size, 0 ) ;
290
+ assert_eq ! ( tenc. kid, kid) ;
291
+ // Note: 0 for both crypt and skip seems odd but
292
+ // that's what shaka-packager produced. It appears
293
+ // to indicate full encryption.
294
+ assert_eq ! ( tenc. crypt_byte_block_count, Some ( 0 ) ) ;
295
+ assert_eq ! ( tenc. skip_byte_block_count, Some ( 0 ) ) ;
296
+ assert_eq ! ( tenc. constant_iv, Some ( default_iv. clone( ) ) ) ;
297
+ } else {
298
+ assert ! ( false , "Invalid test condition" ) ;
299
+ }
300
+ }
301
+ } ,
302
+ _ => {
303
+ panic ! ( "expected a VideoSampleEntry" ) ;
304
+ } ,
305
+ }
306
+ }
307
+ assert ! ( found_encrypted_sample_description,
308
+ "Should have found an encrypted sample description" ) ;
309
+ }
310
+
311
+ for pssh in context. psshs {
312
+ assert_eq ! ( pssh. system_id, system_id) ;
313
+ for kid_id in pssh. kid {
314
+ assert_eq ! ( kid_id, kid) ;
315
+ }
316
+ assert ! ( pssh. data. is_empty( ) ) ;
317
+ assert_eq ! ( pssh. box_content, pssh_box) ;
318
+ }
319
+ }
320
+
321
+ #[ test]
322
+ fn public_video_cbcs ( ) {
323
+ let system_id =
324
+ vec ! [ 0x10 , 0x77 , 0xef , 0xec , 0xc0 , 0xb2 , 0x4d , 0x02 ,
325
+ 0xac , 0xe3 , 0x3c , 0x1e , 0x52 , 0xe2 , 0xfb , 0x4b ] ;
326
+
327
+ let kid =
328
+ vec ! [ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ,
329
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x21 ] ;
330
+
331
+ let default_iv =
332
+ vec ! [ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 ,
333
+ 0x99 , 0x00 , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 ] ;
334
+
335
+ let pssh_box =
336
+ vec ! [ 0x00 , 0x00 , 0x00 , 0x34 , 0x70 , 0x73 , 0x73 , 0x68 ,
337
+ 0x01 , 0x00 , 0x00 , 0x00 , 0x10 , 0x77 , 0xef , 0xec ,
338
+ 0xc0 , 0xb2 , 0x4d , 0x02 , 0xac , 0xe3 , 0x3c , 0x1e ,
339
+ 0x52 , 0xe2 , 0xfb , 0x4b , 0x00 , 0x00 , 0x00 , 0x01 ,
340
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x04 ,
341
+ 0x7e , 0x57 , 0x1d , 0x04 , 0x7e , 0x57 , 0x1d , 0x21 ,
342
+ 0x00 , 0x00 , 0x00 , 0x00 ] ;
343
+
344
+ let mut fd = File :: open ( VIDEO_EME_CBCS_MP4 ) . expect ( "Unknown file" ) ;
345
+ let mut buf = Vec :: new ( ) ;
346
+ fd. read_to_end ( & mut buf) . expect ( "File error" ) ;
347
+
348
+ let mut c = Cursor :: new ( & buf) ;
349
+ let mut context = mp4:: MediaContext :: new ( ) ;
350
+ mp4:: read_mp4 ( & mut c, & mut context) . expect ( "read_mp4 failed" ) ;
351
+ for track in context. tracks {
352
+ let stsd = track. stsd . expect ( "expected an stsd" ) ;
353
+ assert_eq ! ( stsd. descriptions. len( ) , 2 ) ;
354
+ let mut found_encrypted_sample_description = false ;
355
+ for description in stsd. descriptions {
356
+ match description {
357
+ mp4:: SampleEntry :: Video ( ref v) => {
358
+ assert_eq ! ( v. width, 400 ) ;
359
+ assert_eq ! ( v. height, 300 ) ;
360
+ if let Some ( p) = v. protection_info . iter ( ) . find ( |sinf| sinf. tenc . is_some ( ) ) {
361
+ found_encrypted_sample_description = true ;
362
+ assert_eq ! ( p. code_name, "avc1" ) ;
363
+ if let Some ( ref tenc) = p. tenc {
364
+ assert ! ( tenc. is_encrypted > 0 ) ;
365
+ assert_eq ! ( tenc. iv_size, 0 ) ;
366
+ assert_eq ! ( tenc. kid, kid) ;
367
+ assert_eq ! ( tenc. crypt_byte_block_count, Some ( 1 ) ) ;
368
+ assert_eq ! ( tenc. skip_byte_block_count, Some ( 9 ) ) ;
369
+ assert_eq ! ( tenc. constant_iv, Some ( default_iv. clone( ) ) ) ;
370
+ } else {
371
+ assert ! ( false , "Invalid test condition" ) ;
372
+ }
373
+ }
374
+ } ,
375
+ _ => {
376
+ panic ! ( "expected a VideoSampleEntry" ) ;
377
+ } ,
378
+ }
379
+ }
380
+ assert ! ( found_encrypted_sample_description,
381
+ "Should have found an encrypted sample description" ) ;
382
+ }
383
+
384
+ for pssh in context. psshs {
385
+ assert_eq ! ( pssh. system_id, system_id) ;
386
+ for kid_id in pssh. kid {
387
+ assert_eq ! ( kid_id, kid) ;
388
+ }
389
+ assert ! ( pssh. data. is_empty( ) ) ;
390
+ assert_eq ! ( pssh. box_content, pssh_box) ;
391
+ }
392
+ }
393
+
236
394
#[ test]
237
395
fn public_video_av1 ( ) {
238
396
let mut fd = File :: open ( VIDEO_AV1_MP4 ) . expect ( "Unknown file" ) ;
0 commit comments