4

В эти дни я изо всех сил пытался найти способ воспроизведения сетевого аудиопотока (в формате MP3-пакета) с помощью AudioQueue Service на iPhone.Воспроизведение MP3-буфера данных с использованием сервиса AudioQueue: Prime failed (-50)

Для достижения этой цели я впервые получил обычный локальный MP3-файл для воспроизведения с использованием AudioQueue, и он действительно работает. И затем я заменил AudioFileReadPackets файлом stdio, и каждый раз, когда я пробовал такое же количество 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) 

Кто-то знает, что является причиной для этого «Prime не удалось (-50)» ошибка? Помощь zzzzzzz

******************************************* ************************************************** ************************************************** **********************.

Чтобы объяснить, что я сделал на заменяющего работу, я хотел бы показать вам основную измененную часть кода, есть две части: «Перед заменой» и «после замены»

  1. Перед замена (playbak локальный файл 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. После замены (playbak буфер данных mp3 както FREAD):

Для того, чтобы сделать код портирование гладко, я скопировал RUN- значение времени критических переменных, таких как pAqData-> bufferByteSize, pAqData-> mNumPacketsToRead, pAqData-> mDataFormat ... и т. д. И непосредственно инициализируйте эти переменные, используя скопированное значение в замененном коде. Цель этого поведения состоит в том, чтобы отбросить интерфейсы инфраструктуры AudioToolbox, такие как: AudioFileOpenURL, AudioFileGetProperty, AudioFileReadPackets ... И затем мы можем использовать функцию stdio, чтобы получить 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) Открыть аудио-файл (используйте Еореп заменить 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 (измененная)!

Потому что каждый раз функция 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; 
    } 
    ... 
} 

Наконец, проблема фиксированной!

+0

У меня такая же проблема. Но я не могу понять, где я должен изменить или переопределить HandleOutputBuffer? – Aplextor