3

私は現在、MP3とAACのラジオ局をストリーミングしています。ICY / HTTPヘッダーを読んでいて、content-typeでaudio/aacまたはaudio/aacpを検出するときは、AudioFileStreamOpenの手がかりとしてkAudioFileAAC_ADTSTypeを指定します。それ以外の場合は、kAudioFileMP3Typeを指定します。

これはうまく機能します。問題は、ステーションがAACを再生しているが、HTTPヘッダーのコンテンツタイプとしてaudio/aacpを送信しない場合です。それが起こったとき、私は通常mp3の手がかりを使ってaudiofilestreamを作成します(手がかりとして0でも違いはありません)、そしてaudiofilestreamのプロパティコールバックは、ストリームがMP3を読んでいると考えていることを示し、formatListコールバックも起こりません。オーディオキューの作成が失敗する時が来ます。

コンストラクターにAACヒントを渡さずにAudioFileStreamをAACで動作させる方法はありますか、またはステーションデータベースでそれらを何らかの方法でマークする以外に、それらのステーションを検出する方法について他のアイデアがありますか?また、通常は失敗するたびに、ヒントとしてAACを使用して新しいオーディオファイルストリームを作成しようとはしません。

4

1 に答える 1

1

しばらくこのコードを見ていませんでしたが、うまくいくはずです。

// 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;
}
于 2011-03-13T18:46:14.633 に答える