obs之lame编码。
#include "Main.h"
#include "../lame/include/lame.h"
const int audioBlockSize = 4; //output is 2 16bit channels
struct AACDataPacket
{
List<BYTE> Packet;
inline void FreeData() {Packet.Clear();}
};
//lame is not lame.. it's godly.
class MP3Encoder : public AudioEncoder
{
lame_global_flags *lgf;
List<BYTE> MP3OutputBuffer;
List<BYTE> header;
DWORD dwMP3MaxSize;
bool bFirstPacket;
UINT outputFrameSize;
UINT curBitRate;
List<DWORD> bufferedTimestamps;
DWORD curEncodeTimestamp;
DWORD frameCounter;
bool bFirstFrame;
public:
MP3Encoder(UINT bitRate)
{
curBitRate = bitRate;
lgf = lame_init();
if(!lgf)
CrashError(TEXT("Unable to open mp3 encoder"));
lame_set_in_samplerate(lgf, 44100);
lame_set_out_samplerate(lgf, 44100);
lame_set_num_channels(lgf, 2);
lame_set_mode(lgf, STEREO);
lame_set_disable_reservoir(lgf, TRUE); //bit reservoir has to be disabled for seamless streaming
lame_set_VBR(lgf, vbr_off);
lame_set_brate(lgf, bitRate);
lame_init_params(lgf);
outputFrameSize = lame_get_framesize(lgf); //1152 usually
dwMP3MaxSize = DWORD(1.25*double(outputFrameSize*audioBlockSize) + 7200.0);
MP3OutputBuffer.SetSize(dwMP3MaxSize+1);
MP3OutputBuffer[0] = 0x2f;
bFirstPacket = true;
Log(TEXT("------------------------------------------"));
Log(TEXT("%s"), GetInfoString().Array());
}
~MP3Encoder()
{
lame_close(lgf);
}
bool Encode(float *input, UINT numInputFrames, DataPacket &packet, DWORD ×tamp)
{
if(bFirstFrame)
{
curEncodeTimestamp = timestamp;
bFirstFrame = false;
}
//------------------------------------------------
UINT lastSampleSize = frameCounter;
frameCounter += numInputFrames;
if(frameCounter > outputFrameSize)
{
frameCounter -= outputFrameSize;
bufferedTimestamps << curEncodeTimestamp;
curEncodeTimestamp = timestamp + ((outputFrameSize-lastSampleSize)*10/441);
}
int framenum1 = lame_get_frameNum(lgf);
int ret = lame_encode_buffer_interleaved_ieee_float(lgf, (float*)input, numInputFrames, MP3OutputBuffer.Array()+1, dwMP3MaxSize);
int framesEncoded = lame_get_frameNum(lgf)-framenum1;
if(ret < 0)
{
AppWarning(TEXT("MP3 encode failed"));
return false;
}
if(ret > 0)
{
if(bFirstPacket)
{
header.CopyArray(MP3OutputBuffer.Array(), ret);
bFirstPacket = false;
ret = 0;
}
else
{
packet.lpPacket = MP3OutputBuffer.Array();
packet.size = ret+1;
timestamp = bufferedTimestamps[0];
bufferedTimestamps.Remove(0);
}
}
return ret > 0;
}
UINT GetFrameSize() const
{
return outputFrameSize;
}
void GetHeaders(DataPacket &packet)
{
packet.lpPacket = header.Array();
packet.size = header.Num();
OSDebugOut(TEXT("testing, 123\r\n"));
}
int GetBitRate() const {return curBitRate;}
CTSTR GetCodec() const {return TEXT("MP3");}
String GetInfoString() const
{
String strInfo;
strInfo << TEXT("Audio Encoding: MP3") <<
TEXT("\r\n bitrate: ") << IntString(curBitRate);
return strInfo;
}
};
AudioEncoder* CreateMP3Encoder(UINT bitRate)
{
return new MP3Encoder(bitRate);
}