winamp/Src/aacdec-mft/MP4AACDecoder.cpp

171 lines
3.6 KiB
C++

#include "MP4AACDecoder.h"
#include <Mferror.h>
#include <Mfapi.h>
#include "../external_dependencies/libmp4v2/mp4.h"
#include "util.h"
#include "../nsutil/pcm.h"
MP4AACDecoder::MP4AACDecoder()
{
isFloat = false;
gain=1.0f;
channels = 0;
}
MP4AACDecoder::~MP4AACDecoder()
{
}
int MP4AACDecoder::OpenMP4(MP4FileHandle mp4_file, MP4TrackId mp4_track, size_t output_bits, size_t maxChannels, bool useFloat)
{
HRESULT hr;
unsigned char *buffer;
uint32_t buffer_size;
if (useFloat) {
this->bitsPerSample = 32;
} else if (output_bits) {
this->bitsPerSample = (unsigned int)output_bits;
} else {
this->bitsPerSample = 16;
}
this->isFloat = useFloat;
if (MP4GetTrackESConfiguration(mp4_file, mp4_track, (uint8_t **)&buffer, &buffer_size) && buffer) {
hr = decoder.Open(buffer, buffer_size);
if (SUCCEEDED(hr)) {
uint32_t local_sample_rate, local_channels;
hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels);
if (SUCCEEDED(hr)) {
this->channels = local_channels;
return MP4_SUCCESS;
}
}
}
return MP4_FAILURE;
}
void MP4AACDecoder::Close()
{
}
void MP4AACDecoder::Flush()
{
decoder.Flush();
}
int MP4AACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *_bitsPerSample)
{
bool dummy;
return GetOutputPropertiesEx(sampleRate, channels, _bitsPerSample, &dummy);
}
int MP4AACDecoder::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *useFloat)
{
HRESULT hr;
UINT32 local_sample_rate, local_channels;
hr = decoder.GetOutputProperties(&local_sample_rate, &local_channels);
if (FAILED(hr)) {
return MP4_FAILURE;
}
*sampleRate = local_sample_rate;
*channels = local_channels;
*bitsPerSample = this->bitsPerSample;
*useFloat = this->isFloat;
return MP4_SUCCESS;
}
int MP4AACDecoder::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
{
HRESULT hr;
hr = decoder.Feed(inputBuffer, inputBufferBytes);
if (FAILED(hr)) {
return MP4_FAILURE;
}
hr = decoder.Decode(outputBuffer, outputBufferBytes, this->bitsPerSample, this->isFloat, this->gain);
if (FAILED(hr)) {
return MP4_FAILURE;
}
return MP4_SUCCESS;
}
int MP4AACDecoder::OutputFrameSize(size_t *frameSize)
{
if (channels == 0) {
return MP4_FAILURE;
}
size_t local_frame_size;
if (FAILED(decoder.OutputBlockSizeSamples(&local_frame_size))) {
return MP4_FAILURE;
}
*frameSize = local_frame_size / channels;
return MP4_SUCCESS;
}
int MP4AACDecoder::CanHandleCodec(const char *codecName)
{
return !strcmp(codecName, "mp4a");
}
int MP4AACDecoder::CanHandleType(uint8_t type)
{
switch (type)
{
case MP4_TYPE_MPEG4_AUDIO:
return 1;
case MP4_TYPE_MPEG2_AAC_LC_AUDIO:
return 1;
default:
return 0;
}
}
int MP4AACDecoder::CanHandleMPEG4Type(uint8_t type)
{
switch (type)
{
case MP4_MPEG4_TYPE_AAC_LC_AUDIO:
case MP4_MPEG4_TYPE_AAC_HE_AUDIO:
case MP4_MPEG4_TYPE_PARAMETRIC_STEREO:
return 1;
default:
return 0;
}
}
void MP4AACDecoder::EndOfStream()
{
decoder.Feed(0, 0);
}
#ifdef CBCLASS
#undef CBCLASS
#endif
#define CBCLASS MP4AACDecoder
START_DISPATCH;
CB(MPEG4_AUDIO_OPENMP4, OpenMP4)
#if 0
CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate)
#endif
CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize)
CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties)
CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx)
CB(MPEG4_AUDIO_DECODE, DecodeSample)
VCB(MPEG4_AUDIO_FLUSH, Flush)
VCB(MPEG4_AUDIO_CLOSE, Close)
CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec)
CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType)
CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type)
CB(MPEG4_AUDIO_SET_GAIN, SetGain)
END_DISPATCH;