mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 22:45:46 -04:00
Initial community commit
This commit is contained in:
228
Src/mp3-mpg123/mp3_in_mp4.cpp
Normal file
228
Src/mp3-mpg123/mp3_in_mp4.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
// used to decode an MPEG-1 audio object in an MPEG-4 ISO Media file
|
||||
#include "mp3_in_mp4.h"
|
||||
#include "api__mp3-mpg123.h"
|
||||
#include "../nsutil/pcm.h"
|
||||
|
||||
// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
|
||||
static const GUID playbackConfigGroupGUID =
|
||||
{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
|
||||
|
||||
#define FHG_DELAY 529
|
||||
MPEG4_MP3::MPEG4_MP3()
|
||||
{
|
||||
channels = 0;
|
||||
gain = 1;
|
||||
floatingPoint = false;
|
||||
decoder = 0;
|
||||
sample_rate = 0;
|
||||
bits = 16;
|
||||
pregap = FHG_DELAY;
|
||||
}
|
||||
|
||||
MPEG4_MP3::~MPEG4_MP3()
|
||||
{
|
||||
if (decoder) {
|
||||
mpg123_delete(decoder);
|
||||
decoder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int MPEG4_MP3::OpenEx(size_t _bits, size_t _maxChannels, bool useFloat)
|
||||
{
|
||||
_bits = bits;
|
||||
floatingPoint = useFloat;
|
||||
if (floatingPoint)
|
||||
bits = 32;
|
||||
else
|
||||
bits = (int)_bits;
|
||||
|
||||
decoder = mpg123_new(NULL, NULL);
|
||||
long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
|
||||
if (_maxChannels == 1) {
|
||||
flags |= MPG123_FORCE_MONO;
|
||||
}
|
||||
mpg123_param(decoder, MPG123_FLAGS, flags, 0);
|
||||
mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
|
||||
mpg123_open_feed(decoder);
|
||||
return MP4_SUCCESS;
|
||||
}
|
||||
|
||||
const char *MPEG4_MP3::GetCodecInfoString()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MPEG4_MP3::CanHandleCodec(const char *codecName)
|
||||
{
|
||||
if (!lstrcmpA(codecName, "mp4a"))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MPEG4_MP3::CanHandleType(unsigned __int8 type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case MP4_MPEG4_LAYER3_AUDIO:
|
||||
case MP4_MPEG4_LAYER2_AUDIO:
|
||||
case MP4_MPEG4_LAYER1_AUDIO:
|
||||
case MP4_TYPE_MPEG1_AUDIO:
|
||||
case MP4_TYPE_MPEG2_AUDIO:
|
||||
//case MP4_TYPE_MPEG4_AUDIO:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int MPEG4_MP3::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
|
||||
{
|
||||
if (!decoder)
|
||||
return MP4_FAILURE;
|
||||
|
||||
*outputBufferBytes = 0;
|
||||
mpg123_feed(decoder, (unsigned char *)inputBuffer, inputBufferBytes);
|
||||
|
||||
for (;;) {
|
||||
// get the decoded data out
|
||||
size_t pcm_buf_used=0;
|
||||
float decodeBuf[1152*2];
|
||||
int err = mpg123_read(decoder, (unsigned char *)decodeBuf, sizeof(decodeBuf), &pcm_buf_used);
|
||||
|
||||
if (pcm_buf_used) {
|
||||
if (!_UpdateProperties()) {
|
||||
return MP4_FAILURE;
|
||||
}
|
||||
// deal with pregap
|
||||
int numSamples = (int)pcm_buf_used / sizeof(float);
|
||||
int offset = min(numSamples, pregap * channels);
|
||||
numSamples -= offset;
|
||||
pregap -= offset / channels;
|
||||
float *pcm_buf = decodeBuf + offset;
|
||||
|
||||
// convert to destination sample format
|
||||
|
||||
nsutil_pcm_FloatToInt_Interleaved(outputBuffer, pcm_buf, bits, numSamples);
|
||||
|
||||
*outputBufferBytes += numSamples * bits / 8;
|
||||
outputBuffer = (char *)outputBuffer + numSamples * bits / 8;
|
||||
|
||||
return MP4_SUCCESS;
|
||||
} else if (err == MPG123_NEED_MORE) {
|
||||
*outputBufferBytes = 0;
|
||||
return MP4_NEED_MORE_INPUT;
|
||||
} else if (err == MPG123_NEW_FORMAT) {
|
||||
continue;
|
||||
} else if (err == MPG123_OK) {
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return MP4_FAILURE;
|
||||
}
|
||||
return MP4_SUCCESS;
|
||||
}
|
||||
|
||||
bool MPEG4_MP3::_UpdateProperties()
|
||||
{
|
||||
if (decoder && (!channels || !sample_rate)) {
|
||||
long sample_rate = 44100;
|
||||
int channels = 2;
|
||||
int encoding = 0;
|
||||
if (mpg123_getformat(decoder, &sample_rate, &channels, &encoding) == MPG123_OK) {
|
||||
this->channels = channels;
|
||||
this->sample_rate = sample_rate;
|
||||
}
|
||||
}
|
||||
|
||||
return channels && sample_rate;
|
||||
}
|
||||
int MPEG4_MP3::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
|
||||
{
|
||||
if (_UpdateProperties()) {
|
||||
*sampleRate = this->sample_rate;
|
||||
*channels = this->channels;
|
||||
*bitsPerSample = bits;
|
||||
*isFloat = floatingPoint;
|
||||
return MP4_SUCCESS;
|
||||
} else {
|
||||
return MP4_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int MPEG4_MP3::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample)
|
||||
{
|
||||
bool dummy;
|
||||
return GetOutputPropertiesEx(sampleRate, channels, bitsPerSample, &dummy);
|
||||
}
|
||||
|
||||
void MPEG4_MP3::Close()
|
||||
{
|
||||
if (decoder) {
|
||||
mpg123_delete(decoder);
|
||||
decoder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MPEG4_MP3::Flush()
|
||||
{
|
||||
mpg123_open_feed(decoder);
|
||||
pregap = FHG_DELAY;
|
||||
}
|
||||
|
||||
int MPEG4_MP3::SetGain(float _gain)
|
||||
{
|
||||
gain = _gain;
|
||||
return MP4_SUCCESS;
|
||||
}
|
||||
|
||||
int MPEG4_MP3::GetCurrentBitrate(unsigned int *bitrate)
|
||||
{
|
||||
mpg123_frameinfo frameInfo;
|
||||
if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
|
||||
*bitrate = frameInfo.bitrate;
|
||||
return MP4_SUCCESS;
|
||||
} else {
|
||||
return MP4_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int MPEG4_MP3::OutputFrameSize(size_t *frameSize)
|
||||
{
|
||||
if (_UpdateProperties()) {
|
||||
*frameSize = (bits/8) * channels * mpg123_spf(decoder);
|
||||
return MP4_SUCCESS;
|
||||
} else {
|
||||
return MP4_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int MPEG4_MP3::CanHandleMPEG4Type(unsigned __int8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MP4_MPEG4_LAYER1_AUDIO:
|
||||
case MP4_MPEG4_LAYER2_AUDIO:
|
||||
case MP4_MPEG4_LAYER3_AUDIO:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define CBCLASS MPEG4_MP3
|
||||
START_DISPATCH;
|
||||
CB(MPEG4_AUDIO_OPEN_EX, OpenEx)
|
||||
CB(MPEG4_AUDIO_CODEC_INFO_STRING, GetCodecInfoString)
|
||||
CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate)
|
||||
CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize)
|
||||
CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties)
|
||||
CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx)
|
||||
CB(MPEG4_AUDIO_DECODE, DecodeSample)
|
||||
VCB(MPEG4_AUDIO_FLUSH, Flush)
|
||||
VCB(MPEG4_AUDIO_CLOSE, Close)
|
||||
CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec)
|
||||
CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType)
|
||||
CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type)
|
||||
CB(MPEG4_AUDIO_SET_GAIN, SetGain)
|
||||
END_DISPATCH;
|
Reference in New Issue
Block a user