2828 int64_t cachedTotalFrames = 0 ;
2929 int64_t currentFrame = 0 ;
3030
31- // Internal batch buffer for performance
32- size_t batch_size;
33- std::vector<uint8_t > batch_buffer;
34- size_t batch_count = 0 ;
35- size_t batch_index = 0 ;
31+ std::vector<uint8_t > frame_buffer;
32+ std::vector<uint8_t > prefetch_buffer;
33+ bool has_prefetched_frame = false ;
3634
3735 bool isOpen = false ;
3836 bool debugLogging = false ;
3937
40- Impl (size_t batch_size_param) : batch_size(batch_size_param ) {
38+ Impl () {
4139 if (std::getenv (" VITEO_DEBUG" )) {
4240 debugLogging = true ;
4341 }
44- DEBUG_LOG (" Setting batch size to " << batch_size );
42+ DEBUG_LOG (" Initialized frame extractor " );
4543 }
4644
4745 ~Impl () {
@@ -126,13 +124,15 @@ bool open(const std::string& path) {
126124
127125 cacheMetadata (videoTrack, asset);
128126
129- // Allocate batch buffer
130127 size_t frame_size = cachedWidth * cachedHeight * 4 ;
131- batch_buffer.resize (batch_size * frame_size);
132- DEBUG_LOG (" Allocated batch buffer for " << batch_size << " frames" );
128+ frame_buffer.resize (frame_size);
129+ prefetch_buffer.resize (frame_size);
130+ DEBUG_LOG (" Allocated frame buffers (" << (frame_size * 2 / 1024 / 1024 ) << " MB)" );
133131
134132 isOpen = true ;
135- return setupReader (0 );
133+ if (!setupReader (0 )) return false ;
134+
135+ return prefetchFrame ();
136136 }
137137 }
138138
@@ -208,8 +208,6 @@ bool setupReader(int64_t startFrame) {
208208 }
209209
210210 currentFrame = startFrame;
211- batch_count = 0 ;
212- batch_index = 0 ;
213211 DEBUG_LOG (" Reader initialized successfully" );
214212 return true ;
215213 }
@@ -233,85 +231,64 @@ void copyFrameData(CVImageBufferRef imageBuffer, uint8_t* dst) {
233231 }
234232 }
235233
236- // / Processes single sample buffer and adds to batch
237- bool processSampleBuffer (CMSampleBufferRef sampleBuffer, size_t frame_size) {
238- CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer (sampleBuffer);
239- if (!imageBuffer) return false ;
240-
241- CVPixelBufferLockBaseAddress (imageBuffer, kCVPixelBufferLock_ReadOnly );
242-
243- uint8_t * dst = batch_buffer.data () + (batch_count * frame_size);
244- copyFrameData (imageBuffer, dst);
245-
246- CVPixelBufferUnlockBaseAddress (imageBuffer, kCVPixelBufferLock_ReadOnly );
247- batch_count++;
248- currentFrame++;
249-
250- return true ;
251- }
252-
253- // / Load next batch of frames into internal buffer
254- void loadBatch () {
255- if (!reader || !output || !isOpen) {
256- batch_count = 0 ;
257- return ;
234+ bool prefetchFrame () {
235+ if (!isOpen || !reader || !output) {
236+ return false ;
258237 }
259238
260- size_t frame_size = cachedWidth * cachedHeight * 4 ;
261- batch_count = 0 ;
262-
263239 @autoreleasepool {
264- while (batch_count < batch_size) {
265- if (reader.status != AVAssetReaderStatusReading) {
266- DEBUG_LOG (" Reader stopped, loaded " << batch_count << " frames" );
267- break ;
268- }
269-
270- CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer ];
271- if (!sampleBuffer) {
272- DEBUG_LOG (" No more sample buffers, loaded " << batch_count << " frames" );
273- break ;
274- }
275-
276- processSampleBuffer (sampleBuffer, frame_size);
240+ if (reader.status != AVAssetReaderStatusReading) {
241+ return false ;
242+ }
243+
244+ CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer ];
245+ if (!sampleBuffer) {
246+ return false ;
247+ }
248+
249+ CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer (sampleBuffer);
250+ if (!imageBuffer) {
277251 CFRelease (sampleBuffer);
252+ return false ;
278253 }
279- }
280254
281- batch_index = 0 ;
282- if (batch_count > 0 ) {
283- DEBUG_LOG (" Loaded batch of " << batch_count << " frames" );
255+ CVPixelBufferLockBaseAddress (imageBuffer, kCVPixelBufferLock_ReadOnly );
256+ copyFrameData (imageBuffer, prefetch_buffer.data ());
257+ CVPixelBufferUnlockBaseAddress (imageBuffer, kCVPixelBufferLock_ReadOnly );
258+
259+ CFRelease (sampleBuffer);
260+ has_prefetched_frame = true ;
261+
262+ return true ;
284263 }
285264 }
286265
287- // / Returns pointer to next frame from batch
288266 uint8_t * nextFrame () {
289- if (!isOpen) return nullptr ;
290-
291- if (batch_index >= batch_count) {
292- loadBatch ();
293- if (batch_count == 0 ) {
294- DEBUG_LOG (" No more frames available" );
295- return nullptr ;
296- }
267+ if (!isOpen || !has_prefetched_frame) {
268+ DEBUG_LOG (" Not ready to extract frames" );
269+ return nullptr ;
297270 }
298271
299- size_t frame_size = cachedWidth * cachedHeight * 4 ;
300- uint8_t * frame_ptr = batch_buffer.data () + (batch_index * frame_size);
301- batch_index++;
302- return frame_ptr;
272+ std::swap (frame_buffer, prefetch_buffer);
273+ currentFrame++;
274+
275+ prefetchFrame ();
276+
277+ return frame_buffer.data ();
303278 }
304279
305- // / Resets reader to specified frame index
306280 void reset (int64_t frameIndex) {
307281 if (!isOpen) return ;
308282 DEBUG_LOG (" Resetting to frame " << frameIndex);
309- setupReader (frameIndex);
283+ has_prefetched_frame = false ;
284+ if (setupReader (frameIndex)) {
285+ prefetchFrame ();
286+ }
310287 }
311288};
312289
313290// Public interface implementation
314- FrameExtractor::FrameExtractor (size_t batch_size_param ) : impl(new Impl(batch_size_param )) {}
291+ FrameExtractor::FrameExtractor () : impl(new Impl()) {}
315292FrameExtractor::~FrameExtractor () { delete impl; }
316293
317294bool FrameExtractor::open (const std::string& path) {
0 commit comments