209 lines
6.6 KiB
C
209 lines
6.6 KiB
C
|
#ifndef NULLSOFT_MPEG4AUDIOH
|
||
|
#define NULLSOFT_MPEG4AUDIOH
|
||
|
#include "../external_dependencies/libmp4v2/mp4.h"
|
||
|
#include <bfc/dispatch.h>
|
||
|
#include <bfc/platform/types.h>
|
||
|
#include <api/service/services.h>
|
||
|
enum
|
||
|
{
|
||
|
MP4_SUCCESS = 0,
|
||
|
MP4_FAILURE = 1,
|
||
|
|
||
|
MP4_GETOUTPUTPROPERTIES_NEED_MORE_INPUT = 2,
|
||
|
MP4_NEED_MORE_INPUT = 2,
|
||
|
|
||
|
MP4_GETCURRENTBITRATE_UNKNOWN = 2, // unable to calculate (e.g. VBR for CT's decoder)
|
||
|
|
||
|
MP4_OUTPUTFRAMESIZE_VARIABLE = 2, // don't know if any codecs do this
|
||
|
|
||
|
MP4_TYPE_MPEG1_AUDIO = 0x6B,
|
||
|
MP4_TYPE_MPEG2_AUDIO = 0x69,
|
||
|
MP4_TYPE_MPEG2_AAC_MAIN_AUDIO = 0x66,
|
||
|
MP4_TYPE_MPEG2_AAC_LC_AUDIO = 0x67,
|
||
|
MP4_TYPE_MPEG2_AAC_SSR_AUDIO = 0x68,
|
||
|
MP4_TYPE_MPEG4_AUDIO = 0x40,
|
||
|
MP4_TYPE_PRIVATE_AUDIO = 0xC0,
|
||
|
MP4_TYPE_PCM16_LITTLE_ENDIAN_AUDIO = 0xE0,
|
||
|
MP4_TYPE_VORBIS_AUDIO = 0xE1,
|
||
|
MP4_TYPE_AC3_AUDIO = 0xE2,
|
||
|
MP4_TYPE_ALAW_AUDIO = 0xE3,
|
||
|
MP4_TYPE_ULAW_AUDIO = 0xE4,
|
||
|
MP4_TYPE_G723_AUDIO = 0xE5,
|
||
|
MP4_TYPE_PCM16_BIG_ENDIAN_AUDIO = 0xE6,
|
||
|
|
||
|
/* MP4 MPEG-4 Audio types from 14496-3 Table 1.5.1 */
|
||
|
MP4_MPEG4_TYPE_AAC_MAIN_AUDIO = 1,
|
||
|
MP4_MPEG4_TYPE_AAC_LC_AUDIO = 2,
|
||
|
MP4_MPEG4_TYPE_AAC_SSR_AUDIO = 3,
|
||
|
MP4_MPEG4_TYPE_AAC_LTP_AUDIO = 4,
|
||
|
MP4_MPEG4_TYPE_AAC_HE_AUDIO = 5,
|
||
|
MP4_MPEG4_TYPE_AAC_SCALABLE_AUDIO = 6,
|
||
|
MP4_MPEG4_TYPE_CELP_AUDIO = 8,
|
||
|
MP4_MPEG4_TYPE_HVXC_AUDIO = 9,
|
||
|
MP4_MPEG4_TYPE_TTSI_AUDIO = 12,
|
||
|
MP4_MPEG4_TYPE_MAIN_SYNTHETIC_AUDIO = 13,
|
||
|
MP4_MPEG4_TYPE_WAVETABLE_AUDIO = 14,
|
||
|
MP4_MPEG4_TYPE_MIDI_AUDIO = 15,
|
||
|
MP4_MPEG4_TYPE_ALGORITHMIC_FX_AUDIO = 16,
|
||
|
MP4_MPEG4_TYPE_PARAMETRIC_STEREO=29,
|
||
|
MP4_MPEG4_ALS_AUDIO=31,
|
||
|
MP4_MPEG4_LAYER1_AUDIO = 32,
|
||
|
MP4_MPEG4_LAYER2_AUDIO= 33,
|
||
|
MP4_MPEG4_LAYER3_AUDIO= 34,
|
||
|
|
||
|
MP4_MPEG4_SLS_AUDIO=37,
|
||
|
};
|
||
|
|
||
|
class MP4AudioDecoder : public Dispatchable
|
||
|
{
|
||
|
protected:
|
||
|
MP4AudioDecoder() {}
|
||
|
~MP4AudioDecoder() {}
|
||
|
|
||
|
public:
|
||
|
static FOURCC getServiceType() { return WaSvc::MP4AUDIODECODER; }
|
||
|
int Open();
|
||
|
int OpenEx(size_t bits, size_t maxChannels, bool useFloat);
|
||
|
int OpenMP4(MP4FileHandle mp4_file, MP4TrackId mp4_track, size_t output_bits, size_t maxChannels, bool useFloat);
|
||
|
int AudioSpecificConfiguration(void *buffer, size_t buffer_size); // reads ASC block from mp4 file
|
||
|
int GetCurrentBitrate(unsigned int *bitrate);
|
||
|
int OutputFrameSize(size_t *frameSize); // in Frames
|
||
|
int GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample); // can return an error code for "havn't locked to stream yet"
|
||
|
int GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat);
|
||
|
int DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes);
|
||
|
void Flush();
|
||
|
void Close();
|
||
|
const char *GetCodecInfoString();
|
||
|
int CanHandleCodec(const char *codecName);
|
||
|
int CanHandleType(uint8_t type);
|
||
|
int CanHandleMPEG4Type(uint8_t type);
|
||
|
int SetGain(float gain);
|
||
|
int RequireChunks(); // return 1 if your decoder wants to read whole chunks rather than samples
|
||
|
void EndOfStream();
|
||
|
|
||
|
public:
|
||
|
DISPATCH_CODES
|
||
|
{
|
||
|
MPEG4_AUDIO_OPEN = 10,
|
||
|
MPEG4_AUDIO_OPEN_EX = 11,
|
||
|
MPEG4_AUDIO_OPENMP4 = 12,
|
||
|
MPEG4_AUDIO_ASC = 20,
|
||
|
MPEG4_AUDIO_BITRATE = 30,
|
||
|
MPEG4_AUDIO_FRAMESIZE = 40,
|
||
|
MPEG4_AUDIO_OUTPUTINFO = 50,
|
||
|
MPEG4_AUDIO_OUTPUTINFO_EX = 51,
|
||
|
MPEG4_AUDIO_DECODE = 60,
|
||
|
MPEG4_AUDIO_FLUSH = 70,
|
||
|
MPEG4_AUDIO_CLOSE = 80,
|
||
|
MPEG4_AUDIO_CODEC_INFO_STRING = 90,
|
||
|
MPEG4_AUDIO_HANDLES_CODEC = 100,
|
||
|
MPEG4_AUDIO_HANDLES_TYPE = 110,
|
||
|
MPEG4_AUDIO_HANDLES_MPEG4_TYPE = 120,
|
||
|
MPEG4_AUDIO_SET_GAIN=130,
|
||
|
MPEG4_AUDIO_REQUIRE_CHUNKS = 140,
|
||
|
MPEG4_END_OF_STREAM = 150,
|
||
|
};
|
||
|
};
|
||
|
|
||
|
inline int MP4AudioDecoder::Open()
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_OPEN, (int)MP4_FAILURE);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::OpenEx(size_t bits, size_t maxChannels, bool useFloat)
|
||
|
{
|
||
|
void *params[3] = { &bits, &maxChannels, &useFloat};
|
||
|
int retval;
|
||
|
if (_dispatch(MPEG4_AUDIO_OPEN_EX, &retval, params, 3))
|
||
|
return retval;
|
||
|
else
|
||
|
return Open();
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::OpenMP4(MP4FileHandle mp4_file, MP4TrackId mp4_track, size_t output_bits, size_t maxChannels, bool useFloat)
|
||
|
{
|
||
|
void *params[5] = { &mp4_file, &mp4_track, &output_bits, &maxChannels, &useFloat};
|
||
|
int retval;
|
||
|
if (_dispatch(MPEG4_AUDIO_OPENMP4, &retval, params, 5))
|
||
|
return retval;
|
||
|
else
|
||
|
return OpenEx(output_bits, maxChannels, useFloat);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::AudioSpecificConfiguration(void *buffer, size_t buffer_size)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_ASC, (int)MP4_FAILURE, buffer, buffer_size);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::GetCurrentBitrate(unsigned int *bitrate)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_BITRATE, (int)MP4_FAILURE, bitrate);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::OutputFrameSize(size_t *frameSize)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_FRAMESIZE, (int)MP4_FAILURE, frameSize);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_OUTPUTINFO, (int)MP4_FAILURE, sampleRate, channels, bitsPerSample);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *useFloat)
|
||
|
{
|
||
|
void *params[4] = { &sampleRate, &channels, &bitsPerSample, &useFloat};
|
||
|
int retval;
|
||
|
if (_dispatch(MPEG4_AUDIO_OUTPUTINFO_EX, &retval, params, 4))
|
||
|
return retval;
|
||
|
else
|
||
|
{
|
||
|
*useFloat=false;
|
||
|
return GetOutputProperties(sampleRate, channels, bitsPerSample);
|
||
|
}
|
||
|
// return _call(MPEG4_AUDIO_OUTPUTINFO_EX, (int)MP4_FAILURE, sampleRate, channels, bitsPerSample);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_DECODE, (int)MP4_FAILURE, inputBuffer, inputBufferBytes, outputBuffer, outputBufferBytes);
|
||
|
}
|
||
|
|
||
|
inline void MP4AudioDecoder::Flush()
|
||
|
{
|
||
|
_voidcall(MPEG4_AUDIO_FLUSH);
|
||
|
}
|
||
|
inline void MP4AudioDecoder::Close()
|
||
|
{
|
||
|
_voidcall(MPEG4_AUDIO_CLOSE);
|
||
|
}
|
||
|
inline const char *MP4AudioDecoder::GetCodecInfoString()
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_CODEC_INFO_STRING, (const char *)0);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::CanHandleCodec(const char *codecName)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_HANDLES_CODEC, (int)0, codecName);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::CanHandleType(uint8_t type)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_HANDLES_TYPE, (int)0, type);
|
||
|
}
|
||
|
inline int MP4AudioDecoder::CanHandleMPEG4Type(uint8_t type)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, (int)0, type);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::SetGain(float gain)
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_SET_GAIN, (int)MP4_FAILURE, gain);
|
||
|
}
|
||
|
|
||
|
inline int MP4AudioDecoder::RequireChunks()
|
||
|
{
|
||
|
return _call(MPEG4_AUDIO_REQUIRE_CHUNKS, (int)0);
|
||
|
}
|
||
|
|
||
|
inline void MP4AudioDecoder::EndOfStream()
|
||
|
{
|
||
|
_voidcall(MPEG4_END_OF_STREAM);
|
||
|
}
|
||
|
#endif
|