1
votes

When attempting to play AAC-HE content in an mp4 container, the reported sampling rate found in the mp4 container appears to be half of the actual sampling rate.

E.g it appears as 24kHz instead of 48kHz.

Using the FFmpeg AAC decoder, retrieving the actual sampling rate can be done by simply decoding an audio packet using

avcodec_decode_audio4

And looking at AVCodecContext::sample_rate which will be updated appropriately. From that it's easy to adapt the output.

With CoreAudio decoder, I would use a AudioConverterRef set the input and output AudioStreamBasicDescription and call AudioConverterFillComplexBuffer

As the converter performs all the required internal conversion including resampling it's fine. But it plays the content after resampling it to 24kHz (as that's what the input AudioStreamBasicDescription contains.

Would there be a way to retrieve the actual sampling rate as found be the decoder (rather than the demuxer) in a similar fashion as one can with FFmpeg ?

Would prefer to avoid losing audio quality if at all possible, and not downmix data

Thanks

1

1 Answers

0
votes

Found this : https://developer.apple.com/library/ios/qa/qa1639/_index.html

explaining on how to retrieve the higher quality stream..

resulting code is as follow:

AudioStreamBasicDescription inputFormat;
AudioFormatListItem* formatListPtr = NULL;
UInt32 propertySize;
OSStatus rv = noErr;

rv = AudioFileStreamGetPropertyInfo(mStream,
                                    kAudioFileStreamProperty_FormatList,
                                    &propertySize,
                                    NULL);
if (rv == noErr) {
  // allocate memory for the format list items
  formatListPtr = static_cast<AudioFormatListItem*>(malloc(propertySize));
  if (!formatListPtr) {
    LOG("Error %d constructing AudioConverter", rv);
    mCallback->Error();
    return;
  }

  // get the list of Audio Format List Item's
  rv = AudioFileStreamGetProperty(mStream,
                                  kAudioFileStreamProperty_FormatList,
                                  &propertySize,
                                  formatListPtr);
  if (rv == noErr) {
    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
    rv = AudioFormatGetProperty(kAudioFormatProperty_FirstPlayableFormatFromList,
                                propertySize,
                                formatListPtr,
                                &indexSize,
                                &itemIndex);
    if (rv != noErr) {
      free(formatListPtr);
      LOG("Error %d retrieving best format for AudioConverter", rv);
      return;
    }
    // copy the format item at index we want returned
    inputFormat =  formatListPtr[itemIndex].mASBD;
  }
  free(formatListPtr);
} else {
  // Fill in the input format description from the stream.
  nsresult rv = AppleUtils::GetProperty(mStream,
                                        kAudioFileStreamProperty_DataFormat,
                                        &inputFormat);
  if (NS_FAILED(rv)) {
    LOG("Error %d retrieving default format for AudioConverter", rv);
    return;
  }
}

// Fill in the output format manually.
PodZero(&mOutputFormat);
mOutputFormat.mFormatID = kAudioFormatLinearPCM;
mOutputFormat.mSampleRate = inputFormat.mSampleRate;
mOutputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;