2011-03-17 103 views
2

更新:我以爲問題是內存不足;不是。這個錯誤在4.3中始終發生,即使在內存很低的情況下也不會發生在4.1/4.2中。AVAssetExportSession在iOS 4.3中發生dealloc崩潰

這是在一個小型的Objective-C庫中,我不得不寫一些主要是Monotouch應用程序--AVFoundation尚未完全綁定。

這裏的痕跡:

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 

下面的代碼:

@implementation AVUtils : NSObject 

+ (void) dubAudio:(NSURL*)videoUrl 
    withTrack:(NSURL*)audioUrl 
    outputTo:(NSURL*)newUrl 
    handleSuccess:(void(^)(void))successHandler 
    handleFailure:(void(^)(NSError* err))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 

我的理論是,我是泄漏的指針_assetExport.error,其傳遞到另一個線程 - 我是 - - 當它被解除引用時它是無效的,因爲_assetExport被垃圾收集。但是,我證實,即使導出成功,segfault也會發生,所以在這種情況下不是這樣。

我是Obj-C的新手 - 任何人都可以看到我在這裏做的任何其他明顯的缺陷?

+0

我很好奇,你發現哪些API在MonoTouch中缺失? – 2011-03-19 02:37:24

+0

嘿,米格爾 - 我認爲AVMutableCompositionTrack.InsertTimeRange()是最大的一個。這是在11月份,所以它可能自那時起被添加,我沒有注意到。 – 2011-03-19 14:36:59

回答

2

看起來像內存管理有關您的完成塊是問題。崩潰日誌說它在_assetExport發行版崩潰..你絕對不應該釋放newComposition(你沒有分配它或保留它)。

+0

好點。我也沒有發佈'成功==沒有'的情況下的任何alloc'd的東西...這是什麼來自貨物崇拜編程。 :)我會清理它,看看它是否有幫助。 – 2011-03-18 17:04:37

+0

這似乎已修復它。謝謝! – 2011-03-19 01:08:20