@@ -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