2011-05-18 74 views
5

這是我的目標:我想將一個.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,並採用與我在視頻軌道上使用的方法相同的方法,但它似乎沒有正確格式化。

在這一點上,我覺得我盲目地徘徊,如果有人能告訴我這種方法是否可行,我會非常喜歡它。如果不是,我當然會欣賞一個可行的。

回答

3

爲每個軌道創建AVMutableCompositions(基本上是新的AVAssets)似乎對我來說很簡單,我只是在音軌上使用AVAssetReader。另外,你的videoComposition似乎並沒有在任何地方使用,所以爲什麼要創建它?

在任何情況下,要使兩種解決方案都起作用,請將您的音頻會話類別設置爲kAudioSessionCategory_MediaPlayback並啓用kAudioSessionProperty_OverrideCategoryMixWithOthers

我從來沒有找到任何解釋爲什麼這是必要的文檔。

+0

我省略了使用視頻合成的代碼,因爲它的工作原理並且會增加已經很長的問題的大小。無論如何,在音頻會話中設置這些屬性確定了問題。謝謝你爲我節省了幾個小時的挫折。我從來沒有聽說過AVAudioSession ... – 2011-05-18 16:44:33

+0

不客氣。解決方案絕對不明顯。 – 2011-05-18 16:55:32