mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fixes animated frame timing (#44622)
Summary: Fixes https://github.com/facebook/react-native/issues/44608 . ## Changelog: [IOS] [FIXED] - Fixes animated frame timing Pull Request resolved: https://github.com/facebook/react-native/pull/44622 Test Plan: Example in https://github.com/facebook/react-native/issues/44608 . Reviewed By: sammy-SC Differential Revision: D57559884 Pulled By: cipolleschi fbshipit-source-id: 33eaf71c24eb83715403a67b3471dd1ac2dd9d2f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f500b47a95
commit
690df7a556
@@ -121,6 +121,8 @@ static NSUInteger RCTDeviceFreeMemory(void)
|
||||
// Calculate max buffer size
|
||||
[self calculateMaxBufferCount];
|
||||
|
||||
[self prefetchNextFrame:nil fetchFrameIndex:1];
|
||||
|
||||
if ([self paused]) {
|
||||
[self start];
|
||||
}
|
||||
@@ -167,6 +169,21 @@ static NSUInteger RCTDeviceFreeMemory(void)
|
||||
return _displayLink;
|
||||
}
|
||||
|
||||
- (void)prefetchNextFrame:(UIImage *)fetchFrame fetchFrameIndex:(NSInteger)fetchFrameIndex
|
||||
{
|
||||
if (!fetchFrame && !(self.frameBuffer.count == self.totalFrameCount) && self.fetchQueue.operationCount == 0) {
|
||||
// Prefetch next frame in background queue
|
||||
UIImage<RCTAnimatedImage> *animatedImage = self.animatedImage;
|
||||
NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
|
||||
UIImage *frame = [animatedImage animatedImageFrameAtIndex:fetchFrameIndex];
|
||||
dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
|
||||
self.frameBuffer[@(fetchFrameIndex)] = frame;
|
||||
dispatch_semaphore_signal(self.lock);
|
||||
}];
|
||||
[self.fetchQueue addOperation:operation];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Animation
|
||||
|
||||
- (void)start
|
||||
@@ -210,6 +227,9 @@ static NSUInteger RCTDeviceFreeMemory(void)
|
||||
// Do not skip frame
|
||||
self.currentTime = nextDuration;
|
||||
}
|
||||
currentFrameIndex = nextFrameIndex;
|
||||
self.currentFrameIndex = nextFrameIndex;
|
||||
nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount;
|
||||
}
|
||||
|
||||
// Update the current frame
|
||||
@@ -219,20 +239,14 @@ static NSUInteger RCTDeviceFreeMemory(void)
|
||||
currentFrame = self.frameBuffer[@(currentFrameIndex)];
|
||||
fetchFrame = currentFrame ? self.frameBuffer[@(nextFrameIndex)] : nil;
|
||||
dispatch_semaphore_signal(self.lock);
|
||||
BOOL bufferFull = NO;
|
||||
if (currentFrame) {
|
||||
dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
|
||||
// Remove the frame buffer if need
|
||||
if (self.frameBuffer.count > self.maxBufferCount) {
|
||||
self.frameBuffer[@(currentFrameIndex)] = nil;
|
||||
}
|
||||
// Check whether we can stop fetch
|
||||
if (self.frameBuffer.count == totalFrameCount) {
|
||||
bufferFull = YES;
|
||||
}
|
||||
dispatch_semaphore_signal(self.lock);
|
||||
self.currentFrame = currentFrame;
|
||||
self.currentFrameIndex = nextFrameIndex;
|
||||
self.bufferMiss = NO;
|
||||
[self.layer setNeedsDisplay];
|
||||
} else {
|
||||
@@ -261,17 +275,7 @@ static NSUInteger RCTDeviceFreeMemory(void)
|
||||
fetchFrameIndex = nextFrameIndex;
|
||||
}
|
||||
|
||||
if (!fetchFrame && !bufferFull && self.fetchQueue.operationCount == 0) {
|
||||
// Prefetch next frame in background queue
|
||||
UIImage<RCTAnimatedImage> *animatedImage = self.animatedImage;
|
||||
NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
|
||||
UIImage *frame = [animatedImage animatedImageFrameAtIndex:fetchFrameIndex];
|
||||
dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
|
||||
self.frameBuffer[@(fetchFrameIndex)] = frame;
|
||||
dispatch_semaphore_signal(self.lock);
|
||||
}];
|
||||
[self.fetchQueue addOperation:operation];
|
||||
}
|
||||
[self prefetchNextFrame:fetchFrame fetchFrameIndex:fetchFrameIndex];
|
||||
}
|
||||
|
||||
#pragma mark - CALayerDelegate
|
||||
|
||||
Reference in New Issue
Block a user