Nick Jennings
Nick Jennings

Reputation: 4044

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.

Upvotes: 7

Views: 5294

Answers (1)

Nick Jennings
Nick Jennings

Reputation: 4044

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.

Upvotes: 15

Related Questions