@@ -24,9 +24,7 @@ import {
24
24
muxed as muxedSegment ,
25
25
mp4Video as mp4VideoSegment ,
26
26
mp4VideoInit as mp4VideoInitSegment ,
27
- videoOneSecond as tsVideoSegment ,
28
- encrypted as encryptedSegment ,
29
- encryptionKey
27
+ videoOneSecond as tsVideoSegment
30
28
} from 'create-test-data!segments' ;
31
29
32
30
/**
@@ -133,7 +131,12 @@ export const LoaderCommonFactory = ({
133
131
loaderBeforeEach,
134
132
usesAsyncAppends = true ,
135
133
initSegments = true ,
136
- testData = muxedSegment
134
+ testData = muxedSegment ,
135
+ // These need to be functions. If you use a value alone, the bytes may be cleared out
136
+ // after decrypting, leaving an empty segment/key. This usage is consistent with other
137
+ // segments used in tests.
138
+ encryptedSegmentFn,
139
+ encryptedSegmentKeyFn
137
140
} ) => {
138
141
let loader ;
139
142
@@ -1503,6 +1506,142 @@ export const LoaderCommonFactory = ({
1503
1506
) ;
1504
1507
} ) ;
1505
1508
1509
+ QUnit . module ( 'Segment Key Caching' ) ;
1510
+
1511
+ QUnit . test ( 'segmentKey will cache new encrypted keys with cacheEncryptionKeys true' , function ( assert ) {
1512
+ loader . cacheEncryptionKeys_ = true ;
1513
+
1514
+ return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1515
+ loader . playlist ( playlistWithDuration ( 10 , { isEncrypted : true } ) ) ;
1516
+ loader . load ( ) ;
1517
+ this . clock . tick ( 1 ) ;
1518
+
1519
+ const keyCache = loader . keyCache_ ;
1520
+ const bytes = new Uint32Array ( [ 1 , 2 , 3 , 4 ] ) ;
1521
+
1522
+ assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1523
+
1524
+ const result = loader . segmentKey ( { resolvedUri : 'key.php' , bytes} ) ;
1525
+
1526
+ assert . deepEqual ( result , { resolvedUri : 'key.php' } , 'gets by default' ) ;
1527
+ loader . segmentKey ( { resolvedUri : 'key.php' , bytes} , true ) ;
1528
+ assert . deepEqual ( keyCache [ 'key.php' ] . bytes , bytes , 'key has been cached' ) ;
1529
+ } ) ;
1530
+ } ) ;
1531
+
1532
+ QUnit . test ( 'segmentKey will not cache encrypted keys with cacheEncryptionKeys false' , function ( assert ) {
1533
+ loader . cacheEncryptionKeys_ = false ;
1534
+
1535
+ return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1536
+ loader . playlist ( playlistWithDuration ( 10 , { isEncrypted : true } ) ) ;
1537
+ loader . load ( ) ;
1538
+ this . clock . tick ( 1 ) ;
1539
+
1540
+ const keyCache = loader . keyCache_ ;
1541
+ const bytes = new Uint32Array ( [ 1 , 2 , 3 , 4 ] ) ;
1542
+
1543
+ assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1544
+ loader . segmentKey ( { resolvedUri : 'key.php' , bytes} , true ) ;
1545
+
1546
+ assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1547
+ } ) ;
1548
+ } ) ;
1549
+
1550
+ QUnit . test ( 'segment requests use cached keys when available' , function ( assert ) {
1551
+ loader . cacheEncryptionKeys_ = true ;
1552
+
1553
+ return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1554
+ return new Promise ( ( resolve , reject ) => {
1555
+ loader . one ( 'appended' , resolve ) ;
1556
+ loader . one ( 'error' , reject ) ;
1557
+ loader . playlist ( playlistWithDuration ( 20 , { isEncrypted : true } ) ) ;
1558
+
1559
+ // make the keys the same
1560
+ loader . playlist_ . segments [ 1 ] . key =
1561
+ videojs . mergeOptions ( { } , loader . playlist_ . segments [ 0 ] . key ) ;
1562
+ // give 2nd key an iv
1563
+ loader . playlist_ . segments [ 1 ] . key . iv = new Uint32Array ( [ 0 , 1 , 2 , 3 ] ) ;
1564
+
1565
+ loader . load ( ) ;
1566
+ this . clock . tick ( 1 ) ;
1567
+
1568
+ assert . strictEqual ( this . requests . length , 2 , 'one request' ) ;
1569
+ assert . strictEqual ( this . requests [ 0 ] . uri , '0-key.php' , 'key request' ) ;
1570
+ assert . strictEqual ( this . requests [ 1 ] . uri , '0.ts' , 'segment request' ) ;
1571
+
1572
+ // key response
1573
+ standardXHRResponse ( this . requests . shift ( ) , encryptedSegmentKeyFn ( ) ) ;
1574
+ this . clock . tick ( 1 ) ;
1575
+
1576
+ // segment
1577
+ standardXHRResponse ( this . requests . shift ( ) , encryptedSegmentFn ( ) ) ;
1578
+ this . clock . tick ( 1 ) ;
1579
+
1580
+ // decryption tick for syncWorker
1581
+ this . clock . tick ( 1 ) ;
1582
+
1583
+ // tick for web worker segment probe
1584
+ this . clock . tick ( 1 ) ;
1585
+ } ) ;
1586
+ } ) . then ( ( ) => {
1587
+ assert . deepEqual ( loader . keyCache_ [ '0-key.php' ] , {
1588
+ resolvedUri : '0-key.php' ,
1589
+ bytes : new Uint32Array ( [ 609867320 , 2355137646 , 2410040447 , 480344904 ] )
1590
+ } , 'previous key was cached' ) ;
1591
+
1592
+ this . clock . tick ( 1 ) ;
1593
+ assert . deepEqual ( loader . pendingSegment_ . segment . key , {
1594
+ resolvedUri : '0-key.php' ,
1595
+ uri : '0-key.php' ,
1596
+ iv : new Uint32Array ( [ 0 , 1 , 2 , 3 ] )
1597
+ } , 'used cached key for request and own initialization vector' ) ;
1598
+
1599
+ assert . strictEqual ( this . requests . length , 1 , 'one request' ) ;
1600
+ assert . strictEqual ( this . requests [ 0 ] . uri , '1.ts' , 'only segment request' ) ;
1601
+ } ) ;
1602
+ } ) ;
1603
+
1604
+ QUnit . test ( 'segment requests make key requests when key isn\'t cached' , function ( assert ) {
1605
+ return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1606
+ return new Promise ( ( resolve , reject ) => {
1607
+ loader . one ( 'appended' , resolve ) ;
1608
+ loader . one ( 'error' , reject ) ;
1609
+ loader . playlist ( playlistWithDuration ( 20 , { isEncrypted : true } ) ) ;
1610
+
1611
+ loader . load ( ) ;
1612
+ this . clock . tick ( 1 ) ;
1613
+
1614
+ assert . strictEqual ( this . requests . length , 2 , 'one request' ) ;
1615
+ assert . strictEqual ( this . requests [ 0 ] . uri , '0-key.php' , 'key request' ) ;
1616
+ assert . strictEqual ( this . requests [ 1 ] . uri , '0.ts' , 'segment request' ) ;
1617
+
1618
+ // key response
1619
+ standardXHRResponse ( this . requests . shift ( ) , encryptedSegmentKeyFn ( ) ) ;
1620
+ this . clock . tick ( 1 ) ;
1621
+
1622
+ // segment
1623
+ standardXHRResponse ( this . requests . shift ( ) , encryptedSegmentFn ( ) ) ;
1624
+ this . clock . tick ( 1 ) ;
1625
+
1626
+ // decryption tick for syncWorker
1627
+ this . clock . tick ( 1 ) ;
1628
+ } ) ;
1629
+ } ) . then ( ( ) => {
1630
+ this . clock . tick ( 1 ) ;
1631
+
1632
+ assert . notOk ( loader . keyCache_ [ '0-key.php' ] , 'not cached' ) ;
1633
+
1634
+ assert . deepEqual ( loader . pendingSegment_ . segment . key , {
1635
+ resolvedUri : '1-key.php' ,
1636
+ uri : '1-key.php'
1637
+ } , 'used cached key for request and own initialization vector' ) ;
1638
+
1639
+ assert . strictEqual ( this . requests . length , 2 , 'two requests' ) ;
1640
+ assert . strictEqual ( this . requests [ 0 ] . uri , '1-key.php' , 'key request' ) ;
1641
+ assert . strictEqual ( this . requests [ 1 ] . uri , '1.ts' , 'segment request' ) ;
1642
+ } ) ;
1643
+ } ) ;
1644
+
1506
1645
QUnit . module ( 'Loading Calculation' ) ;
1507
1646
1508
1647
QUnit . test ( 'requests the first segment with an empty buffer' , function ( assert ) {
@@ -1695,140 +1834,5 @@ export const LoaderCommonFactory = ({
1695
1834
1696
1835
assert . notOk ( loader . playlist_ . syncInfo , 'did not set sync info on new playlist' ) ;
1697
1836
} ) ;
1698
-
1699
- QUnit . test ( 'segmentKey will cache new encrypted keys with cacheEncryptionKeys true' , function ( assert ) {
1700
- loader . cacheEncryptionKeys_ = true ;
1701
-
1702
- return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1703
- loader . playlist ( playlistWithDuration ( 10 , { isEncrypted : true } ) ) ;
1704
- loader . load ( ) ;
1705
- this . clock . tick ( 1 ) ;
1706
-
1707
- const keyCache = loader . keyCache_ ;
1708
- const bytes = new Uint32Array ( [ 1 , 2 , 3 , 4 ] ) ;
1709
-
1710
- assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1711
-
1712
- const result = loader . segmentKey ( { resolvedUri : 'key.php' , bytes} ) ;
1713
-
1714
- assert . deepEqual ( result , { resolvedUri : 'key.php' } , 'gets by default' ) ;
1715
- loader . segmentKey ( { resolvedUri : 'key.php' , bytes} , true ) ;
1716
- assert . deepEqual ( keyCache [ 'key.php' ] . bytes , bytes , 'key has been cached' ) ;
1717
- } ) ;
1718
- } ) ;
1719
-
1720
- QUnit . test ( 'segmentKey will not cache encrypted keys with cacheEncryptionKeys false' , function ( assert ) {
1721
- loader . cacheEncryptionKeys_ = false ;
1722
-
1723
- return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1724
- loader . playlist ( playlistWithDuration ( 10 , { isEncrypted : true } ) ) ;
1725
- loader . load ( ) ;
1726
- this . clock . tick ( 1 ) ;
1727
-
1728
- const keyCache = loader . keyCache_ ;
1729
- const bytes = new Uint32Array ( [ 1 , 2 , 3 , 4 ] ) ;
1730
-
1731
- assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1732
- loader . segmentKey ( { resolvedUri : 'key.php' , bytes} , true ) ;
1733
-
1734
- assert . strictEqual ( Object . keys ( keyCache ) . length , 0 , 'no keys have been cached' ) ;
1735
- } ) ;
1736
- } ) ;
1737
-
1738
- QUnit . test ( 'new segment requests will use cached keys' , function ( assert ) {
1739
- loader . cacheEncryptionKeys_ = true ;
1740
-
1741
- return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1742
- return new Promise ( ( resolve , reject ) => {
1743
- loader . one ( 'appended' , resolve ) ;
1744
- loader . one ( 'error' , reject ) ;
1745
- loader . playlist ( playlistWithDuration ( 20 , { isEncrypted : true } ) ) ;
1746
-
1747
- // make the keys the same
1748
- loader . playlist_ . segments [ 1 ] . key =
1749
- videojs . mergeOptions ( { } , loader . playlist_ . segments [ 0 ] . key ) ;
1750
- // give 2nd key an iv
1751
- loader . playlist_ . segments [ 1 ] . key . iv = new Uint32Array ( [ 0 , 1 , 2 , 3 ] ) ;
1752
-
1753
- loader . load ( ) ;
1754
- this . clock . tick ( 1 ) ;
1755
-
1756
- assert . strictEqual ( this . requests . length , 2 , 'one request' ) ;
1757
- assert . strictEqual ( this . requests [ 0 ] . uri , '0-key.php' , 'key request' ) ;
1758
- assert . strictEqual ( this . requests [ 1 ] . uri , '0.ts' , 'segment request' ) ;
1759
-
1760
- // key response
1761
- standardXHRResponse ( this . requests . shift ( ) , encryptionKey ( ) ) ;
1762
- this . clock . tick ( 1 ) ;
1763
-
1764
- // segment
1765
- standardXHRResponse ( this . requests . shift ( ) , encryptedSegment ( ) ) ;
1766
- this . clock . tick ( 1 ) ;
1767
-
1768
- // decryption tick for syncWorker
1769
- this . clock . tick ( 1 ) ;
1770
-
1771
- // tick for web worker segment probe
1772
- this . clock . tick ( 1 ) ;
1773
- } ) ;
1774
- } ) . then ( ( ) => {
1775
- assert . deepEqual ( loader . keyCache_ [ '0-key.php' ] , {
1776
- resolvedUri : '0-key.php' ,
1777
- bytes : new Uint32Array ( [ 609867320 , 2355137646 , 2410040447 , 480344904 ] )
1778
- } , 'previous key was cached' ) ;
1779
-
1780
- this . clock . tick ( 1 ) ;
1781
- assert . deepEqual ( loader . pendingSegment_ . segment . key , {
1782
- resolvedUri : '0-key.php' ,
1783
- uri : '0-key.php' ,
1784
- iv : new Uint32Array ( [ 0 , 1 , 2 , 3 ] )
1785
- } , 'used cached key for request and own initialization vector' ) ;
1786
-
1787
- assert . strictEqual ( this . requests . length , 1 , 'one request' ) ;
1788
- assert . strictEqual ( this . requests [ 0 ] . uri , '1.ts' , 'only segment request' ) ;
1789
- } ) ;
1790
- } ) ;
1791
-
1792
- QUnit . test ( 'new segment request keys every time' , function ( assert ) {
1793
- return this . setupMediaSource ( loader . mediaSource_ , loader . sourceUpdater_ ) . then ( ( ) => {
1794
- return new Promise ( ( resolve , reject ) => {
1795
- loader . one ( 'appended' , resolve ) ;
1796
- loader . one ( 'error' , reject ) ;
1797
- loader . playlist ( playlistWithDuration ( 20 , { isEncrypted : true } ) ) ;
1798
-
1799
- loader . load ( ) ;
1800
- this . clock . tick ( 1 ) ;
1801
-
1802
- assert . strictEqual ( this . requests . length , 2 , 'one request' ) ;
1803
- assert . strictEqual ( this . requests [ 0 ] . uri , '0-key.php' , 'key request' ) ;
1804
- assert . strictEqual ( this . requests [ 1 ] . uri , '0.ts' , 'segment request' ) ;
1805
-
1806
- // key response
1807
- standardXHRResponse ( this . requests . shift ( ) , encryptionKey ( ) ) ;
1808
- this . clock . tick ( 1 ) ;
1809
-
1810
- // segment
1811
- standardXHRResponse ( this . requests . shift ( ) , encryptedSegment ( ) ) ;
1812
- this . clock . tick ( 1 ) ;
1813
-
1814
- // decryption tick for syncWorker
1815
- this . clock . tick ( 1 ) ;
1816
-
1817
- } ) ;
1818
- } ) . then ( ( ) => {
1819
- this . clock . tick ( 1 ) ;
1820
-
1821
- assert . notOk ( loader . keyCache_ [ '0-key.php' ] , 'not cached' ) ;
1822
-
1823
- assert . deepEqual ( loader . pendingSegment_ . segment . key , {
1824
- resolvedUri : '1-key.php' ,
1825
- uri : '1-key.php'
1826
- } , 'used cached key for request and own initialization vector' ) ;
1827
-
1828
- assert . strictEqual ( this . requests . length , 2 , 'two requests' ) ;
1829
- assert . strictEqual ( this . requests [ 0 ] . uri , '1-key.php' , 'key request' ) ;
1830
- assert . strictEqual ( this . requests [ 1 ] . uri , '1.ts' , 'segment request' ) ;
1831
- } ) ;
1832
- } ) ;
1833
1837
} ) ;
1834
1838
} ;
0 commit comments