开发者

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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜