5b21807c by David LaPalomento

Add PRIV handling

Create a specialized parser for PRIV frames.
1 parent 2a97d7fd
...@@ -6,13 +6,24 @@ ...@@ -6,13 +6,24 @@
6 (function(window, videojs, undefined) { 6 (function(window, videojs, undefined) {
7 'use strict'; 7 'use strict';
8 var 8 var
9 parseString = function(bytes, start, end) { 9 // return the string representation of the specified byte range,
10 // interpreted as UTf-8.
11 parseUtf8 = function(bytes, start, end) {
10 var i, result = ''; 12 var i, result = '';
11 for (i = start; i < end; i++) { 13 for (i = start; i < end; i++) {
12 result += '%' + ('00' + bytes[i].toString(16)).slice(-2); 14 result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
13 } 15 }
14 return window.decodeURIComponent(result); 16 return window.decodeURIComponent(result);
15 }, 17 },
18 // return the string representation of the specified byte range,
19 // interpreted as ISO-8859-1.
20 parseIso88591 = function(bytes, start, end) {
21 var i, result = '';
22 for (i = start; i < end; i++) {
23 result += '%' + ('00' + bytes[i].toString(16)).slice(-2);
24 }
25 return window.unescape(result);
26 },
16 tagParsers = { 27 tagParsers = {
17 'TXXX': function(tag) { 28 'TXXX': function(tag) {
18 var i; 29 var i;
...@@ -24,8 +35,8 @@ ...@@ -24,8 +35,8 @@
24 for (i = 1; i < tag.data.length; i++) { 35 for (i = 1; i < tag.data.length; i++) {
25 if (tag.data[i] === 0) { 36 if (tag.data[i] === 0) {
26 // parse the text fields 37 // parse the text fields
27 tag.description = parseString(tag.data, 1, i); 38 tag.description = parseUtf8(tag.data, 1, i);
28 tag.value = parseString(tag.data, i + 1, tag.data.length); 39 tag.value = parseUtf8(tag.data, i + 1, tag.data.length);
29 break; 40 break;
30 } 41 }
31 } 42 }
...@@ -40,11 +51,23 @@ ...@@ -40,11 +51,23 @@
40 for (i = 1; i < tag.data.length; i++) { 51 for (i = 1; i < tag.data.length; i++) {
41 if (tag.data[i] === 0) { 52 if (tag.data[i] === 0) {
42 // parse the description and URL fields 53 // parse the description and URL fields
43 tag.description = parseString(tag.data, 1, i); 54 tag.description = parseUtf8(tag.data, 1, i);
44 tag.url = parseString(tag.data, i + 1, tag.data.length); 55 tag.url = parseUtf8(tag.data, i + 1, tag.data.length);
56 break;
57 }
58 }
59 },
60 'PRIV': function(tag) {
61 var i;
62
63 for (i = 0; i < tag.data.length; i++) {
64 if (tag.data[i] === 0) {
65 // parse the description and URL fields
66 tag.owner = parseIso88591(tag.data, 0, i);
45 break; 67 break;
46 } 68 }
47 } 69 }
70 tag.privateData = tag.data.subarray(i + 1);
48 } 71 }
49 }, 72 },
50 MetadataStream; 73 MetadataStream;
......
...@@ -227,6 +227,7 @@ ...@@ -227,6 +227,7 @@
227 227
228 equal(events.length, 1, 'parsed one tag'); 228 equal(events.length, 1, 'parsed one tag');
229 equal(events[0].frames.length, 1, 'parsed one frame'); 229 equal(events[0].frames.length, 1, 'parsed one frame');
230 equal(events[0].frames[0].id, 'TXXX', 'parsed the frame id');
230 equal(events[0].frames[0].description, 'get done', 'parsed the description'); 231 equal(events[0].frames[0].description, 'get done', 'parsed the description');
231 equal(events[0].frames[0].value, '{ "key": "value" }', 'parsed the value'); 232 equal(events[0].frames[0].value, '{ "key": "value" }', 'parsed the value');
232 }); 233 });
...@@ -252,6 +253,7 @@ ...@@ -252,6 +253,7 @@
252 253
253 equal(events.length, 1, 'parsed one tag'); 254 equal(events.length, 1, 'parsed one tag');
254 equal(events[0].frames.length, 1, 'parsed one frame'); 255 equal(events[0].frames.length, 1, 'parsed one frame');
256 equal(events[0].frames[0].id, 'WXXX', 'parsed the frame id');
255 equal(events[0].frames[0].description, '', 'parsed the description'); 257 equal(events[0].frames[0].description, '', 'parsed the description');
256 equal(events[0].frames[0].url, url, 'parsed the value'); 258 equal(events[0].frames[0].url, url, 'parsed the value');
257 }); 259 });
...@@ -280,6 +282,37 @@ ...@@ -280,6 +282,37 @@
280 'parsed the single-digit character'); 282 'parsed the single-digit character');
281 }); 283 });
282 284
285 test('parses PRIV tags', function() {
286 var
287 events = [],
288 payload = stringToInts('arbitrary data may be included in the payload ' +
289 'of a PRIV frame');
290
291 metadataStream.on('data', function(event) {
292 events.push(event);
293 });
294
295 metadataStream.push({
296 trackId: 7,
297 pts: 1000,
298 dts: 900,
299
300 // header
301 data: new Uint8Array(id3Tag(id3Frame('PRIV',
302 stringToCString('priv-owner@example.com'),
303 payload)))
304 });
305
306 equal(events.length, 1, 'parsed a tag');
307 equal(events[0].frames.length, 1, 'parsed a frame');
308 equal(events[0].frames[0].id, 'PRIV', 'frame id is PRIV');
309 equal(events[0].frames[0].owner, 'priv-owner@example.com', 'parsed the owner');
310 deepEqual(events[0].frames[0].privateData,
311 new Uint8Array(payload),
312 'parsed the frame private data');
313
314 });
315
283 // https://html.spec.whatwg.org/multipage/embedded-content.html#steps-to-expose-a-media-resource-specific-text-track 316 // https://html.spec.whatwg.org/multipage/embedded-content.html#steps-to-expose-a-media-resource-specific-text-track
284 test('constructs the dispatch type', function() { 317 test('constructs the dispatch type', function() {
285 metadataStream = new videojs.Hls.MetadataStream({ 318 metadataStream = new videojs.Hls.MetadataStream({
......