AVFoundation: fix memory leak

Using 'self' in a block maintains a strong reference to it, the previous
code would never release that reference and therefore leak the
AVFMediaPlayerSessionObserver object when the session was deleted.
Captured variables used in the relevant block are now marked with
'__block' to make sure no strong references are maintained.
We now also make sure the session still exist when that callback block
is called.

Change-Id: I847b524d8692559fe5884517abb5b9cc7696b4fd
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
This commit is contained in:
Yoann Lopes
2016-08-17 14:03:49 +02:00
parent a52aa624e6
commit 69296d229e

View File

@@ -35,6 +35,8 @@
#include "avfmediaplayerservice.h" #include "avfmediaplayerservice.h"
#include "avfvideooutput.h" #include "avfvideooutput.h"
#include <qpointer.h>
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
QT_USE_NAMESPACE QT_USE_NAMESPACE
@@ -105,15 +107,23 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
//Create an asset for inspection of a resource referenced by a given URL. //Create an asset for inspection of a resource referenced by a given URL.
//Load the values for the asset keys "tracks", "playable". //Load the values for the asset keys "tracks", "playable".
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:m_URL options:nil]; // use __block to avoid maintaining strong references on variables captured by the
NSArray *requestedKeys = [NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil]; // following block callback
__block AVURLAsset *asset = [[AVURLAsset URLAssetWithURL:m_URL options:nil] retain];
__block NSArray *requestedKeys = [[NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil] retain];
__block AVFMediaPlayerSessionObserver *blockSelf = self;
QPointer<AVFMediaPlayerSession> session(m_session);
// Tells the asset to load the values of any of the specified keys that are not already loaded. // Tells the asset to load the values of any of the specified keys that are not already loaded.
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler: [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
^{ ^{
dispatch_async( dispatch_get_main_queue(), dispatch_async( dispatch_get_main_queue(),
^{ ^{
[self prepareToPlayAsset:asset withKeys:requestedKeys]; if (session)
[blockSelf prepareToPlayAsset:asset withKeys:requestedKeys];
[asset release];
[requestedKeys release];
}); });
}]; }];
} }