SDWebImage / SDWebImageAVIFCoder

A SDWebImage coder plugin to support AVIF(AV1 Image File Format) image
MIT License
55 stars 14 forks source link

Potential leak when using AVIFS animated image #53

Closed dreampiggy closed 1 year ago

dreampiggy commented 1 year ago

See more in: https://github.com/AOMediaCodec/libavif/issues/1397

Hi.

Enviornment

I'm deploy libavif (version 0.11.1) with dav1d codeoc (1.1.0) on arm64 M1 Mac

When testing with animated AVIFS to play ainmation, I use the following code (actually, open-sourced, see SDWebImageAVIFCoder)

Demo

    if (_decoder->imageIndex != index) {
        avifResult decodeResult = avifDecoderNthImage(_decoder, (uint32_t)index);
        if (decodeResult != AVIF_RESULT_OK) {
            SD_UNLOCK(_lock);
            return nil;
        }
    }
    width = _decoder->image->width;
    height = _decoder->image->height;
    CGImageRef originImageRef = SDCreateCGImageFromAVIF(_decoder->image);

// Then put this CGImage to NSImageView to display

However, when running Xcode (The IDE in Apple's platform)'s leak detection, I found strange leak here:

image

Full allocation stacktrace

posix_memalign      
dav1d_alloc_aligned /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/mem.h:66   
dav1d_default_picture_alloc /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/picture.c:71   
picture_alloc_with_edges    /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/picture.c:122  
dav1d_thread_picture_alloc  /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/picture.c:182  
dav1d_submit_frame  /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/decode.c:3670  
dav1d_parse_obus    /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/obu.c:1232 
gen_picture /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/lib.c:466  
dav1d_send_data /path/to/SDWebImageAVIFCoder/Example/Pods/libdav1d/dav1d/src/lib.c:496  
dav1dCodecGetNextImage  /path/to/SDWebImageAVIFCoder/Example/Pods/libavif/src/codec_dav1d.c:77  
avifDecoderDecodeTiles  /path/to/SDWebImageAVIFCoder/Example/Pods/libavif/src/read.c:3853   
avifDecoderNextImage    /path/to/SDWebImageAVIFCoder/Example/Pods/libavif/src/read.c:3937   
-[SDImageAVIFCoder animatedImageFrameAtIndex:]  /path/to/SDWebImageAVIFCoder/SDWebImageAVIFCoder/Classes/SDImageAVIFCoder.m:410 
-[SDAnimatedImage animatedImageFrameAtIndex:]   /path/to/SDWebImageAVIFCoder/Example/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImage.m:255  
__67-[SDAnimatedImagePlayer prefetchFrameAtIndex:nextIndex:bufferFull:]_block_invoke    /path/to/SDWebImageAVIFCoder/Example/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImagePlayer.m:363    
__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__      
-[NSBlockOperation main]        
__NSOPERATION_IS_INVOKING_MAIN__        
-[NSOperation start]        
__NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__       
__NSOQSchedule_f        
_dispatch_block_async_invoke2       
_dispatch_client_callout        
_dispatch_continuation_pop      
_dispatch_async_redirect_invoke     
_dispatch_root_queue_drain      
_dispatch_worker_thread2        
_pthread_wqthread       
start_wqthread      

It shows that dav1d plugin (from dav1dCodecGetNextImage), call dav1d_send_data and will leak the internal Dav1dMemPoolBuffer for each frame.

Extra

Firstly I just try to switch back to aom codec and use the exact same code above without any modification, then Xcode report no leak at all.

However, I'm not familiar with dav1d's source code. Is this issue inside the libavif or dav1d ?

Attachment

Note: The full report can be downloaded here and opened in Xcode.

Untitled.trace.zip

dreampiggy commented 1 year ago

Close for now, see libavif's issue comment. Seems the Xcode Instrument Leak Detection bug