/*
   Run time compatibility for Faad2.5 in Faad2.0 software

This allows you to work around the compile time API changes in FAAD2 between
version 2.0 and 2.5, and so avoid the likes of

  Opening audio decoder: [faad] AAC (MPEG2/4 Advanced Audio Coding)
  mplayer: symbol lookup error: mplayer: undefined symbol: faacDecOpen

Build this with:
	gcc -Wall -O2 -fpic -shared -ldl -o faad-shim.so faad-shim.c -lfaad

Install this with:
	sudo cp faad-shim.so /usr/local/lib/

Use this with
	LD_PRELOAD=/usr/local/lib/faad-shim.so <command>
eg
	LD_PRELOAD=/usr/local/lib/faad-shim.so mplayer MyMusic.mp4

*/

/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
** 
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software 
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** Software using this code must display the following message visibly in or
** on each copy of the software:
** "FAAD2 AAC/HE-AAC/HE-AACv2/DRM decoder (c) Nero AG, www.nero.com"
** in, for example, the about-box or help/startup screen.
**/


typedef void *NeAACDecHandle;
typedef struct NeAACDecConfiguration
{
    unsigned char defObjectType;
    unsigned long defSampleRate;
    unsigned char outputFormat;
    unsigned char downMatrix;
    unsigned char useOldADTSFormat;
    unsigned char dontUpSampleImplicitSBR;
} NeAACDecConfiguration, *NeAACDecConfigurationPtr;
typedef struct NeAACDecFrameInfo
{
    unsigned long bytesconsumed;
    unsigned long samples;
    unsigned char channels;
    unsigned char error;
    unsigned long samplerate;

    /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
    unsigned char sbr;

    /* MPEG-4 ObjectType */
    unsigned char object_type;

    /* AAC header type; MP4 will be signalled as RAW also */
    unsigned char header_type;
    
    /* multichannel configuration */
    unsigned char num_front_channels;
    unsigned char num_side_channels;
    unsigned char num_back_channels;
    unsigned char num_lfe_channels;
    unsigned char channel_position[64];
    
    /* PS: 0: off, 1: on */
    unsigned char ps;
} NeAACDecFrameInfo;
typedef struct mp4AudioSpecificConfig
{
    /* Audio Specific Info */
    unsigned char objectTypeIndex;
    unsigned char samplingFrequencyIndex;
    unsigned long samplingFrequency;
    unsigned char channelsConfiguration;

    /* GA Specific Info */
    unsigned char frameLengthFlag;
    unsigned char dependsOnCoreCoder;
    unsigned short coreCoderDelay;
    unsigned char extensionFlag;
    unsigned char aacSectionDataResilienceFlag;
    unsigned char aacScalefactorDataResilienceFlag;
    unsigned char aacSpectralDataResilienceFlag;
    unsigned char epConfig;

    char sbr_present_flag;
    char forceUpSampling;
    char downSampledSBR;
} mp4AudioSpecificConfig;



char* NeAACDecGetErrorMessage(unsigned char errcode);
unsigned char NeAACDecSetConfiguration(NeAACDecHandle hDecoder,
                                       NeAACDecConfigurationPtr config);
NeAACDecConfigurationPtr NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder);
long NeAACDecInit(NeAACDecHandle hDecoder,
		      unsigned char *buffer,
		      unsigned long buffer_size,
		      unsigned long *samplerate,
		      unsigned char *channels);

char NeAACDecInit2(NeAACDecHandle hDecoder, unsigned char *pBuffer,
		       unsigned long SizeOfDecoderSpecificInfo,
		       unsigned long *samplerate, unsigned char *channels);

char NeAACDecInitDRM(NeAACDecHandle *hDecoder, unsigned long samplerate,
                       unsigned char channels);

void NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame);

NeAACDecHandle NeAACDecOpen(void);

void NeAACDecClose(NeAACDecHandle hDecoder);

void* NeAACDecDecode(NeAACDecHandle hDecoder,
			 NeAACDecFrameInfo *hInfo,
			 unsigned char *buffer,
			 unsigned long buffer_size);

char NeAACDecAudioSpecificConfig(unsigned char *pBuffer,
				     unsigned long buffer_size,
				     mp4AudioSpecificConfig *mp4ASC);




char* faacDecGetErrorMessage(unsigned char errcode) {
	return NeAACDecGetErrorMessage(errcode); }

unsigned char faacDecSetConfiguration(NeAACDecHandle hDecoder, NeAACDecConfigurationPtr config) {
	return NeAACDecSetConfiguration(hDecoder,config); }

NeAACDecConfigurationPtr faacDecGetCurrentConfiguration(NeAACDecHandle hDecoder) {
	return NeAACDecGetCurrentConfiguration(hDecoder); }

long faacDecInit(NeAACDecHandle hDecoder,
		      unsigned char *buffer,
		      unsigned long buffer_size,
		      unsigned long *samplerate,
		      unsigned char *channels) {
	return NeAACDecInit(hDecoder,buffer,buffer_size,samplerate,channels); }

char faacDecInit2(NeAACDecHandle hDecoder, unsigned char *pBuffer,
		       unsigned long SizeOfDecoderSpecificInfo,
		       unsigned long *samplerate, unsigned char *channels) {
	return NeAACDecInit2(hDecoder,pBuffer,SizeOfDecoderSpecificInfo,samplerate,channels); }

char faacDecInitDRM(NeAACDecHandle *hDecoder, unsigned long samplerate,
                       unsigned char channels) {
	return NeAACDecInitDRM(hDecoder,samplerate,channels); }

void faacDecPostSeekReset(NeAACDecHandle hDecoder, long frame) {
	return NeAACDecPostSeekReset(hDecoder,frame); }

NeAACDecHandle faacDecOpen(void) {
	return NeAACDecOpen(); }

void faacDecClose(NeAACDecHandle hDecoder) {
	return NeAACDecClose(hDecoder); }

void* faacDecDecode(NeAACDecHandle hDecoder,
                         NeAACDecFrameInfo *hInfo,
                         unsigned char *buffer,
                         unsigned long buffer_size) {
	return NeAACDecDecode(hDecoder,hInfo,buffer,buffer_size); }

char AudioSpecificConfig(unsigned char *pBuffer,
			     unsigned long buffer_size,
			     mp4AudioSpecificConfig *mp4ASC) {
	return NeAACDecAudioSpecificConfig(pBuffer,buffer_size,mp4ASC); }
