![](/img/trans.png)
[英]How to use AVAssetReader and AVAssetWriter for multiple tracks (audio and video) simultaneously?
[英]difference between how AVAssetReader and AudioFileReadPackets reads Audio
考慮這兩種場景,用於從音頻文件讀取/寫入數據(用於通過網絡發送):
場景1:音頻文件服務:
使用音頻文件服務中的 AudioFileReadPackets 。 這會生成您可以通過網絡輕松發送的音頻數據包。 在接收端,您使用AudioFileStreamOpen和AudioFileStreamParseBytes來解析數據。
然后AudioFileStreamParseBytes有兩個回調函數: AudioFileStream_PropertyListenerProc和AudioFileStream_PacketsProc 。 當在流中發現新屬性並且分別從流接收到分組時,將調用這些人。 收到數據包后,您可以使用音頻隊列服務將其提供給音頻隊列,該服務可以正常播放文件。
注意:此方法不適用於存儲在iPod庫中的音樂文件,這使我們進入第二種情況:
場景2:AVAssetReader:
使用AVAssetReader,您可以從iPod音樂庫中讀取並通過網絡發送數據包。 通常,您可以直接在類似於上面的音頻隊列上加載數據包。 但是,在這種情況下,您必須創建一個線程以確保在隊列已滿時阻止接收數據包,並在隊列緩沖區可用時取消阻止(請參閱此示例)。
題:
是否可以使用AVAssetReader發送數據包,只是讓它被AudioFileStreamParseBytes讀取? (動機是AudioFileStreamParseBytes的回調將處理線程/阻塞業務並為您節省痛苦)。 我嘗試這樣做:
1.首先使用AVAssetReader讀取音頻文件
//NSURL *assetURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?id=1053020204400037178"];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
NSError * error = nil;
AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];
AVAssetTrack* track = [songAsset.tracks objectAtIndex:0];
// Note: I don't supply an audio format description here, rather I pass on nil to keep the original
// file format. In another piece of code (see here: http://stackoverflow.com/questions/12264799/why-is-audio-coming-up-garbled-when-using-avassetreader-with-audio-queue?answertab=active#tab-top) I can extract the audio format from the track, let's say it's an AAC format.
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
outputSettings:nil];
[reader addOutput:readerOutput];
[reader startReading];
2.設置流光
// notice how i manually add the audio file type (for the file hint parameter)
// using the info from step one.. If i leave it as 0, this call fails and returns
// the typ? error, which is :The specified file type is not supported.
streamer->err = AudioFileStreamOpen((__bridge void*)streamer,
ASPropertyListenerProc, ASPacketsProc,
kAudioFileAAC_ADTSType, &(streamer->audioFileStream));
3.一旦我收到數據,我解析字節:
streamer->err = AudioFileStreamParseBytes(streamer->audioFileStream, inDataByteSize, inData, 0);
問題:當我做這種方式。我發送的字節數和AudioFileStreamParseBytes 不會失敗。 但是,永遠不會調用回調* AudioFileStream_PropertyListenerProc *和* AudioFileStream_PacketsProc *。 這讓我覺得解析器無法解析字節並從中提取任何有用的信息..在AudioStreamParseBytes的文檔中它指出:*你應該提供至少不止一個數據包的音頻文件數據,但它最好一次提供一些數據包到幾秒數據。*我發送超過900字節,這低於GKSession的數據限制 。 我非常確定900字節就足夠了(在方案1下測試時,每次總字節數為417,並且工作正常)。
有任何想法嗎?
簡短的回答是,音頻數據包被AudioFileStreamParseBytes解析是沒有意義的。在文檔中 AudioFileStreamParseBytes是一個依賴於音頻文件存在的函數(因此參數inAudioFileStream ..定義為您希望傳遞數據的解析器的ID。解析器ID由AudioFileStreamOpen函數返回。 )
所以吸取了教訓:不要嘗試使用iOS功能來適應你的情況..它應該是另一種方式。
我最終做的是直接將數據提供給音頻隊列..而不經過所有這些不必要的中間函數..更深入的方式是將數據饋送到音頻單元..但我的應用程序不需要那個級別控制
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.