#ifndef NULLSOFT_MPEG4AUDIOH #define NULLSOFT_MPEG4AUDIOH #include "../external_dependencies/libmp4v2/mp4.h" #include #include #include 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