Skip to content

Commit 7c92d7f

Browse files
authored
Merge pull request #179 from atexp/master
Fix bug in videoFrameSource.js when the video frame buffer is too small (fixes #167)
2 parents b27900a + ebd3275 commit 7c92d7f

File tree

1 file changed

+36
-19
lines changed

1 file changed

+36
-19
lines changed

sources/videoFrameSource.js

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ export default async ({ width: canvasWidth, height: canvasHeight, channels, fram
6565

6666
// TODO assert that we have read the correct amount of frames
6767

68-
const buf = Buffer.allocUnsafe(frameByteSize);
68+
let buf = Buffer.allocUnsafe(frameByteSize);
69+
const frameBuffer = Buffer.allocUnsafe(frameByteSize);
6970
let length = 0;
7071
// let inFrameCount = 0;
7172

@@ -109,8 +110,27 @@ export default async ({ width: canvasWidth, height: canvasHeight, channels, fram
109110
ended = true;
110111
});
111112

113+
// returns a frame from the buffer if available
114+
function getNextFrame() {
115+
if (length >= frameByteSize) {
116+
// copy the frame
117+
buf.copy(frameBuffer, 0, 0, frameByteSize);
118+
// move remaining buffer content to the beginning
119+
buf.copy(buf, 0, frameByteSize, length);
120+
length -= frameByteSize;
121+
return frameBuffer;
122+
}
123+
return null;
124+
}
125+
112126
async function readNextFrame(progress, canvas) {
113127
const rgba = await new Promise((resolve, reject) => {
128+
const frame = getNextFrame();
129+
if (frame) {
130+
resolve(frame);
131+
return;
132+
}
133+
114134
if (ended) {
115135
console.log(path, 'Tried to read next video frame after ffmpeg video stream ended');
116136
resolve();
@@ -131,28 +151,25 @@ export default async ({ width: canvasWidth, height: canvasHeight, channels, fram
131151
}
132152

133153
function handleChunk(chunk) {
134-
// console.log('chunk', chunk.length);
135-
const nCopied = length + chunk.length > frameByteSize ? frameByteSize - length : chunk.length;
154+
const nCopied = Math.min(buf.length - length, chunk.length);
136155
chunk.copy(buf, length, 0, nCopied);
137156
length += nCopied;
138-
139-
if (length > frameByteSize) console.error('Video data overflow', length);
140-
141-
if (length >= frameByteSize) {
142-
// console.log('Finished reading frame', inFrameCount, path);
143-
const out = Buffer.from(buf);
144-
145-
const restLength = chunk.length - nCopied;
146-
if (restLength > 0) {
147-
// if (verbose) console.log('Left over data', nCopied, chunk.length, restLength);
148-
chunk.slice(nCopied).copy(buf, 0);
149-
length = restLength;
150-
} else {
151-
length = 0;
157+
const out = getNextFrame();
158+
const restLength = chunk.length - nCopied;
159+
if (restLength > 0) {
160+
if (verbose) console.log('Left over data', nCopied, chunk.length, restLength);
161+
// make sure the buffer can store all chunk data
162+
if (chunk.length > buf.length) {
163+
if (verbose) console.log('resizing buffer', buf.length, chunk.length);
164+
const newBuf = Buffer.allocUnsafe(chunk.length);
165+
buf.copy(newBuf, 0, 0, length);
166+
buf = newBuf;
152167
}
168+
chunk.copy(buf, length, nCopied);
169+
length += restLength;
170+
}
153171

154-
// inFrameCount += 1;
155-
172+
if (out) {
156173
clearTimeout(timeout);
157174
cleanup();
158175
resolve(out);

0 commit comments

Comments
 (0)