2011-09-29 33 views
4

這些天,我努力尋找在iPhone上使用AudioQueue服務播放網絡音頻流(MP3包格式)的方式。播放MP3數據緩衝區:總理失敗(-50)

依次達到這個目標,我首先得到了當地常見的MP3文件的使用AudioQueue播放,和它的工作。然後,我更換了AudioFileReadPackets與標準輸入輸出功能的fread,每次我FREAD MP3包相同數量的像AudioFileReadPackets做過,模擬從網絡傳來的音頻流。不過,這一次,錯誤傳來:

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

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

爲了解釋我做了什麼對替換的工作,我想向您展示這些代碼的主要變化的部分,有兩個部分:「更換之前」和

  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.將(回放時mp3數據緩衝器通過的fread得到)後:

爲了使代碼順利移植,我複製的遊程關鍵變量的時間值,如pAqData-> bufferByteSize,pAqData-> mNumPacketsToRead,pAqData-> mDataFormat ...等。並使用替換代碼中的複製值直接初始化這些變量。這種行爲的目的是放棄involking AudioToolbox框架一樣的接口:AudioFileOpenURL,AudioFileGetProperty,AudioFileReadPackets ...然後,我們可以使用標準輸入輸出函數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);  
} 

回答

3

傢伙:

我找到了根本原因!

問題來自函數HandleOutputBuffer(更改後的)!因爲每次函數都會發送338個數據包(不只是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; 
    } 
    ... 
} 

最後,問題解決!

+0

我有同樣的問題。但我不明白,我應該在哪裏更改或重新定義HandleOutputBuffer? – Aplextor