Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading/writing/copying an ArrayBuffer into another ArrayBuffer with an offset

Let's say I have an ArrayBuffer which is an mp4 file. I'd like to create a new ArrayBuffer with a few extra bytes to be used as header information, and then store the mp4 buffer in the remainder of the new ArrayBuffer.

// ... assume the `data` variable is an existing ArrayBuffer with the contents
// of the mp4 video file.

var ab = new ArrayBuffer(10 + data.byteLength)
var view = new DataView(ab);

view.setInt32(0, 29102); // header information 1
view.setInt32(4, 18282); // header information 2
view.setInt16(8, 576); // header information 3

Now, at this point, I can't figure out how to write the contents of data into the new ab buffer, so that, in the end I have an ArrayBuffer which contains 3 groups of numbers in the beginning, along with the entire contents of the video.

I tried using the following:

view.setInt32(10, data.buffer)

and although I got no errors, the data was not actually written into the buffer. I was unable to write the video to a file and play it:

function readPayload(ab) {
    var view = new DataView(ab);
    console.log(' first header: ' + view.getInt32(0)); // correct
    console.log('second header: ' + view.getInt32(4)); // correct
    console.log(' third header: ' + view.getInt16(8)); // correct
    var data = new Buffer(ab.slice(10));
    console.log('new file size: ' + data.byteLength); // correct length of mp4 file

    var ws = fs.createWriteStream('test.mp4');  // this wrote a corrupt file
    ws.write(data);
    ws.end();
}

In the above function, all of the numbers I retrieve are correct, however when I try to write the payload data to a file, the file is the correct size, but it is corrupt.

    file size: 5253880
  buffer size: 5253890
-- reading data
 first header: 29102
second header: 18282
 third header: 576
new file size: 5253880

So I can't tell whether it's being stored in the new ArrayBuffer incorrectly, or whether I'm extracting the buffer incorrectly - but the test.mp4 that is written does not contain the correct binary data.

like image 661
Nick Jennings Avatar asked Mar 29 '16 12:03

Nick Jennings


1 Answers

After more digging I was finally able to piece together a workable solution. This successfully copies the contents of the mp4 ArrayBuffer into the new ArrayBuffer, from an offset (which has the header information):

new Uint8Array(ab, 0, ab.byteLength).set(new Uint8Array(data), 10);

Here I'm creating a view of type Uint8Array on the ArrayBuffer that also contains the header information (ab). Specifying the same size I used to create that ArrayBuffer.

With that newly created view, I then call the .set function, the first parameter is the original mp4 ArrayBuffer which I also give a Uint8Array view to, and tell the set command to start from offset 10.

This assigns all of the contents of data to ab from an offset of 10.

like image 86
Nick Jennings Avatar answered Sep 17 '22 08:09

Nick Jennings