From fe0e42afc25d66efeb0ceaefbec089b99f93cf90 Mon Sep 17 00:00:00 2001 From: zxiou Date: Thu, 21 Nov 2019 19:17:44 +0800 Subject: [PATCH] fix the core render of SDAnimatedImagePlayer and fix assignment animationRepeatCount does not work Signed-off-by: zxiou --- .DS_Store | Bin 0 -> 6148 bytes Examples/.DS_Store | Bin 0 -> 6148 bytes .../SDWebImage Demo/DetailViewController.m | 2 + .../SDWebImage Demo/MasterViewController.m | 1 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ SDWebImage/.DS_Store | Bin 0 -> 6148 bytes SDWebImage/Core/SDAnimatedImagePlayer.m | 118 ++++++++++-------- SDWebImage/Core/SDAnimatedImageView.m | 13 ++ 8 files changed, 90 insertions(+), 52 deletions(-) create mode 100644 .DS_Store create mode 100644 Examples/.DS_Store create mode 100644 SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SDWebImage/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2d16dfcc10fe0dc9f4cb84573ae26c03191498de GIT binary patch literal 6148 zcmeHKL2uJA6n^dsq(g`vCfLyzPODI>!nz$Mg%S?CAu?^!0By+{(reAtH(crbu)ZnhaP3K#`$ngXa`9OXs3{gc(! z>bGv+u^RZhXT5cYqI3(d80UR2dreO-y<+HV|3HZNx9|CfQCOZdH=c{6@S-HlBsmH~ zobu)##W)FaxsIy>l&5jh+?-6dySpv^w7WBH@ky`OZt*AG?dh~(J$%&J+dmzB z`aJnE{d%s{W%x3Zc3TX~D&fIj>MpU~4BkVIwR@;TI8!_H zj+f=nkydMF*xYA53Rv`i8<}c3hv!>A-A-rZ);01!fgk zQ;$tL|6lz1{y$4HPeuWwz<;Fxt2?gK$CC8fI#(Q>wH(_iHZq!5DU=lK^l>a5I*K>3 bNy8W?2hrA8DZ~*p^C2K*Fr86gr3(B460Dw@ literal 0 HcmV?d00001 diff --git a/Examples/.DS_Store b/Examples/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fa4d26ea88797260ea849d0f24dece6255454310 GIT binary patch literal 6148 zcmeHKyG{c^3>-s>NED=`++W}iR?$&VUqK6qC=DbM5~;7^yZAK54R+`PKil})$n0;v()XH#$nA@s@^(#Iq$WNeoyzB54s!I oL1Bn?OpJESjkn{gD9XC#Yd-IVQ)1AW4?0ml1Fnlq3jDPKpS%Yac>n+a literal 0 HcmV?d00001 diff --git a/Examples/SDWebImage Demo/DetailViewController.m b/Examples/SDWebImage Demo/DetailViewController.m index 4327c9dd..ee9be9df 100644 --- a/Examples/SDWebImage Demo/DetailViewController.m +++ b/Examples/SDWebImage Demo/DetailViewController.m @@ -24,6 +24,8 @@ [self.imageView sd_setImageWithURL:self.imageURL placeholderImage:nil options:SDWebImageProgressiveLoad]; + self.imageView.shouldCustomLoopCount = YES; + self.imageView.animationRepeatCount = NSIntegerMax; } - (void)viewDidLoad { diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index 14aea5ca..bb86ba17 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -63,6 +63,7 @@ [SDWebImageDownloader sharedDownloader].config.executionOrder = SDWebImageDownloaderLIFOExecutionOrder; self.objects = [NSMutableArray arrayWithObjects: + @"https://s2.ax1x.com/2019/11/01/KHYIgJ.gif", @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth @"http://assets.sbnation.com/assets/2512203/dogflops.gif", @"https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif", diff --git a/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SDWebImage/.DS_Store b/SDWebImage/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..516153fe4952f37097299528382f83d7f653aab6 GIT binary patch literal 6148 zcmeHK!AiqG5Z!H~CWzRBV2`!GD;y$GSL2X8_|4=Qa!f(^uMNm7f}N`6EC$S?4B zoY~zLOBFnc*qJcsotMhS+WLlR!Lw!FxC1eEb1xrdZ7;pT z-kFyVd~Kf#5zlSUzlg$dud>q-N$y2Sn9AfR2qEP9GD-q5Zi`V8WO5!?4d6OfuTq^% zng`9Ay?<1n*6c~ERR_CyIGtMN?q1{gw14;TIC+{rzbIBYe1KB6HO}A_jCq0gZkog* zxdq=Weilba3=jjvzzQ*-w?K1qg=(f!i2-8ZXAI!}V1pt$8ViMT>wpG-A9373L;)M` z5{R}&M`NK7MnJeq1yreAUop5!2fwZ39F2uSmCm?a8RpR|bA3bMa&_?AGMsToA+^K+ zF|f!$S#>LT{-1n*|6fd^9x*@+{3`~y(RI6RC`q5KOU2oxg eM{yNY3ixd_03D5mLhyjlkAS3s8e-sA8TbIFeo$oq literal 0 HcmV?d00001 diff --git a/SDWebImage/Core/SDAnimatedImagePlayer.m b/SDWebImage/Core/SDAnimatedImagePlayer.m index 2efd8805..39658b43 100644 --- a/SDWebImage/Core/SDAnimatedImagePlayer.m +++ b/SDWebImage/Core/SDAnimatedImagePlayer.m @@ -23,6 +23,7 @@ @property (nonatomic, strong) NSMutableDictionary *frameBuffer; @property (nonatomic, assign) NSTimeInterval currentTime; @property (nonatomic, assign) BOOL bufferMiss; +@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable; @property (nonatomic, assign) NSUInteger maxBufferCount; @property (nonatomic, strong) NSOperationQueue *fetchQueue; @property (nonatomic, strong) dispatch_semaphore_t lock; @@ -165,6 +166,7 @@ self.currentLoopCount = 0; self.currentTime = 0; self.bufferMiss = NO; + self.needsDisplayWhenImageBecomesAvailable = NO; [self handleFrameChange]; } @@ -217,8 +219,6 @@ if (!self.isPlaying) { return; } - // Calculate refresh duration - NSTimeInterval duration = self.displayLink.duration; NSUInteger totalFrameCount = self.totalFrameCount; if (totalFrameCount <= 1) { @@ -226,8 +226,6 @@ [self stopPlaying]; return; } - NSUInteger currentFrameIndex = self.currentFrameIndex; - NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount; NSTimeInterval playbackRate = self.playbackRate; if (playbackRate <= 0) { @@ -236,7 +234,46 @@ return; } - // Check if we have the frame buffer firstly to improve performance + // Calculate refresh duration + NSTimeInterval duration = self.displayLink.duration; + + NSUInteger currentFrameIndex = self.currentFrameIndex; + NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount; + + // Check if we need to display new frame firstly + BOOL bufferFull = NO; + if (self.needsDisplayWhenImageBecomesAvailable) { + UIImage *currentFrame; + SD_LOCK(self.lock); + currentFrame = self.frameBuffer[@(currentFrameIndex)]; + SD_UNLOCK(self.lock); + + // Update the current frame + if (currentFrame) { + SD_LOCK(self.lock); + // 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; + } + SD_UNLOCK(self.lock); + + // Update the current frame immediately + self.currentFrame = currentFrame; + [self handleFrameChange]; + + self.bufferMiss = NO; + self.needsDisplayWhenImageBecomesAvailable = NO; + } + else { + self.bufferMiss = YES; + } + } + + // Check if we have the frame buffer if (!self.bufferMiss) { // Then check if timestamp is reached self.currentTime += duration; @@ -246,6 +283,10 @@ // Current frame timestamp not reached, return return; } + + // Otherwise, we shoudle be ready to display next frame + self.needsDisplayWhenImageBecomesAvailable = YES; + self.currentFrameIndex = nextFrameIndex; self.currentTime -= currentDuration; NSTimeInterval nextDuration = [self.animatedProvider animatedImageDurationAtIndex:nextFrameIndex]; nextDuration = nextDuration / playbackRate; @@ -253,45 +294,19 @@ // Do not skip frame self.currentTime = nextDuration; } - } - - // Update the current frame - UIImage *currentFrame; - UIImage *fetchFrame; - SD_LOCK(self.lock); - currentFrame = self.frameBuffer[@(currentFrameIndex)]; - fetchFrame = currentFrame ? self.frameBuffer[@(nextFrameIndex)] : nil; - SD_UNLOCK(self.lock); - BOOL bufferFull = NO; - if (currentFrame) { - SD_LOCK(self.lock); - // 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; - } - SD_UNLOCK(self.lock); - self.currentFrame = currentFrame; - [self handleFrameChange]; - self.currentFrameIndex = nextFrameIndex; - self.bufferMiss = NO; - } else { - self.bufferMiss = YES; - } - - // Update the loop count when last frame rendered - if (nextFrameIndex == 0 && !self.bufferMiss) { - // Update the loop count - self.currentLoopCount++; - [self handleLoopChnage]; - // if reached the max loop count, stop animating, 0 means loop indefinitely - NSUInteger maxLoopCount = self.totalLoopCount; - if (maxLoopCount != 0 && (self.currentLoopCount >= maxLoopCount)) { - [self stopPlaying]; - return; + + // Update the loop count when last frame rendered + if (nextFrameIndex == 0) { + // Update the loop count + self.currentLoopCount++; + [self handleLoopChnage]; + + // if reached the max loop count, stop animating, 0 means loop indefinitely + NSUInteger maxLoopCount = self.totalLoopCount; + if (maxLoopCount != 0 && (self.currentLoopCount >= maxLoopCount)) { + [self stopPlaying]; + return; + } } } @@ -301,14 +316,13 @@ } // Check if we should prefetch next frame or current frame - NSUInteger fetchFrameIndex; - if (self.bufferMiss) { - // When buffer miss, means the decode speed is slower than render speed, we fetch current miss frame - fetchFrameIndex = currentFrameIndex; - } else { - // Or, most cases, the decode speed is faster than render speed, we fetch next frame - fetchFrameIndex = nextFrameIndex; - } + // When buffer miss, means the decode speed is slower than render speed, we fetch current miss frame + // Or, most cases, the decode speed is faster than render speed, we fetch next frame + NSUInteger fetchFrameIndex = self.bufferMiss? currentFrameIndex : nextFrameIndex; + UIImage *fetchFrame; + SD_LOCK(self.lock); + fetchFrame = self.bufferMiss? nil : self.frameBuffer[@(nextFrameIndex)]; + SD_UNLOCK(self.lock); if (!fetchFrame && !bufferFull && self.fetchQueue.operationCount == 0) { // Prefetch next frame in background queue diff --git a/SDWebImage/Core/SDAnimatedImageView.m b/SDWebImage/Core/SDAnimatedImageView.m index 181f2db9..78f1cb8b 100644 --- a/SDWebImage/Core/SDAnimatedImageView.m +++ b/SDWebImage/Core/SDAnimatedImageView.m @@ -306,6 +306,19 @@ #pragma mark - UIImageView Method Overrides #pragma mark Image Data +- (void)setAnimationRepeatCount:(NSInteger)animationRepeatCount +{ +#if SD_UIKIT + [super setAnimationRepeatCount:animationRepeatCount]; +#else + _animationRepeatCount = animationRepeatCount; +#endif + + if (self.shouldCustomLoopCount) { + self.player.totalLoopCount = animationRepeatCount; + } +} + - (void)startAnimating { if (self.player) {