Parse out frame payload from ID3 frames
Fix up karma configuration so tests pass from the command line. Attach the bytes of the ID3 frame body in metadata stream events.
Showing
4 changed files
with
38 additions
and
19 deletions
... | @@ -49,13 +49,7 @@ | ... | @@ -49,13 +49,7 @@ |
49 | // http://id3.org/id3v2.3.0#ID3v2_frame_overview | 49 | // http://id3.org/id3v2.3.0#ID3v2_frame_overview |
50 | chunk.frames = []; | 50 | chunk.frames = []; |
51 | do { | 51 | do { |
52 | chunk.frames.push({ | 52 | // determine the number of bytes in this frame |
53 | id: String.fromCharCode(chunk.data[frameStart]) + | ||
54 | String.fromCharCode(chunk.data[frameStart + 1]) + | ||
55 | String.fromCharCode(chunk.data[frameStart + 2]) + | ||
56 | String.fromCharCode(chunk.data[frameStart + 3]) | ||
57 | }); | ||
58 | |||
59 | frameSize = (chunk.data[frameStart + 4] << 24) | | 53 | frameSize = (chunk.data[frameStart + 4] << 24) | |
60 | (chunk.data[frameStart + 5] << 16) | | 54 | (chunk.data[frameStart + 5] << 16) | |
61 | (chunk.data[frameStart + 6] << 8) | | 55 | (chunk.data[frameStart + 6] << 8) | |
... | @@ -63,13 +57,22 @@ | ... | @@ -63,13 +57,22 @@ |
63 | if (frameSize < 1) { | 57 | if (frameSize < 1) { |
64 | return videojs.log('Malformed ID3 frame encountered. Skipping metadata parsing.'); | 58 | return videojs.log('Malformed ID3 frame encountered. Skipping metadata parsing.'); |
65 | } | 59 | } |
60 | |||
61 | chunk.frames.push({ | ||
62 | id: String.fromCharCode(chunk.data[frameStart]) + | ||
63 | String.fromCharCode(chunk.data[frameStart + 1]) + | ||
64 | String.fromCharCode(chunk.data[frameStart + 2]) + | ||
65 | String.fromCharCode(chunk.data[frameStart + 3]), | ||
66 | data: chunk.data.subarray(frameStart + 10, frameStart + frameSize + 10) | ||
67 | }); | ||
68 | |||
66 | frameStart += 10; // advance past the frame header | 69 | frameStart += 10; // advance past the frame header |
67 | frameStart += frameSize; // advance past the frame body | 70 | frameStart += frameSize; // advance past the frame body |
68 | } while (frameStart < tagSize) | 71 | } while (frameStart < tagSize); |
69 | this.trigger('data', chunk); | 72 | this.trigger('data', chunk); |
70 | }; | 73 | }; |
71 | }; | 74 | }; |
72 | MetadataStream.prototype = new videojs.Hls.Stream(); | 75 | MetadataStream.prototype = new videojs.Hls.Stream(); |
73 | 76 | ||
74 | videojs.Hls.MetadataStream = MetadataStream; | 77 | videojs.Hls.MetadataStream = MetadataStream; |
75 | })(window, videojs); | 78 | })(window, window.videojs); | ... | ... |
... | @@ -80,14 +80,15 @@ module.exports = function(config) { | ... | @@ -80,14 +80,15 @@ module.exports = function(config) { |
80 | '../node_modules/pkcs7/dist/pkcs7.unpad.js', | 80 | '../node_modules/pkcs7/dist/pkcs7.unpad.js', |
81 | '../test/karma-qunit-shim.js', | 81 | '../test/karma-qunit-shim.js', |
82 | '../src/videojs-hls.js', | 82 | '../src/videojs-hls.js', |
83 | '../src/xhr.js', | 83 | '../src/stream.js', |
84 | '../src/flv-tag.js', | 84 | '../src/flv-tag.js', |
85 | '../src/exp-golomb.js', | 85 | '../src/exp-golomb.js', |
86 | '../src/h264-stream.js', | 86 | '../src/h264-stream.js', |
87 | '../src/aac-stream.js', | 87 | '../src/aac-stream.js', |
88 | '../src/metadata-stream.js', | ||
88 | '../src/segment-parser.js', | 89 | '../src/segment-parser.js', |
89 | '../src/stream.js', | ||
90 | '../src/m3u8/m3u8-parser.js', | 90 | '../src/m3u8/m3u8-parser.js', |
91 | '../src/xhr.js', | ||
91 | '../src/playlist-loader.js', | 92 | '../src/playlist-loader.js', |
92 | '../src/decrypter.js', | 93 | '../src/decrypter.js', |
93 | '../tmp/manifests.js', | 94 | '../tmp/manifests.js', | ... | ... |
... | @@ -44,14 +44,15 @@ module.exports = function(config) { | ... | @@ -44,14 +44,15 @@ module.exports = function(config) { |
44 | '../node_modules/pkcs7/dist/pkcs7.unpad.js', | 44 | '../node_modules/pkcs7/dist/pkcs7.unpad.js', |
45 | '../test/karma-qunit-shim.js', | 45 | '../test/karma-qunit-shim.js', |
46 | '../src/videojs-hls.js', | 46 | '../src/videojs-hls.js', |
47 | '../src/xhr.js', | 47 | '../src/stream.js', |
48 | '../src/flv-tag.js', | 48 | '../src/flv-tag.js', |
49 | '../src/exp-golomb.js', | 49 | '../src/exp-golomb.js', |
50 | '../src/h264-stream.js', | 50 | '../src/h264-stream.js', |
51 | '../src/aac-stream.js', | 51 | '../src/aac-stream.js', |
52 | '../src/metadata-stream.js', | ||
52 | '../src/segment-parser.js', | 53 | '../src/segment-parser.js', |
53 | '../src/stream.js', | ||
54 | '../src/m3u8/m3u8-parser.js', | 54 | '../src/m3u8/m3u8-parser.js', |
55 | '../src/xhr.js', | ||
55 | '../src/playlist-loader.js', | 56 | '../src/playlist-loader.js', |
56 | '../src/decrypter.js', | 57 | '../src/decrypter.js', |
57 | '../tmp/manifests.js', | 58 | '../tmp/manifests.js', | ... | ... |
... | @@ -66,7 +66,15 @@ | ... | @@ -66,7 +66,15 @@ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | test('parses simple ID3 metadata out of PES packets', function() { | 68 | test('parses simple ID3 metadata out of PES packets', function() { |
69 | var events = [], id3Bytes, size; | 69 | var |
70 | events = [], | ||
71 | wxxxPayload = [ | ||
72 | 0x00 // text encoding. ISO-8859-1 | ||
73 | ].concat(stringToCString('ad tag URL'), // description | ||
74 | stringToInts('http://example.com/ad?v=1234&q=7')), // value | ||
75 | id3Bytes, | ||
76 | size; | ||
77 | |||
70 | metadataStream.on('data', function(event) { | 78 | metadataStream.on('data', function(event) { |
71 | events.push(event); | 79 | events.push(event); |
72 | }); | 80 | }); |
... | @@ -84,9 +92,7 @@ | ... | @@ -84,9 +92,7 @@ |
84 | // frame 0 | 92 | // frame 0 |
85 | // http://id3.org/id3v2.3.0#User_defined_text_information_frame | 93 | // http://id3.org/id3v2.3.0#User_defined_text_information_frame |
86 | ], id3Frame('WXXX', | 94 | ], id3Frame('WXXX', |
87 | [0x00], // text encoding. ISO-8859-1 | 95 | wxxxPayload), // value |
88 | stringToCString('ad tag URL'), // description | ||
89 | stringToInts('http://example.com/ad?v=1234&q=7')), // value | ||
90 | // frame 1 | 96 | // frame 1 |
91 | // custom tag | 97 | // custom tag |
92 | id3Frame('XINF', | 98 | id3Frame('XINF', |
... | @@ -115,11 +121,17 @@ | ... | @@ -115,11 +121,17 @@ |
115 | equal(events.length, 1, 'parsed one tag'); | 121 | equal(events.length, 1, 'parsed one tag'); |
116 | equal(events[0].frames.length, 2, 'parsed two frames'); | 122 | equal(events[0].frames.length, 2, 'parsed two frames'); |
117 | equal(events[0].frames[0].id, 'WXXX', 'parsed a WXXX frame'); | 123 | equal(events[0].frames[0].id, 'WXXX', 'parsed a WXXX frame'); |
124 | deepEqual(new Uint8Array(events[0].frames[0].data), | ||
125 | new Uint8Array(wxxxPayload), | ||
126 | 'attached the frame payload'); | ||
118 | equal(events[0].frames[1].id, 'XINF', 'parsed a user-defined frame'); | 127 | equal(events[0].frames[1].id, 'XINF', 'parsed a user-defined frame'); |
128 | deepEqual(new Uint8Array(events[0].frames[1].data), | ||
129 | new Uint8Array([0x04, 0x03, 0x02, 0x01]), | ||
130 | 'attached the frame payload'); | ||
119 | }); | 131 | }); |
120 | 132 | ||
121 | test('skips non-ID3 metadata events', function() { | 133 | test('skips non-ID3 metadata events', function() { |
122 | var events = [], id3Bytes, size; | 134 | var events = []; |
123 | metadataStream.on('data', function(event) { | 135 | metadataStream.on('data', function(event) { |
124 | events.push(event); | 136 | events.push(event); |
125 | }); | 137 | }); |
... | @@ -143,5 +155,7 @@ | ... | @@ -143,5 +155,7 @@ |
143 | // compressed frames | 155 | // compressed frames |
144 | // encrypted frames | 156 | // encrypted frames |
145 | // frame groups | 157 | // frame groups |
158 | // too large/small tag size values | ||
159 | // too large/small frame size values | ||
146 | 160 | ||
147 | })(window, videojs); | 161 | })(window, window.videojs); | ... | ... |
-
Please register or sign in to post a comment