Skip to content

Commit

Permalink
Add thread safety checks for PAGView and PAGImageView. (#2572)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevingpqi123 authored Nov 7, 2024
1 parent 530f786 commit 832d86c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
58 changes: 42 additions & 16 deletions src/platform/ios/PAGImageView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ @implementation PAGImageView {
PAGDecoder* pagDecoder;
NSInteger duartion;
float renderScaleFactor;
NSInteger width;
NSInteger height;
NSUInteger numFrames;

NSMutableDictionary<NSNumber*, UIImage*>* imagesMap;
std::mutex imageViewLock;
Expand All @@ -97,6 +100,9 @@ - (void)initPAG {
self.memeoryCacheFinished = NO;
self.isVisible = NO;
filePath = nil;
width = 0;
height = 0;
numFrames = 0;
self.backgroundColor = [UIColor clearColor];
animator = [[PAGAnimator alloc] initWithUpdater:(id<PAGAnimatorUpdater>)self];

Expand Down Expand Up @@ -162,6 +168,7 @@ - (void)setCompositionInternal:(PAGComposition*)newComposition maxFrameRate:(flo
duartion = [newComposition duration];

[self reset];
[self updatePAGDecoder];
if (self.isVisible) {
[animator setDuration:duartion];
}
Expand All @@ -171,8 +178,8 @@ - (CVPixelBufferRef)getDiskCacheCVPixelBuffer {
if (diskBufferPool == nil) {
NSDictionary* options = @{
(id)kCVPixelBufferIOSurfacePropertiesKey : @{},
(id)kCVPixelBufferWidthKey : @([[self getPAGDecoder] width]),
(id)kCVPixelBufferHeightKey : @([[self getPAGDecoder] height]),
(id)kCVPixelBufferWidthKey : @(width),
(id)kCVPixelBufferHeightKey : @(height),
(id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)
};
CVReturn status = CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, (CFDictionaryRef)options,
Expand All @@ -194,16 +201,15 @@ - (CVPixelBufferRef)getDiskCacheCVPixelBuffer {

- (CVPixelBufferRef)getMemoryCacheCVPixelBuffer {
CVPixelBufferRef pixelBuffer =
pag::PixelBufferUtil::Make(static_cast<int>([[self getPAGDecoder] width]),
static_cast<int>([[self getPAGDecoder] height]));
pag::PixelBufferUtil::Make(static_cast<int>(width), static_cast<int>(height));
if (pixelBuffer == nil) {
NSLog(@"PAGImageView: CVPixelBufferRef create failed!");
return nil;
}
return pixelBuffer;
}

- (PAGDecoder*)getPAGDecoder {
- (void)updatePAGDecoder {
if (pagDecoder == nil) {
float scaleFactor;
if (self.viewSize.width >= self.viewSize.height) {
Expand All @@ -224,10 +230,12 @@ - (PAGDecoder*)getPAGDecoder {
scale:scaleFactor];
}
if (pagDecoder) {
width = [pagDecoder width];
height = [pagDecoder height];
numFrames = [pagDecoder numFrames];
[pagDecoder retain];
}
}
return pagDecoder;
}

- (void)onAnimationFlush:(double)progress {
Expand Down Expand Up @@ -262,14 +270,17 @@ - (BOOL)updateImageViewFrom:(CVPixelBufferRef)pixelBuffer atIndex:(NSInteger)fra
self.currentUIImage = image;
[self submitToImageView];
}
if ([imagesMap count] == (NSUInteger)[[self getPAGDecoder] numFrames]) {
if ([imagesMap count] == numFrames) {
self.memeoryCacheFinished = YES;
}
return YES;
}
PAGDecoder* decoder = [self getPAGDecoder];
if ([decoder checkFrameChanged:(int)frameIndex]) {
BOOL status = [decoder readFrame:frameIndex to:pixelBuffer];
[self updatePAGDecoder];
if (pagDecoder == nil) {
return false;
}
if ([pagDecoder checkFrameChanged:(int)frameIndex]) {
BOOL status = [pagDecoder readFrame:frameIndex to:pixelBuffer];
if (!status) {
return status;
}
Expand All @@ -294,6 +305,7 @@ - (BOOL)checkPAGCompositionChanged {
if ([PAGContentVersion Get:pagComposition] != self.pagContentVersion) {
self.pagContentVersion = [PAGContentVersion Get:pagComposition];
[self reset];
[self updatePAGDecoder];
if (self.isVisible) {
[animator setDuration:[pagComposition duration]];
}
Expand All @@ -317,8 +329,7 @@ - (void)applicationDidBecomeActive:(NSNotification*)notification {
}

- (void)freeCache {
if (self.memoryCacheEnabled && self->pagDecoder &&
[self->imagesMap count] == (NSUInteger)[self->pagDecoder numFrames]) {
if (self.memoryCacheEnabled && self->pagDecoder && [self->imagesMap count] == numFrames) {
[self->pagDecoder release];
self->pagDecoder = nil;
}
Expand All @@ -339,6 +350,9 @@ - (void)reset {
[pagDecoder release];
pagDecoder = nil;
}
width = 0;
height = 0;
numFrames = 0;
}

- (UIImage*)imageForCVPixelBuffer:(CVPixelBufferRef)pixelBuffer {
Expand Down Expand Up @@ -370,6 +384,7 @@ - (void)setBounds:(CGRect)bounds {
std::lock_guard<std::mutex> autoLock(imageViewLock);
if (pagComposition || filePath) {
[self reset];
[self updatePAGDecoder];
if (oldBounds.size.width == 0 || oldBounds.size.height == 0) {
[animator update];
}
Expand All @@ -385,6 +400,7 @@ - (void)setFrame:(CGRect)frame {
std::lock_guard<std::mutex> autoLock(imageViewLock);
if (pagComposition || filePath) {
[self reset];
[self updatePAGDecoder];
if (oldRect.size.width == 0 || oldRect.size.height == 0) {
[animator update];
}
Expand All @@ -400,6 +416,7 @@ - (void)setRenderScale:(float)scale {
renderScaleFactor = scale;
if (pagComposition || filePath) {
[self reset];
[self updatePAGDecoder];
}
}

Expand All @@ -415,6 +432,7 @@ - (void)setContentScaleFactor:(CGFloat)scaleFactor {
if (pagComposition || filePath) {
std::lock_guard<std::mutex> autoLock(imageViewLock);
[self reset];
[self updatePAGDecoder];
self.viewSize = CGSizeMake(self.frame.size.width, self.frame.size.height);
}
}
Expand Down Expand Up @@ -457,7 +475,7 @@ - (void)pause {

- (NSUInteger)numFrames {
std::lock_guard<std::mutex> autoLock(imageViewLock);
return [[self getPAGDecoder] numFrames];
return numFrames;
}

- (UIImage*)currentImage {
Expand Down Expand Up @@ -486,6 +504,7 @@ - (void)setRepeatCount:(int)repeatCount {
}

- (NSString*)getPath {
std::lock_guard<std::mutex> autoLock(imageViewLock);
return filePath == nil ? nil : [[filePath retain] autorelease];
}

Expand Down Expand Up @@ -516,6 +535,7 @@ - (void)setPathAsync:(NSString*)path completionBlock:(void (^)(PAGFile*))callbac
- (void)setPathAsync:(NSString*)path
maxFrameRate:(float)maxFrameRate
completionBlock:(void (^)(PAGFile*))callback {
std::lock_guard<std::mutex> autoLock(imageViewLock);
if (filePath != nil) {
[filePath release];
filePath = nil;
Expand All @@ -533,6 +553,7 @@ - (void)setPathAsync:(NSString*)path
}

- (PAGComposition*)getComposition {
std::lock_guard<std::mutex> autoLock(imageViewLock);
if (filePath) {
return nil;
}
Expand All @@ -554,16 +575,21 @@ - (void)setComposition:(PAGComposition*)newComposition maxFrameRate:(float)maxFr

- (void)setCurrentFrame:(NSUInteger)currentFrame {
std::lock_guard<std::mutex> autoLock(imageViewLock);
[animator setProgress:pag::FrameToProgress(currentFrame, [[self getPAGDecoder] numFrames])];
[animator setProgress:pag::FrameToProgress(currentFrame, numFrames)];
}

- (NSUInteger)currentFrame {
return pag::ProgressToFrame([animator progress], [[self getPAGDecoder] numFrames]);
std::lock_guard<std::mutex> autoLock(imageViewLock);
return [self currentFrameInternal];
}

- (NSUInteger)currentFrameInternal {
return pag::ProgressToFrame([animator progress], numFrames);
}

- (BOOL)flush {
std::lock_guard<std::mutex> autoLock(imageViewLock);
NSInteger frameIndex = [self currentFrame];
NSInteger frameIndex = [self currentFrameInternal];
if (self.memeoryCacheFinished) {
if ([self checkPAGCompositionChanged] == NO) {
if (self.currentFrameIndex != frameIndex) {
Expand Down
5 changes: 5 additions & 0 deletions src/platform/ios/PAGView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ @implementation PAGView {
NSString* filePath;
PAGAnimator* animator;
BOOL _isVisible;
std::mutex lock;
}

- (instancetype)initWithFrame:(CGRect)frame {
Expand Down Expand Up @@ -192,10 +193,12 @@ - (void)stop {
}

- (NSString*)getPath {
std::lock_guard<std::mutex> autoLock(lock);
return filePath == nil ? nil : [[filePath retain] autorelease];
}

- (BOOL)setPath:(NSString*)path {
std::lock_guard<std::mutex> autoLock(lock);
if (filePath != nil) {
[filePath release];
filePath = nil;
Expand All @@ -207,6 +210,7 @@ - (BOOL)setPath:(NSString*)path {
}

- (void)setPathAsync:(NSString*)path completionBlock:(void (^)(PAGFile*))callback {
std::lock_guard<std::mutex> autoLock(lock);
if (filePath != nil) {
[filePath release];
filePath = nil;
Expand All @@ -226,6 +230,7 @@ - (PAGComposition*)getComposition {
}

- (void)setComposition:(PAGComposition*)newComposition {
std::lock_guard<std::mutex> autoLock(lock);
if (filePath != nil) {
[filePath release];
filePath = nil;
Expand Down

0 comments on commit 832d86c

Please sign in to comment.