4

最近、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つの部分があります前に

  1. 「を交換した後」と「交換する前に」 (ローカル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);  
} 

答えて

3

ガイズ:

私は根本的な原因を発見!

問題は関数HandleOutputBuffer(変更されたもの)から発生しました!

毎回、mp3データの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