@@ -86,7 +86,6 @@ @implementation SDWebPCoderFrame
86
86
@implementation SDImageWebPCoder {
87
87
WebPIDecoder *_idec;
88
88
WebPDemuxer *_demux;
89
- WebPData *_webpdata; // Copied for progressive animation demuxer
90
89
NSData *_imageData;
91
90
CGFloat _scale;
92
91
NSUInteger _loopCount;
@@ -114,10 +113,6 @@ - (void)dealloc {
114
113
WebPDemuxDelete (_demux);
115
114
_demux = NULL ;
116
115
}
117
- if (_webpdata) {
118
- WebPDataClear (_webpdata);
119
- _webpdata = NULL ;
120
- }
121
116
if (_canvas) {
122
117
CGContextRelease (_canvas);
123
118
_canvas = NULL ;
@@ -305,41 +300,36 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
305
300
if (_finished) {
306
301
return ;
307
302
}
308
- _imageData = data;
309
303
_finished = finished;
310
- if (!_demux) {
311
- VP8StatusCode status = WebPIUpdate (_idec, data.bytes , data.length );
312
- if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
304
+ // check whether we can detect Animated WebP or Static WebP, they need different codec (Demuxer or IDecoder)
305
+ if (!_hasAnimation) {
306
+ _imageData = [data copy ];
307
+ VP8StatusCode status = WebPIUpdate (_idec, _imageData.bytes , _imageData.length );
308
+ // For Static WebP, all things done.
309
+ // For Animated WebP (currently use `VP8_STATUS_UNSUPPORTED_FEATURE` to check), continue to create demuxer
310
+ if (status != VP8_STATUS_UNSUPPORTED_FEATURE) {
313
311
return ;
314
312
}
315
- // This case may be Animated WebP progressive decode
316
- if (status == VP8_STATUS_UNSUPPORTED_FEATURE) {
317
- WebPDemuxState state;
318
- WebPData tmpData;
319
- WebPDataInit (&tmpData);
320
- tmpData.bytes = data.bytes ;
321
- tmpData.size = data.length ;
322
- // Copy to avoid the NSData dealloc and VP8 internal retain the pointer
323
- _webpdata = malloc (sizeof (WebPData));
324
- WebPDataCopy (&tmpData, _webpdata);
325
- _demux = WebPDemuxPartial (_webpdata, &state);
326
- }
327
- } else {
328
- // libwebp current have no API to update demuxer, so we always delete and recreate demuxer
313
+ _hasAnimation = YES ;
314
+ }
315
+ // libwebp current have no API to update demuxer, so we always delete and recreate demuxer
316
+ // Use lock to avoid progressive animation decoding thread safe issue
317
+ SD_LOCK (_lock);
318
+ if (_demux) {
319
+ // next line `_imageData = nil` ARC will release the raw buffer, but need release the demuxer firstly because libwebp don't use retain/release rule
329
320
WebPDemuxDelete (_demux);
330
321
_demux = NULL ;
331
- WebPDemuxState state;
332
- WebPData tmpData;
333
- WebPDataInit (&tmpData);
334
- tmpData.bytes = data.bytes ;
335
- tmpData.size = data.length ;
336
- // Copy to avoid the NSData dealloc and VP8 internal retain the pointer
337
- WebPDataClear (_webpdata);
338
- WebPDataCopy (&tmpData, _webpdata);
339
- _demux = WebPDemuxPartial (_webpdata, &state);
340
322
}
323
+ _imageData = [data copy ];
324
+ WebPData webpData;
325
+ WebPDataInit (&webpData);
326
+ webpData.bytes = _imageData.bytes ;
327
+ webpData.size = _imageData.length ;
328
+ WebPDemuxState state;
329
+ _demux = WebPDemuxPartial (&webpData, &state);
330
+ SD_UNLOCK (_lock);
341
331
342
- if (_demux) {
332
+ if (_demux && state != WEBP_DEMUX_PARSE_ERROR ) {
343
333
[self scanAndCheckFramesValidWithDemuxer: _demux];
344
334
}
345
335
}
0 commit comments