gpt4 book ai didi

iphone - 使用 AudioQueue 服务播放 MP3 数据缓冲区 : Prime failed (-50)

转载 作者:可可西里 更新时间:2023-11-01 05:47:47 24 4
gpt4 key购买 nike

这几天我一直在努力寻找在 iPhone 上使用 AudioQueue 服务播放网络音频流(MP3 数据包格式)的方法。

为了成功实现这个目标,我先用AudioQueue把普通的本地MP3文件拿来播放,果然可以。然后,我用 stdio 函数 fread 替换了 AudioFileReadPackets,每次我都像 AudioFileReadPackets 一样 fread 相同数量的 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)

有人知道这个“Prime failed (-50)”错误的原因吗?帮忙zzzzzzz

*********************************************** ****************************************************** ****************************************************** *********************

为了解释我在替换工作上做了什么,我想向您展示代码的主要更改部分,有两部分:“替换前”和“替换后”

  1. 替换前(播放本地 MP3 文件):

1) 音频队列runloop回调

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) 创建音频队列

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。替换后(通过fread获取playbak mp3 data buffer):

为了代码移植顺利,我复制了关键变量的运行时值,如pAqData->bufferByteSize、pAqData->mNumPacketsToRead、pAqData->mDataFormat…等。并在替换代码中使用复制的值直接初始化这些变量。此行为的目的是放弃涉及 AudioToolbox 框架的接口(interface),如:AudioFileOpenURL、AudioFileGetProperty、AudioFileReadPackets……然后,我们可以使用 stdio 函数 fread 直接获取 mp3 数据包。修改后的代码如下所示:

1)音频队列runloop回调(之前的代码中,AudioFileReadPackets读取了338个包,共129792字节,我直接将这些值复制到替换代码中)

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) 打开音频文件(用fopen代替AudioFileOpenURL)

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)创建音频队列(直接初始化pAqData->mDataFormat为本地MP3播放模式赋值)

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(改的)!

因为函数fread每次都要读取338包mp3数据(不是1包),所以[pAqData->mPacketDescs]不是一个单一的变量,它实际上是一个数组,大小为338个数组项。因此,我们必须初始化所有 338 个数组项。

因此,我们需要更改代码:

static void HandleOutputBuffer(void                *aqData, 
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer)
{
...
pAqData->mPacketDescs->mStartOffset = 0;
pAqData->mPacketDescs->mVariableFramesInPacket = 0;
pAqData->mPacketDescs->mDataByteSize = 384;
...
}

进入

static void HandleOutputBuffer(void                *aqData, 
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer)
{
...
for (i = 0; i < 338; i++)
{
pAqData->mPacketDescs[i].mStartOffset = PACKET_SIZE * i;
pAqData->mPacketDescs[i].mVariableFramesInPacket = 0;
pAqData->mPacketDescs[i].mDataByteSize = PACKET_SIZE;
}
...
}

终于,问题解决了!

关于iphone - 使用 AudioQueue 服务播放 MP3 数据缓冲区 : Prime failed (-50),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7593142/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com