Dynamic AAC discovery and streaming using AQ and audiofilestream

I am currently broadcasting MP3 and AAC radio stations. I read ICY / HTTP headers, and when detecting audio / aac or audio / aacp in the content type, I provide kAudioFileAAC_ADTSType as the key for AudioFileStreamOpen, otherwise I give it kAudioFileMP3Type.

It works fine, the problem is that the station plays AAC, but does not send audio / aacp as content in the HTTP headers. When this happens, I usually create an audio file using an mp3 key (nothing is different from 0 as the key), and then the callbacks on the properties of the audio file show that the stream believes it is reading MP3, the formatList callback never happens, and when it's time to create a sound queue.

Is there a way to get AudioFileStream to work with AAC without specifying AAC in the constructor, or does anyone have a different idea on how to find those stations that then label them somehow in the station databases? I would also rather not try to create a new AAC audio file as a hint every time I fail.

+3
source share
1 answer

I haven't looked at this code after a while, but I think it should do the trick.

// the file stream parser is now ready to produce audio packets.
// get the stream format.
AudioFormatListItem afli = GetFirstPlayableAudioFormatForFile(inAudioFileStream);
AudioStreamBasicDescription asbd = afli.mASBD;
...
// create the audio queue
err = AudioQueueNewOutput(&asbd, MyAudioQueueOutputCallback, myData, NULL, NULL, 0, &myData->audioQueue);

GetFirstPlayableAudioFormatForFile impl:

AudioFormatListItem GetFirstPlayableAudioFormatForFile(AudioFileStreamID inAudioFileStream)
{
    AudioFormatListItem *formatListPtr = NULL;
    AudioFormatListItem formatItem = {0};
    UInt32 propertySize;

    OSStatus status = noErr;

    if (NULL == inAudioFileStream) return formatItem;

    status = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_FormatList, &propertySize, NULL);
    if (noErr == status) {

        // allocate memory for the format list items
        formatListPtr = (AudioFormatListItem *)malloc(propertySize);
        if (NULL == formatListPtr) return formatItem;

        // get the list of Audio Format List Item's
        status = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_FormatList, &propertySize, formatListPtr);
        if (noErr == status) {
            // print out some helpful information
            UInt32 numFormats = propertySize / sizeof(AudioFormatListItem);
            printf ("This file has a %d layered data format:\n", (int)numFormats);
            /*for (unsigned int i = 0; i < numFormats; ++i) {
                CAStreamBasicDescription(formatListPtr[i].mASBD).Print();
            }*/

            UInt32 itemIndex;
            UInt32 indexSize = sizeof(itemIndex);

            // get the index number of the first playable format -- this index number will be for
            // the highest quality layer the platform is capable of playing
            status = AudioFormatGetProperty(kAudioFormatProperty_FirstPlayableFormatFromList, propertySize,
                                            formatListPtr, &indexSize, &itemIndex);
            if (noErr == status) {
                printf ("Returning AudioFormatListItem at index %d.\n", (int)itemIndex);
                // copy the format item at index we want returned
                formatItem =  formatListPtr[itemIndex];
            }
        }

        free(formatListPtr);
    } else {
        AudioStreamBasicDescription asbd;
        UInt32 asbdSize = sizeof(asbd);
        /*status = */AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd);
        //if (err) { errorDidOccur(myData, err, @"get kAudioFileStreamProperty_DataFormat"); return err; }

        formatItem.mASBD = asbd;
    }


    return formatItem;
}
+1
source

All Articles