89d286d1 by David LaPalomento

Grow the internal array if an FLV tag needs more than 16k

Before each write, check that the FLV tag's buffer has enough capacity and grow it if necessary.
1 parent 64f30e95
...@@ -7,7 +7,25 @@ hls.FlvTag = function(type, extraData) { ...@@ -7,7 +7,25 @@ hls.FlvTag = function(type, extraData) {
7 var 7 var
8 // Counter if this is a metadata tag, nal start marker if this is a video 8 // Counter if this is a metadata tag, nal start marker if this is a video
9 // tag. unused if this is an audio tag 9 // tag. unused if this is an audio tag
10 adHoc = 0; // :uint 10 adHoc = 0, // :uint
11
12 // checks whether the FLV tag has enough capacity to accept the proposed
13 // write and re-allocates the internal buffers if necessary
14 prepareWrite = function(flv, count) {
15 var
16 bytes,
17 minLength = flv.position + count;
18 if (minLength < flv.bytes.byteLength) {
19 // there's enough capacity so do nothing
20 return;
21 }
22
23 // allocate a new buffer and copy over the data that will not be modified
24 bytes = new Uint8Array(minLength * 2);
25 bytes.set(flv.bytes.subarray(0, flv.position), 0);
26 flv.bytes = bytes;
27 flv.view = new DataView(flv.bytes.buffer);
28 };
11 29
12 this.keyFrame = false; // :Boolean 30 this.keyFrame = false; // :Boolean
13 31
...@@ -27,7 +45,6 @@ hls.FlvTag = function(type, extraData) { ...@@ -27,7 +45,6 @@ hls.FlvTag = function(type, extraData) {
27 throw("Error Unknown TagType"); 45 throw("Error Unknown TagType");
28 } 46 }
29 47
30 // XXX: I have no idea if 16k is enough to buffer arbitrary FLV tags
31 this.bytes = new Uint8Array(16384); 48 this.bytes = new Uint8Array(16384);
32 this.view = new DataView(this.bytes.buffer); 49 this.view = new DataView(this.bytes.buffer);
33 this.bytes[0] = type; 50 this.bytes[0] = type;
...@@ -41,20 +58,22 @@ hls.FlvTag = function(type, extraData) { ...@@ -41,20 +58,22 @@ hls.FlvTag = function(type, extraData) {
41 58
42 // ByteArray#writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0) 59 // ByteArray#writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0)
43 this.writeBytes = function(bytes, offset, length) { 60 this.writeBytes = function(bytes, offset, length) {
44 offset = offset || 0; 61 var
62 start = offset || 0,
63 end;
45 length = length || bytes.byteLength; 64 length = length || bytes.byteLength;
65 end = start + length;
66
67 prepareWrite(this, length);
68 this.bytes.set(bytes.subarray(start, end), this.position);
46 69
47 try {
48 this.bytes.set(bytes.subarray(offset, offset + length), this.position);
49 } catch(e) {
50 throw e;
51 }
52 this.position += length; 70 this.position += length;
53 this.length = Math.max(this.length, this.position); 71 this.length = Math.max(this.length, this.position);
54 }; 72 };
55 73
56 // ByteArray#writeByte(value:int):void 74 // ByteArray#writeByte(value:int):void
57 this.writeByte = function(byte) { 75 this.writeByte = function(byte) {
76 prepareWrite(this, 1);
58 this.bytes[this.position] = byte; 77 this.bytes[this.position] = byte;
59 this.position++; 78 this.position++;
60 this.length = Math.max(this.length, this.position); 79 this.length = Math.max(this.length, this.position);
...@@ -62,6 +81,7 @@ hls.FlvTag = function(type, extraData) { ...@@ -62,6 +81,7 @@ hls.FlvTag = function(type, extraData) {
62 81
63 // ByteArray#writeShort(value:int):void 82 // ByteArray#writeShort(value:int):void
64 this.writeShort = function(short) { 83 this.writeShort = function(short) {
84 prepareWrite(this, 2);
65 this.view.setUint16(this.position, short); 85 this.view.setUint16(this.position, short);
66 this.position += 2; 86 this.position += 2;
67 this.length = Math.max(this.length, this.position); 87 this.length = Math.max(this.length, this.position);
...@@ -126,13 +146,16 @@ hls.FlvTag = function(type, extraData) { ...@@ -126,13 +146,16 @@ hls.FlvTag = function(type, extraData) {
126 // (key:String, val:Number):void 146 // (key:String, val:Number):void
127 this.writeMetaDataDouble = function(key, val) { 147 this.writeMetaDataDouble = function(key, val) {
128 var i; 148 var i;
149 prepareWrite(this, 2);
129 this.view.setUint16(this.position, key.length); 150 this.view.setUint16(this.position, key.length);
130 this.position += 2; 151 this.position += 2;
131 for (i in key) { 152 for (i in key) {
132 console.assert(key.charCodeAt(i) < 255); 153 console.assert(key.charCodeAt(i) < 255);
154 prepareWrite(this, 1);
133 this.bytes[this.position] = key.charCodeAt(i); 155 this.bytes[this.position] = key.charCodeAt(i);
134 this.position++; 156 this.position++;
135 } 157 }
158 prepareWrite(this, 9);
136 this.view.setUint8(this.position, 0x00); 159 this.view.setUint8(this.position, 0x00);
137 this.position++; 160 this.position++;
138 this.view.setFloat64(this.position, val); 161 this.view.setFloat64(this.position, val);
...@@ -144,13 +167,16 @@ hls.FlvTag = function(type, extraData) { ...@@ -144,13 +167,16 @@ hls.FlvTag = function(type, extraData) {
144 // (key:String, val:Boolean):void 167 // (key:String, val:Boolean):void
145 this.writeMetaDataBoolean = function(key, val) { 168 this.writeMetaDataBoolean = function(key, val) {
146 var i; 169 var i;
170 prepareWrite(this, 2);
147 this.view.setUint16(this.position, key.length); 171 this.view.setUint16(this.position, key.length);
148 this.position += 2; 172 this.position += 2;
149 for (i in key) { 173 for (i in key) {
150 console.assert(key.charCodeAt(i) < 255); 174 console.assert(key.charCodeAt(i) < 255);
175 prepareWrite(this, 1);
151 this.bytes[this.position] = key.charCodeAt(i); 176 this.bytes[this.position] = key.charCodeAt(i);
152 this.position++; 177 this.position++;
153 } 178 }
179 prepareWrite(this, 2);
154 this.view.setUint8(this.position, 0x01); 180 this.view.setUint8(this.position, 0x01);
155 this.position++; 181 this.position++;
156 this.view.setUint8(this.position, val ? 0x01 : 0x00); 182 this.view.setUint8(this.position, val ? 0x01 : 0x00);
......
...@@ -44,4 +44,17 @@ test('writeShort writes a two byte sequence', function() { ...@@ -44,4 +44,17 @@ test('writeShort writes a two byte sequence', function() {
44 'the value is written'); 44 'the value is written');
45 }); 45 });
46 46
47 test('writeBytes grows the internal byte array dynamically', function() {
48 var
49 tag = new FlvTag(FlvTag.VIDEO_TAG),
50 tooManyBytes = new Uint8Array(tag.bytes.byteLength + 1);
51
52 try {
53 tag.writeBytes(tooManyBytes);
54 ok(true, 'the buffer grew to fit the data');
55 } catch(e) {
56 ok(!e, 'the buffer should grow');
57 }
58 });
59
47 })(this); 60 })(this);
......