#include "mp3encoder.h"
#include <string.h>
#include <iostream>

using namespace std;

MP3Encoder::MP3Encoder(const CodecInfo& info, WAVEFORMATEX* format)
    :IAudioEncoder(info)
{
    in_fmt=*format;
    lame_init(&gf);
    gf.silent=1;
    gf.padding_type=2;
    gf.VBR=0;
    gf.in_samplerate=format->nSamplesPerSec;
    gf.num_channels=format->nChannels;
    if (format->nChannels==1)
	gf.mode=3;
    else
	gf.mode=1;
    //int mode;   /* 0,1,2,3 stereo,jstereo,dual channel,mono */

}
MP3Encoder::~MP3Encoder()
{
    Close(0,0,0);
}

int MP3Encoder::SetBitrate(int bitrate)
{
    cerr<<"Setting bit rate to "<<bitrate<<" "<<bitrate/125<<endl;
    gf.brate=bitrate/125;
    return 0;
}

int MP3Encoder::SetQuality(int quality)
{
    gf.quality=quality;
    return 0;
}
struct __attribute__((__packed__)) strf_mp3 
{
        short wID;
        int fdwFlags;
        short  nBlockSize;
        short  nFramesPerBlock;
        short  nCodecDelay;
};

	/* here are some flags pertaining to the above structure */
#define MPEGLAYER3_ID_UNKNOWN            0
#define MPEGLAYER3_ID_MPEG               1
#define MPEGLAYER3_ID_CONSTANTFRAMESIZE  2
#define MPEGLAYER3_FLAG_PADDING_ISO      0x00000000
#define MPEGLAYER3_FLAG_PADDING_ON       0x00000001
#define MPEGLAYER3_FLAG_PADDING_OFF      0x00000002
																	
int MP3Encoder::GetFormatSize()
{
    return 30;
}

int MP3Encoder::GetFormat(void* extension, size_t size)
{
    if(size<30)return -1;
    WAVEFORMATEX wf;
    strf_mp3 mp3extra;
    memcpy(&wf, &in_fmt, 18);
    wf.wFormatTag=0x55;
    wf.nAvgBytesPerSec=gf.brate*125;
    wf.nBlockAlign=1;
    wf.wBitsPerSample=0;
    wf.cbSize=12;
    memcpy(extension, &wf, 18);
    
    lame_init_params(&gf);
    mp3extra.wID             = 1;        //
    mp3extra.fdwFlags        = 2;        // These values
    mp3extra.nBlockSize      = gf.framesize;      // based on an
    mp3extra.nFramesPerBlock = 1;        // old Usenet post!!
    mp3extra.nCodecDelay     = 1393;     //
    memcpy((char*)extension+18, &mp3extra, 12);
													    
    return 0;
}
int MP3Encoder::Start()
{
    lame_init_params(&gf);
    return 0;
}
int MP3Encoder::Convert(const void* in_data, size_t in_size,
			void* out_data, size_t out_size,
			size_t* size_read, size_t* size_written)
{
#warning FIXME 8-bit?
    int result;
    if(in_fmt.nChannels==1)
	result=lame_encode_buffer(&gf, (short*)in_data, (short*)in_data,
				  in_size, (char*)out_data, out_size);
    else
	result=lame_encode_buffer_interleaved(&gf, (short*)in_data,
					      in_size, (char*)out_data, out_size);
    if(result<0)result=0;
    if(size_read)*size_read=in_size;
    if(size_written)*size_written=result;
    return 0;
}

int MP3Encoder::Close(void* out_data, size_t out_size, size_t* size_read)
{
    char buffer[7200];
    cerr<<"MP3EncodeR::Close()"<<endl;
    size_t bytes=lame_encode_finish(&gf, buffer, sizeof(buffer));
    if (out_size<bytes)
	bytes = out_size;
    if (out_data)
	memcpy(out_data, buffer, bytes);
    if (out_data && size_read)
	*size_read = bytes;
    return 0;
}
