AVAssetExportSession dealloc вылетает в iOS 4.3 - PullRequest
2 голосов
/ 18 марта 2011

Обновление: Я думал, что проблема в нехватке памяти; это не. Эта ошибка постоянно возникает в 4.3 и не встречается в 4.1 / 4.2 даже при достаточно низких условиях памяти.

Это небольшая библиотека 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 - кто-нибудь может увидеть какие-либо другие очевидные недостатки в том, что я здесь делаю?

1 Ответ

2 голосов
/ 18 марта 2011

Похоже, управление памятью относительно вашего завершения Блок является проблемой.В журнале сбоев говорится, что он выходит из строя при выпуске _assetExport .. вам определенно не следует выпускать newComposition (вы его не распределили или не сохранили).

...