這是我的目標:我想將一個.3gp電影文件加載到AVURLAsset。然後,我想拍攝視頻軌道,並將輸出幀抽成OpenGL ES紋理。這將是視頻播放。然後我想繼續利用AVFoundation播放音頻。這個框架非常龐大,所以我希望在這個框架上提供一些經驗豐富的幫助。如何獨立處理AVURLAsset的單獨軌道?
我實際上有兩個部分單獨工作,但是當我嘗試同時執行兩個操作時總會出錯。這是我當前的嘗試,簡而言之(此不再贅述所有錯誤處理):
我加載名爲.3gp文件到AVURLAsset並加載軌道:
NSURL* fileURL = [[NSBundle mainBundle] URLForResource:someName withExtension:someExtension];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^ {/* More Code */}];
在完成處理程序,我得到到音頻和視頻軌道參考:
// Tracks loaded, grab the audio and video tracks.
AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
接下來,我創建一個只包含音軌,只是視頻軌道單獨AVMutableComposition秒。我不知道如果這是完全必要的,但它似乎是一個好主意,它似乎也工作:
// Make a composition with the video track.
AVMutableComposition* videoComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* videoCompositionTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:[videoTrack timeRange] ofTrack:videoTrack atTime:CMTimeMake(0, 1) error:nil];
// Make a composition with the audio track.
AVMutableComposition* audioComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* audioCompositionTrack = [audioComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioCompositionTrack insertTimeRange:[audioTrack timeRange] ofTrack:audioTrack atTime:CMTimeMake(0, 1) error:nil];
現在,我到如何處理每個軌道的細節。我相當有信心,我有處理視頻軌道的唯一方法,即創建視頻合成的AVAssetReader,並添加由視頻合成軌道創建的AVAssetTrackReaderOutput。通過保持對該軌道輸出的引用,我可以調用它的-copyNextSampleBuffer
方法來獲取將視頻輸出泵入OpenGL ES紋理所需的信息。此作品不夠好自身:
// Create Asset Reader and Output for the video track.
NSDictionary* settings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
_assetReader = [[AVAssetReader assetReaderWithAsset:vComposition error:nil] retain];
_videoTrackOutput = [[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:vCompositionTrack outputSettings:settings] retain];
[_assetReader addOutput:_videoTrackOutput];
[_assetReader startReading];
什麼似乎破壞了整個事情是試圖以任何方式進行回放。我不確定採用哪種方法處理剩餘的音軌。只要堅持AVFoundation的領域,我看到兩種可能的方法。第一種方法是使用一個AVPlayer播放音頻組成:
// Create a player for the audio.
AVPlayerItem* audioPlayerItem = [AVPlayerItem playerItemWithAsset:aComposition];
AVPlayer* audioPlayer = [[AVPlayer playerWithPlayerItem:audioPlayerItem] retain];
[audioPlayer play];
這工作,因爲我可以聽到想要的聲音。不幸的是創建這個播放器保證了AVAssetReaderTrackOutput用於視頻通話組成時-copyNextSampleBuffer
失敗,一個神祕的錯誤:
AVAssetReaderStatusFailed
錯誤域= AVFoundationErrorDomain 代碼= -11800「的操作不能 完成」的UserInfo = 0x456e50 {NSLocalizedFailureReason =發生未知 錯誤(-12785), NSUnderlyingError = 0x486570 「的 操作不能完成。 (OSStatus錯誤-12785。)」, NSLocalizedDescription =操作 無法完成}
我感到困惑它們如何相互干擾,但無論如何,這種做法似乎是一個死衚衕。
我認爲音頻播放的另一種選擇是AVAudioPlayer類,但我無法讓它與AVAsset一起工作。我試圖使用它的-initWithData:error:
方法,通過聚合CMSampleBufferRefs的內容構建NSData,並採用與我在視頻軌道上使用的方法相同的方法,但它似乎沒有正確格式化。
在這一點上,我覺得我盲目地徘徊,如果有人能告訴我這種方法是否可行,我會非常喜歡它。如果不是,我當然會欣賞一個可行的。
我省略了使用視頻合成的代碼,因爲它的工作原理並且會增加已經很長的問題的大小。無論如何,在音頻會話中設置這些屬性確定了問題。謝謝你爲我節省了幾個小時的挫折。我從來沒有聽說過AVAudioSession ... – 2011-05-18 16:44:33
不客氣。解決方案絕對不明顯。 – 2011-05-18 16:55:32