AVAssetExportSession dealloc crashes in iOS 4.3
Update: I thought the issue was low memory; it's not. This error happens consistently in 4.3, and doesn't happen in 4.1/4.2 even under quite low memory conditions.
This is in a small Objective-C library I had to write for what is primarily a Monotouch app -- AVFoundation not being fully bound yet.
Here's the trace:
0 Orbiter 0x007977d8 mono_handle_native_sigsegv + 404
1 Orbiter 0x007746b4 mono_sigsegv_signal_handler + 348
2 libsystem_c.dylib 0x34ce472f _sigtramp + 42
3 AVFoundation 0x365b3ab5 -[AVAssetExportSession dealloc] + 164
4 CoreFoundation 0x34bc2c43 -[NSObject(NSObject) release] + 30
5 AVFoundation 0x365b3607 -[AVAssetExportSession release] + 62
6 CoreFoundation 0x34bdd047 sendRelease + 14
7 libsystem_blocks.dylib 0x312c292f _Block_object_dispose + 118
8 AVFoundation 0x365b45b3 __destroy_helper_block_5 + 22
9 libsystem_blocks.dylib 0x312c288f _Block_release + 58
10 libdispatch.dylib 0x30df18ed _dispatch_call_block_and_release + 16
11 libdispatch.dylib 0x30deced1 _dispatch_queue_drain + 240
12 libdispatch.dylib 0x30ded043 _dispatch_queue_invoke + 78
13 libdispatch.dylib 0x30dec611 _dispatch_worker_thread2 + 196
14 libsystem_c.dylib 0x34cda591 _pthread_wqthread + 264
15 libsystem_c.dylib 0x34cdabc4 _init_cpu_capabilities + 4294967295
Here's the code:
@implementation AVUtils : NSObject
+ (void) dubAudio:(NSURL*)videoUrl
withTrack:(NSURL*)audioUrl
outputTo:(NSURL*)newUrl
handleSuccess:(void(^)(void))successHandler
handleFailure:(void(^)(NSError* err))开发者_C百科failureHandler
{
AVURLAsset* video = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];
AVAssetTrack* videoTrack = [[video tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTime videoDuration = video.duration;
AVURLAsset* audio = [[AVURLAsset alloc]initWithURL:audioUrl options:nil];
AVAssetTrack* audioTrack = [[audio tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
CMTime audioDuration = audio.duration;
CMTime newDuration = CMTimeMinimum(audioDuration, videoDuration);
CMTimeRange newTimeRange = CMTimeRangeMake(kCMTimeZero, newDuration);
AVMutableComposition* newComposition = [AVMutableComposition composition];
NSError* theError;
BOOL success;
AVMutableCompositionTrack* newAudioTrack = [newComposition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
theError = nil;
success = [newAudioTrack insertTimeRange:newTimeRange ofTrack:audioTrack atTime:kCMTimeZero error:&theError];
if (success == NO) {
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Error adding audio track"
message:[theError localizedDescription]
delegate: nil
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alertView show];
[alertView release];
} else {
AVMutableCompositionTrack* newVideoTrack = [newComposition addMutableTrackWithMediaType:AVMediaTypeVideo
preferredTrackID:kCMPersistentTrackID_Invalid];
theError = nil;
success = [newVideoTrack insertTimeRange:newTimeRange ofTrack:videoTrack atTime:kCMTimeZero error:&theError];
if (success == NO) {
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Error adding audio track"
message:[theError localizedDescription]
delegate: nil
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alertView show];
[alertView release];
} else {
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:newComposition presetName:AVAssetExportPresetPassthrough];
_assetExport.outputFileType = @"com.apple.quicktime-movie";
_assetExport.outputURL = newUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void) {
if (_assetExport.status == AVAssetExportSessionStatusCompleted) {
successHandler();
} else {
failureHandler(_assetExport.error);
}
[_assetExport release];
[video release];
[audio release];
[newComposition release];
}
];
}
}
}
@end
My theory was that I was leaking the pointer to _assetExport.error
, passing it off to another thread -- which I was -- and then it was invalid when it was dereferenced because _assetExport
was being garbage collected. But I verified that the segfault happens even when the export succeeds, so that's not it in this case.
I'm pretty new to Obj-C -- can anyone see any other obvious flaws in what I'm doing here?
Looks like the memory management regarding your completion Block is the problem. The crash log says that it is crashing on the release of _assetExport.. you definitely shouldn't be releasing newComposition (you didn't alloc it or retain it).
精彩评论