@@ -986,7 +986,6 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
986
986
_hasAlpha = hasAlpha;
987
987
_canvasWidth = canvasWidth;
988
988
_canvasHeight = canvasHeight;
989
- _frameCount = frameCount;
990
989
_loopCount = loopCount;
991
990
992
991
// If static WebP, does not need to parse the frame blend index
@@ -1032,9 +1031,13 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
1032
1031
WebPDemuxReleaseIterator (&iter);
1033
1032
1034
1033
if (frames.count != frameCount) {
1034
+ // frames not match, do not override current value
1035
1035
return NO ;
1036
1036
}
1037
+ _frameCount = frameCount;
1038
+ SD_LOCK (_lock);
1037
1039
_frames = [frames copy ];
1040
+ SD_UNLOCK (_lock);
1038
1041
1039
1042
return YES ;
1040
1043
}
@@ -1052,27 +1055,57 @@ - (NSUInteger)animatedImageFrameCount {
1052
1055
}
1053
1056
1054
1057
- (NSTimeInterval )animatedImageDurationAtIndex : (NSUInteger )index {
1055
- if (index >= _frameCount) {
1056
- return 0 ;
1057
- }
1058
- if (_frameCount <= 1 ) {
1059
- return 0 ;
1058
+ NSTimeInterval duration;
1059
+ // Incremental Animation decoding may update frames when new bytes available
1060
+ // Which should use lock to ensure frame count and frames match, ensure atomic logic
1061
+ if (_idec != NULL ) {
1062
+ SD_LOCK (_lock);
1063
+ if (index >= _frames.count ) {
1064
+ SD_UNLOCK (_lock);
1065
+ return 0 ;
1066
+ }
1067
+ duration = _frames[index].duration ;
1068
+ SD_UNLOCK (_lock);
1069
+ } else {
1070
+ if (index >= _frames.count ) {
1071
+ return 0 ;
1072
+ }
1073
+ duration = _frames[index].duration ;
1060
1074
}
1061
- return _frames[index]. duration ;
1075
+ return duration;
1062
1076
}
1063
1077
1064
1078
- (UIImage *)animatedImageFrameAtIndex : (NSUInteger )index {
1065
1079
UIImage *image;
1066
- if (index >= _frameCount) {
1067
- return nil ;
1068
- }
1069
- SD_LOCK (_lock);
1070
- if (_frameCount <= 1 ) {
1071
- image = [self safeStaticImageFrame ];
1080
+ // Incremental Animation decoding may update frames when new bytes available
1081
+ // Which should use lock to ensure frame count and frames match, ensure atomic logic
1082
+ if (_idec != NULL ) {
1083
+ SD_LOCK (_lock);
1084
+ if (index >= _frames.count ) {
1085
+ SD_UNLOCK (_lock);
1086
+ return nil ;
1087
+ }
1088
+ if (_frames.count <= 1 ) {
1089
+ image = [self safeStaticImageFrame ];
1090
+ } else {
1091
+ image = [self safeAnimatedImageFrameAtIndex: index];
1092
+ }
1093
+ SD_UNLOCK (_lock);
1072
1094
} else {
1073
- image = [self safeAnimatedImageFrameAtIndex: index];
1095
+ // Animation Decoding need a lock on the canvas (which is shared), but the _frames is immutable and no lock needed
1096
+ if (index >= _frames.count ) {
1097
+ return nil ;
1098
+ }
1099
+ if (_frames.count <= 1 ) {
1100
+ SD_LOCK (_lock);
1101
+ image = [self safeStaticImageFrame ];
1102
+ SD_UNLOCK (_lock);
1103
+ } else {
1104
+ SD_LOCK (_lock);
1105
+ image = [self safeAnimatedImageFrameAtIndex: index];
1106
+ SD_UNLOCK (_lock);
1107
+ }
1074
1108
}
1075
- SD_UNLOCK (_lock);
1076
1109
return image;
1077
1110
}
1078
1111
0 commit comments