最近、iPhoneのAudioQueueサービスを使用してネットワークオーディオストリーム(MP3パケット形式)を再生する方法を見つけるのに苦労しました。AudioQueueサービスを使用した再生MP3データバッファ:Prime failed(-50)
この目標を連続的に達成するために、まずAudioQueueを使用して再生する共通のローカルMP3ファイルを取得しました。そして、私はAudioFileReadPacketsをstdio関数freadに置き換えました。そして、AudioFileReadPacketsのようなmp3パケットの同じ量を、ネットワークから来るオーディオストリームをシミュレートするたびに自由にしました。しかし、この時点では、エラーが来た:
2011-09-28 14:21:28.245 SunFlower[1554:207] Prime: Exiting because mConverterError is -50 (0x11940 req, 0x0 primed)
2011-09-28 14:21:28.253 SunFlower[1554:207] Prime failed (-50); will stop (72000/0 frames)
誰かがこの「首相が失敗した(-50)」エラーの原因は何を知っていますか?ヘルプZZZZZZZ
******************************************* *************************************************** *************************************************** *********************。私はあなたのメインを表示したい
私は交換作業に何をしたか説明するのは、コードの一部を変更し、2つの部分があります前に
- 「を交換した後」と「交換する前に」 (ローカルMP3ファイルをplaybak)の交換:
1)オーディオキュー実行ループのコールバック
static void HandleOutputBuffer(void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer)
{
AQPlayerState *pAqData = (AQPlayerState *) aqData;
UInt32 numBytesReadFromFile;
UInt32 numPackets = pAqData->mNumPacketsToRead;
UInt32 i = 0;
printf("HandleOutputBuffer::Start!\n");
//If the audio queue is stopped, returns immediately
if(pAqData->mIsRunning == 0)
{
printf("HandleOutputBuffer::Error Return!\n");
return;
}
//Read a packet of audio data from file stream
AudioFileReadPackets(pAqData->mAudioFile,
false,
&numBytesReadFromFile,
pAqData->mPacketDescs,
pAqData->mCurrentPacket,
&numPackets,
inBuffer->mAudioData);
//Enqueue the audio packet into the audio queue
if(numPackets > 0)
{
printf("HandleOutputBuffer::Step 1!\n");
inBuffer->mAudioDataByteSize = numBytesReadFromFile;
AudioQueueEnqueueBuffer(pAqData->mQueue,
inBuffer,
(pAqData->mPacketDescs ? numPackets : 0),
pAqData->mPacketDescs);
pAqData->mCurrentPacket += numPackets;
}
else
{
printf("HandleOutputBuffer::Step 2!\n");
AudioQueueStop(pAqData->mQueue,
false);
pAqData->mIsRunning = false;
}
}
2)を開き、オーディオファイル
OSStatus AqOpenAudioFile(char *filePath, AQPlayerState *pAqData)
{
CFURLRef audioFileURL;
OSStatus result;
UInt32 maxPacketSize;
UInt32 propertySize = sizeof (maxPacketSize);
audioFileURL =
CFURLCreateFromFileSystemRepresentation(NULL,
(const UInt8 *) filePath,
strlen (filePath),
false);
result = AudioFileOpenURL(audioFileURL,
kAudioFileReadPermission,
0,
&(pAqData->mAudioFile));
CFRelease(audioFileURL);
AudioFileGetProperty(pAqData->mAudioFile,
kAudioFilePropertyPacketSizeUpperBound,
&propertySize,
&maxPacketSize);
DeriveBufferSize(pAqData->mDataFormat,
maxPacketSize,
0.5,
&(pAqData->bufferByteSize),
&(pAqData->mNumPacketsToRead));
return result;
}
3)(playbakのmp3データバッファは、関数freadで取得)交換した後
OSStatus AqCreateAudioQueue(AQPlayerState *pAqData)
{
UInt32 dataFormatSize = sizeof (AudioStreamBasicDescription);
OSStatus result;
bool isFormatVBR;
UInt32 cookieSize = sizeof (UInt32);
bool couldNotGetProperty;
AudioFileGetProperty(pAqData->mAudioFile,
kAudioFilePropertyDataFormat,
&dataFormatSize,
&(pAqData->mDataFormat));
result = AudioQueueNewOutput(&(pAqData->mDataFormat),
HandleOutputBuffer,
pAqData,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&(pAqData->mQueue));
//Configurate the VBR property if any
isFormatVBR = (pAqData->mDataFormat.mBytesPerPacket == 0 ||
pAqData->mDataFormat.mFramesPerPacket == 0);
if(isFormatVBR)
{
pAqData->mPacketDescs =
(AudioStreamPacketDescription*)malloc(pAqData->mNumPacketsToRead * sizeof(AudioStreamPacketDescription));
}
else
{
pAqData->mPacketDescs = NULL;
}
//Set Metadata for Audio Queue
couldNotGetProperty =
AudioFileGetPropertyInfo(pAqData->mAudioFile,
kAudioFilePropertyMagicCookieData,
&cookieSize,
NULL);
if (!couldNotGetProperty && cookieSize)
{
char* magicCookie = (char *)malloc(cookieSize);
AudioFileGetProperty(pAqData->mAudioFile,
kAudioFilePropertyMagicCookieData,
&cookieSize,
magicCookie);
AudioQueueSetProperty(pAqData->mQueue,
kAudioQueueProperty_MagicCookie,
magicCookie,
cookieSize);
free(magicCookie);
}
//Set the playback gain
AudioQueueSetParameter(pAqData->mQueue,
kAudioQueueParam_Volume,
AQ_PLAYBACK_GAIN);
}
2.オーディオキューを作成します。
スムーズにポーティングコードを作るために、私はランをコピーpAqData-> bufferByteSize、pAqData-> mNumPacketsToRead、pAqData-> mDataFormat ...などのクリティカル変数の時間値。置換されたコードのコピーされた値を使用して、これらの変数を直接初期化します。この動作の目的はAudioToolboxフレームワークのインタフェースを取り除くことです:AudioFileOpenURL、AudioFileGetProperty、AudioFileReadPackets ...そして、mp3パケットを直接取得するためにstdio関数freadを使用することができます。変更されたコードを以下に示す:
1)オーディオキュー実行ループのAudioFileReadPackets 338個のパケットを読み取る前のコードにコールバック(、および完全129792バイト、Iは
static void HandleOutputBuffer(void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer)
{
AQPlayerState *pAqData = (AQPlayerState *) aqData;
UInt32 numBytesReadFromFile;
UInt32 numPackets = pAqData->mNumPacketsToRead;
UInt32 i = 0;
printf("HandleOutputBuffer::Start!\n");
//If the audio queue is stopped, returns immediately
if(pAqData->mIsRunning == 0)
{
printf("HandleOutputBuffer::Error Return!\n");
return;
}
//Read a packet of audio data using fread
memset(audio_buffer, 0, 327680);
memset(inBuffer->mAudioData, 0, 327680);
pAqData->mPacketDescs->mStartOffset = 0;
pAqData->mPacketDescs->mVariableFramesInPacket = 0;
pAqData->mPacketDescs->mDataByteSize = 384;
numBytesReadFromFile = fread(audio_buffer, sizeof(uint8_t), 129792, source_file);
numPackets = 338;
memcpy(inBuffer->mAudioData, audio_buffer, 327680);
//Enqueue the audio packet into the audio queue
if(numPackets > 0)
{
printf("HandleOutputBuffer::Step 1!\n");
inBuffer->mAudioDataByteSize = numBytesReadFromFile;
AudioQueueEnqueueBuffer(pAqData->mQueue,
inBuffer,
(pAqData->mPacketDescs ? numPackets : 0),
pAqData->mPacketDescs);
pAqData->mCurrentPacket += numPackets;
}
else
{
printf("HandleOutputBuffer::Step 2!\n");
AudioQueueStop(pAqData->mQueue,
false);
pAqData->mIsRunning = false;
}
}
)直接置換コードにこれらの値をコピー
2)を開き、オーディオファイル(AudioFileOpenURLを置き換えるために使用するのfopen)
OSStatus AqOpenAudioFile(char *filePath, AQPlayerState *pAqData)
{
CFURLRef audioFileURL;
OSStatus result;
UInt32 maxPacketSize;
UInt32 propertySize = sizeof (maxPacketSize);
source_file = fopen(filePath, "r");
memset(audio_buffer, 0, 327680);
fread(audio_buffer, sizeof(uint8_t), 32, source_file);
pAqData->bufferByteSize = 327680;
pAqData->mNumPacketsToRead = 338;
return result;
}
3)オーディオキューを作成します(直接現地MP3再生モードに割り当てられた値でpAqData-> mDataFormatを初期化)
OSStatus AqCreateAudioQueue(AQPlayerState *pAqData)
{
UInt32 dataFormatSize = sizeof (AudioStreamBasicDescription);
OSStatus result;
bool isFormatVBR;
UInt32 cookieSize = sizeof (UInt32);
bool couldNotGetProperty;
memset(&(pAqData->mDataFormat), 0, sizeof(AudioStreamBasicDescription));
pAqData->mDataFormat.mSampleRate = 48000;
pAqData->mDataFormat.mFormatID = 778924083;//mp3 ID
pAqData->mDataFormat.mFramesPerPacket = 1152;
pAqData->mDataFormat.mChannelsPerFrame = 2;
result = AudioQueueNewOutput(&(pAqData->mDataFormat),
HandleOutputBuffer,
pAqData,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&(pAqData->mQueue));
//Configurate the VBR property if any
isFormatVBR = (pAqData->mDataFormat.mBytesPerPacket == 0 ||
pAqData->mDataFormat.mFramesPerPacket == 0);
if(isFormatVBR)
{
pAqData->mPacketDescs =
(AudioStreamPacketDescription*)malloc(pAqData->mNumPacketsToRead *
sizeof(AudioStreamPacketDescription));
}
else
{
pAqData->mPacketDescs = NULL;
}
//Set the playback gain
AudioQueueSetParameter(pAqData->mQueue,
kAudioQueueParam_Volume,
AQ_PLAYBACK_GAIN);
}
私は同じ問題があります。しかし、私はHandleOutputBufferをどこで変更したり再定義しなければならないのか理解できません。 – Aplextor