toPlaylists.test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. import {
  2. toPlaylists
  3. } from '../src/toPlaylists';
  4. import QUnit from 'qunit';
  5. QUnit.module('toPlaylists');
  6. QUnit.test('no representations', function(assert) {
  7. assert.deepEqual(toPlaylists([]), []);
  8. });
  9. QUnit.test('pretty simple', function(assert) {
  10. const representations = [{
  11. attributes: {
  12. baseUrl: 'http://example.com/',
  13. sourceDuration: 2,
  14. type: 'static',
  15. periodStart: 0
  16. },
  17. segmentInfo: {
  18. template: { }
  19. }
  20. }];
  21. const playlists = [{
  22. attributes: {
  23. baseUrl: 'http://example.com/',
  24. periodStart: 0,
  25. sourceDuration: 2,
  26. duration: 2,
  27. type: 'static'
  28. },
  29. segments: [{
  30. uri: '',
  31. timeline: 0,
  32. duration: 2,
  33. resolvedUri: 'http://example.com/',
  34. map: {
  35. uri: '',
  36. resolvedUri: 'http://example.com/'
  37. },
  38. number: 1,
  39. presentationTime: 0
  40. }]
  41. }];
  42. assert.deepEqual(toPlaylists(representations), playlists);
  43. });
  44. QUnit.test('segment base', function(assert) {
  45. const representations = [{
  46. attributes: {
  47. baseUrl: 'http://example.com/',
  48. periodStart: 0,
  49. sourceDuration: 2,
  50. type: 'static'
  51. },
  52. segmentInfo: {
  53. base: true
  54. }
  55. }];
  56. const playlists = [{
  57. attributes: {
  58. baseUrl: 'http://example.com/',
  59. periodStart: 0,
  60. sourceDuration: 2,
  61. duration: 2,
  62. type: 'static'
  63. },
  64. segments: [{
  65. map: {
  66. resolvedUri: 'http://example.com/',
  67. uri: ''
  68. },
  69. resolvedUri: 'http://example.com/',
  70. uri: 'http://example.com/',
  71. timeline: 0,
  72. duration: 2,
  73. presentationTime: 0,
  74. number: 0
  75. }]
  76. }];
  77. assert.deepEqual(toPlaylists(representations), playlists);
  78. });
  79. QUnit.test('playlist with content steering BaseURLs', function(assert) {
  80. const representations = [
  81. {
  82. attributes: {
  83. bandwidth: 5000000,
  84. baseUrl: 'https://cdn1.example.com/',
  85. clientOffset: 0,
  86. codecs: 'avc1.64001e',
  87. height: 404,
  88. id: 'test',
  89. mimeType: 'video/mp4',
  90. periodStart: 0,
  91. role: {
  92. value: 'main'
  93. },
  94. serviceLocation: 'alpha',
  95. sourceDuration: 0,
  96. type: 'dyanmic',
  97. width: 720
  98. },
  99. segmentInfo: {
  100. template: {}
  101. }
  102. },
  103. {
  104. attributes: {
  105. bandwidth: 5000000,
  106. baseUrl: 'https://cdn2.example.com/',
  107. clientOffset: 0,
  108. codecs: 'avc1.64001e',
  109. height: 404,
  110. id: 'test',
  111. mimeType: 'video/mp4',
  112. periodStart: 0,
  113. role: {
  114. value: 'main'
  115. },
  116. serviceLocation: 'beta',
  117. sourceDuration: 0,
  118. type: 'dyanmic',
  119. width: 720
  120. },
  121. segmentInfo: {
  122. template: {}
  123. }
  124. },
  125. {
  126. attributes: {
  127. bandwidth: 256,
  128. baseUrl: 'https://example.com/en.vtt',
  129. clientOffset: 0,
  130. id: 'en',
  131. lang: 'en',
  132. mimeType: 'text/vtt',
  133. periodStart: 0,
  134. role: {},
  135. sourceDuration: 0,
  136. type: 'dyanmic'
  137. },
  138. segmentInfo: {}
  139. },
  140. {
  141. attributes: {
  142. bandwidth: 256,
  143. baseUrl: 'https://example.com/en.vtt',
  144. clientOffset: 0,
  145. id: 'en',
  146. lang: 'en',
  147. mimeType: 'text/vtt',
  148. periodStart: 0,
  149. role: {},
  150. sourceDuration: 0,
  151. type: 'dyanmic'
  152. },
  153. segmentInfo: {}
  154. }
  155. ];
  156. const playlists = [{
  157. attributes: {
  158. bandwidth: 5000000,
  159. baseUrl: 'https://cdn1.example.com/',
  160. clientOffset: 0,
  161. codecs: 'avc1.64001e',
  162. duration: 0,
  163. height: 404,
  164. id: 'test',
  165. mimeType: 'video/mp4',
  166. periodStart: 0,
  167. role: {
  168. value: 'main'
  169. },
  170. serviceLocation: 'alpha',
  171. sourceDuration: 0,
  172. type: 'dyanmic',
  173. width: 720
  174. },
  175. segments: [
  176. {
  177. duration: 0,
  178. map: {
  179. resolvedUri: 'https://cdn1.example.com/',
  180. uri: ''
  181. },
  182. number: 1,
  183. presentationTime: 0,
  184. resolvedUri: 'https://cdn1.example.com/',
  185. timeline: 0,
  186. uri: ''
  187. }
  188. ]
  189. }, {
  190. attributes: {
  191. bandwidth: 5000000,
  192. baseUrl: 'https://cdn2.example.com/',
  193. clientOffset: 0,
  194. codecs: 'avc1.64001e',
  195. duration: 0,
  196. height: 404,
  197. id: 'test',
  198. mimeType: 'video/mp4',
  199. periodStart: 0,
  200. role: {
  201. value: 'main'
  202. },
  203. serviceLocation: 'beta',
  204. sourceDuration: 0,
  205. type: 'dyanmic',
  206. width: 720
  207. },
  208. segments: [
  209. {
  210. duration: 0,
  211. map: {
  212. resolvedUri: 'https://cdn2.example.com/',
  213. uri: ''
  214. },
  215. number: 1,
  216. presentationTime: 0,
  217. resolvedUri: 'https://cdn2.example.com/',
  218. timeline: 0,
  219. uri: ''
  220. }
  221. ]
  222. }, {
  223. attributes: {
  224. bandwidth: 256,
  225. baseUrl: 'https://example.com/en.vtt',
  226. clientOffset: 0,
  227. id: 'en',
  228. lang: 'en',
  229. mimeType: 'text/vtt',
  230. periodStart: 0,
  231. role: {},
  232. sourceDuration: 0,
  233. type: 'dyanmic'
  234. }
  235. }, {
  236. attributes: {
  237. bandwidth: 256,
  238. baseUrl: 'https://example.com/en.vtt',
  239. clientOffset: 0,
  240. id: 'en',
  241. lang: 'en',
  242. mimeType: 'text/vtt',
  243. periodStart: 0,
  244. role: {},
  245. sourceDuration: 0,
  246. type: 'dyanmic'
  247. }
  248. }];
  249. assert.deepEqual(toPlaylists(representations), playlists);
  250. });
  251. QUnit.test('segment base with sidx', function(assert) {
  252. const representations = [{
  253. attributes: {
  254. baseUrl: 'http://example.com/',
  255. periodStart: 0,
  256. sourceDuration: 2,
  257. indexRange: '10-19',
  258. type: 'static'
  259. },
  260. segmentInfo: {
  261. base: true
  262. }
  263. }];
  264. const playlists = [{
  265. attributes: {
  266. baseUrl: 'http://example.com/',
  267. periodStart: 0,
  268. sourceDuration: 2,
  269. duration: 2,
  270. indexRange: '10-19',
  271. type: 'static'
  272. },
  273. segments: [],
  274. sidx: {
  275. map: {
  276. resolvedUri: 'http://example.com/',
  277. uri: ''
  278. },
  279. resolvedUri: 'http://example.com/',
  280. uri: 'http://example.com/',
  281. byterange: {
  282. offset: 10,
  283. length: 10
  284. },
  285. timeline: 0,
  286. presentationTime: 0,
  287. duration: 2,
  288. number: 0
  289. }
  290. }];
  291. assert.deepEqual(toPlaylists(representations), playlists);
  292. });
  293. QUnit.test('segment list', function(assert) {
  294. const representations = [{
  295. attributes: {
  296. baseUrl: 'http://example.com/',
  297. duration: 10,
  298. sourceDuration: 11,
  299. periodStart: 0,
  300. type: 'static'
  301. },
  302. segmentInfo: {
  303. list: {
  304. segmentUrls: [{
  305. media: '1.fmp4'
  306. }, {
  307. media: '2.fmp4'
  308. }]
  309. }
  310. }
  311. }];
  312. const playlists = [{
  313. attributes: {
  314. baseUrl: 'http://example.com/',
  315. duration: 10,
  316. sourceDuration: 11,
  317. segmentUrls: [{
  318. media: '1.fmp4'
  319. }, {
  320. media: '2.fmp4'
  321. }],
  322. periodStart: 0,
  323. type: 'static'
  324. },
  325. segments: [{
  326. duration: 10,
  327. map: {
  328. resolvedUri: 'http://example.com/',
  329. uri: ''
  330. },
  331. resolvedUri: 'http://example.com/1.fmp4',
  332. timeline: 0,
  333. presentationTime: 0,
  334. uri: '1.fmp4',
  335. number: 1
  336. }, {
  337. duration: 1,
  338. map: {
  339. resolvedUri: 'http://example.com/',
  340. uri: ''
  341. },
  342. resolvedUri: 'http://example.com/2.fmp4',
  343. timeline: 0,
  344. presentationTime: 10,
  345. uri: '2.fmp4',
  346. number: 2
  347. }]
  348. }];
  349. assert.deepEqual(toPlaylists(representations), playlists);
  350. });
  351. QUnit.test('presentationTime accounts for presentationTimeOffset', function(assert) {
  352. const representations = [{
  353. attributes: {
  354. baseUrl: 'http://example.com/',
  355. sourceDuration: 2,
  356. type: 'static',
  357. periodStart: 25
  358. },
  359. segmentInfo: {
  360. template: {
  361. presentationTimeOffset: 100,
  362. timescale: 4
  363. }
  364. }
  365. }];
  366. const playlists = [{
  367. attributes: {
  368. baseUrl: 'http://example.com/',
  369. periodStart: 25,
  370. presentationTimeOffset: 100,
  371. sourceDuration: 2,
  372. duration: 2,
  373. timescale: 4,
  374. type: 'static'
  375. },
  376. segments: [{
  377. uri: '',
  378. timeline: 25,
  379. duration: 2,
  380. // The presentationTime value should be adjusted based on the presentationTimeOffset
  381. // and its timescale.
  382. presentationTime: 0,
  383. resolvedUri: 'http://example.com/',
  384. map: {
  385. uri: '',
  386. resolvedUri: 'http://example.com/'
  387. },
  388. number: 1
  389. }]
  390. }];
  391. assert.deepEqual(toPlaylists(representations), playlists);
  392. });
  393. QUnit.test('playlist with content steering and resolvable BaseURLs', function(assert) {
  394. const representations = [
  395. {
  396. attributes: {
  397. bandwidth: 5000000,
  398. baseUrl: 'https://cdn1.example.com/video',
  399. clientOffset: 0,
  400. codecs: 'avc1.64001e',
  401. height: 404,
  402. id: 'test',
  403. mimeType: 'video/mp4',
  404. periodStart: 0,
  405. role: {
  406. value: 'main'
  407. },
  408. serviceLocation: 'alpha',
  409. sourceDuration: 0,
  410. type: 'dyanmic',
  411. width: 720
  412. },
  413. segmentInfo: {
  414. template: {}
  415. }
  416. },
  417. {
  418. attributes: {
  419. bandwidth: 5000000,
  420. baseUrl: 'https://cdn2.example.com/video',
  421. clientOffset: 0,
  422. codecs: 'avc1.64001e',
  423. height: 404,
  424. id: 'test',
  425. mimeType: 'video/mp4',
  426. periodStart: 0,
  427. role: {
  428. value: 'main'
  429. },
  430. serviceLocation: 'beta',
  431. sourceDuration: 0,
  432. type: 'dyanmic',
  433. width: 720
  434. },
  435. segmentInfo: {
  436. template: {}
  437. }
  438. },
  439. {
  440. attributes: {
  441. bandwidth: 256,
  442. baseUrl: 'https://cdn1.example.com/vtt',
  443. clientOffset: 0,
  444. id: 'en',
  445. lang: 'en',
  446. mimeType: 'text/vtt',
  447. periodStart: 0,
  448. role: {},
  449. serviceLocation: 'alpha',
  450. sourceDuration: 0,
  451. type: 'dyanmic'
  452. },
  453. segmentInfo: {
  454. template: {}
  455. }
  456. },
  457. {
  458. attributes: {
  459. bandwidth: 256,
  460. baseUrl: 'https://cdn2.example.com/vtt',
  461. clientOffset: 0,
  462. id: 'en',
  463. lang: 'en',
  464. mimeType: 'text/vtt',
  465. periodStart: 0,
  466. role: {},
  467. serviceLocation: 'beta',
  468. sourceDuration: 0,
  469. type: 'dyanmic'
  470. },
  471. segmentInfo: {}
  472. }
  473. ];
  474. const playlists = [
  475. {
  476. attributes: {
  477. bandwidth: 5000000,
  478. baseUrl: 'https://cdn1.example.com/video',
  479. clientOffset: 0,
  480. codecs: 'avc1.64001e',
  481. duration: 0,
  482. height: 404,
  483. id: 'test',
  484. mimeType: 'video/mp4',
  485. periodStart: 0,
  486. role: {
  487. value: 'main'
  488. },
  489. serviceLocation: 'alpha',
  490. sourceDuration: 0,
  491. type: 'dyanmic',
  492. width: 720
  493. },
  494. segments: [
  495. {
  496. duration: 0,
  497. map: {
  498. resolvedUri: 'https://cdn1.example.com/video',
  499. uri: ''
  500. },
  501. number: 1,
  502. presentationTime: 0,
  503. resolvedUri: 'https://cdn1.example.com/video',
  504. timeline: 0,
  505. uri: ''
  506. }
  507. ]
  508. },
  509. {
  510. attributes: {
  511. bandwidth: 5000000,
  512. baseUrl: 'https://cdn2.example.com/video',
  513. clientOffset: 0,
  514. codecs: 'avc1.64001e',
  515. duration: 0,
  516. height: 404,
  517. id: 'test',
  518. mimeType: 'video/mp4',
  519. periodStart: 0,
  520. role: {
  521. value: 'main'
  522. },
  523. serviceLocation: 'beta',
  524. sourceDuration: 0,
  525. type: 'dyanmic',
  526. width: 720
  527. },
  528. segments: [
  529. {
  530. duration: 0,
  531. map: {
  532. resolvedUri: 'https://cdn2.example.com/video',
  533. uri: ''
  534. },
  535. number: 1,
  536. presentationTime: 0,
  537. resolvedUri: 'https://cdn2.example.com/video',
  538. timeline: 0,
  539. uri: ''
  540. }
  541. ]
  542. },
  543. {
  544. attributes: {
  545. bandwidth: 256,
  546. baseUrl: 'https://cdn1.example.com/vtt',
  547. clientOffset: 0,
  548. duration: 0,
  549. id: 'en',
  550. lang: 'en',
  551. mimeType: 'text/vtt',
  552. periodStart: 0,
  553. role: {},
  554. serviceLocation: 'alpha',
  555. sourceDuration: 0,
  556. type: 'dyanmic'
  557. },
  558. segments: [
  559. {
  560. duration: 0,
  561. map: {
  562. resolvedUri: 'https://cdn1.example.com/vtt',
  563. uri: ''
  564. },
  565. number: 1,
  566. presentationTime: 0,
  567. resolvedUri: 'https://cdn1.example.com/vtt',
  568. timeline: 0,
  569. uri: ''
  570. }
  571. ]
  572. },
  573. {
  574. attributes: {
  575. bandwidth: 256,
  576. baseUrl: 'https://cdn2.example.com/vtt',
  577. clientOffset: 0,
  578. id: 'en',
  579. lang: 'en',
  580. mimeType: 'text/vtt',
  581. periodStart: 0,
  582. role: {},
  583. serviceLocation: 'beta',
  584. sourceDuration: 0,
  585. type: 'dyanmic'
  586. }
  587. }
  588. ];
  589. assert.deepEqual(toPlaylists(representations), playlists);
  590. });