mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-30 17:02:19 +00:00
Improve sceAtracSetData() error handling.
This commit is contained in:
parent
d5a664a0fa
commit
b7a2a92ebe
@ -36,14 +36,17 @@
|
||||
#define ATRAC_ERROR_NO_ATRACID 0x80630003
|
||||
#define ATRAC_ERROR_INVALID_CODECTYPE 0x80630004
|
||||
#define ATRAC_ERROR_BAD_ATRACID 0x80630005
|
||||
#define ATRAC_ERROR_UNKNOWN_FORMAT 0x80630006
|
||||
#define ATRAC_ERROR_WRONG_CODECTYPE 0x80630007
|
||||
#define ATRAC_ERROR_ALL_DATA_LOADED 0x80630009
|
||||
#define ATRAC_ERROR_NO_DATA 0x80630010
|
||||
#define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
|
||||
#define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
|
||||
#define ATRAC_ERROR_NO_DATA 0x80630010
|
||||
#define ATRAC_ERROR_SIZE_TOO_SMALL 0x80630011
|
||||
#define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
|
||||
#define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
|
||||
#define ATRAC_ERROR_ADD_DATA_IS_TOO_BIG 0x80630018
|
||||
#define ATRAC_ERROR_UNSET_PARAM 0x80630021
|
||||
#define ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED 0x80630022
|
||||
#define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
|
||||
#define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
|
||||
#define ATRAC_ERROR_ALL_DATA_DECODED 0x80630024
|
||||
|
||||
#define AT3_MAGIC 0x0270
|
||||
@ -153,7 +156,7 @@ struct Atrac {
|
||||
p.Do(atracID);
|
||||
p.Do(first);
|
||||
p.Do(atracBufSize);
|
||||
p.Do(codeType);
|
||||
p.Do(codecType);
|
||||
|
||||
p.Do(currentSample);
|
||||
p.Do(endSample);
|
||||
@ -190,9 +193,9 @@ struct Atrac {
|
||||
p.DoMarker("Atrac");
|
||||
}
|
||||
|
||||
void Analyze();
|
||||
int Analyze();
|
||||
u32 getDecodePosBySample(int sample) {
|
||||
int atracSamplesPerFrame = (codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
return (u32)(firstSampleoffset + sample / atracSamplesPerFrame * atracBytesPerFrame );
|
||||
}
|
||||
|
||||
@ -237,7 +240,7 @@ struct Atrac {
|
||||
int loopEndSample;
|
||||
int loopNum;
|
||||
|
||||
u32 codeType;
|
||||
u32 codecType;
|
||||
|
||||
InputBuffer first;
|
||||
InputBuffer second;
|
||||
@ -365,7 +368,7 @@ int deleteAtrac(int atracID) {
|
||||
return ATRAC_ERROR_BAD_ATRACID;
|
||||
}
|
||||
|
||||
int getCodecType(int addr) {
|
||||
int getCodecType(u32 addr) {
|
||||
int at3magic = Memory::Read_U16(addr+20);
|
||||
if (at3magic == AT3_MAGIC) {
|
||||
return PSP_MODE_AT_3;
|
||||
@ -375,9 +378,10 @@ int getCodecType(int addr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atrac::Analyze()
|
||||
int Atrac::Analyze()
|
||||
{
|
||||
// reset some values
|
||||
codecType = 0;
|
||||
currentSample = 0;
|
||||
endSample = -1;
|
||||
loopNum = 0;
|
||||
@ -388,13 +392,13 @@ void Atrac::Analyze()
|
||||
decodePos = 0;
|
||||
|
||||
if (first.size < 0x100) {
|
||||
ERROR_LOG(ME, "Atrac buffer very small: %d", first.size);
|
||||
return;
|
||||
ERROR_LOG_REPORT(ME, "Atrac buffer very small: %d", first.size);
|
||||
return ATRAC_ERROR_SIZE_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (!Memory::IsValidAddress(first.addr)) {
|
||||
WARN_LOG(ME, "Atrac buffer at invalid address: %08x-%08x", first.addr, first.size);
|
||||
return;
|
||||
WARN_LOG_REPORT(ME, "Atrac buffer at invalid address: %08x-%08x", first.addr, first.size);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
|
||||
}
|
||||
|
||||
// TODO: Validate stuff.
|
||||
@ -407,7 +411,7 @@ void Atrac::Analyze()
|
||||
|
||||
this->decodeEnd = first.filesize;
|
||||
bool bfoundData = false;
|
||||
while ((first.filesize - offset) >= 8 && !bfoundData) {
|
||||
while (first.filesize >= offset + 8 && !bfoundData) {
|
||||
int chunkMagic = Memory::Read_U32(first.addr + offset);
|
||||
u32 chunkSize = Memory::Read_U32(first.addr + offset + 4);
|
||||
offset += 8;
|
||||
@ -419,11 +423,11 @@ void Atrac::Analyze()
|
||||
if (chunkSize >= 16) {
|
||||
int codeMagic = Memory::Read_U16(first.addr + offset);
|
||||
if (codeMagic == AT3_MAGIC)
|
||||
codeType = PSP_MODE_AT_3;
|
||||
codecType = PSP_MODE_AT_3;
|
||||
else if (codeMagic == AT3_PLUS_MAGIC)
|
||||
codeType = PSP_MODE_AT_3_PLUS;
|
||||
codecType = PSP_MODE_AT_3_PLUS;
|
||||
else
|
||||
codeType = 0;
|
||||
codecType = 0;
|
||||
atracChannels = Memory::Read_U16(first.addr + offset + 2);
|
||||
// int atracSamplerate = Memory::Read_U32(first.addr + offset + 4); ;Should always be 44100Hz
|
||||
int avgBytesPerSec = Memory::Read_U32(first.addr + offset + 8);
|
||||
@ -473,6 +477,11 @@ void Atrac::Analyze()
|
||||
offset += chunkSize;
|
||||
}
|
||||
|
||||
if (codecType == 0) {
|
||||
WARN_LOG_REPORT(ME, "Atrac buffer with unexpected or no magic bytes");
|
||||
return ATRAC_ERROR_UNKNOWN_FORMAT;
|
||||
}
|
||||
|
||||
// set the loopStartSample and loopEndSample by loopinfo
|
||||
if (loopinfoNum > 0) {
|
||||
loopStartSample = loopinfo[0].startSample;
|
||||
@ -482,10 +491,12 @@ void Atrac::Analyze()
|
||||
}
|
||||
|
||||
// if there is no correct endsample, try to guess it
|
||||
if (endSample < 0) {
|
||||
int atracSamplesPerFrame = (codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
if (endSample < 0 && atracBytesPerFrame != 0) {
|
||||
int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
endSample = (first.filesize / atracBytesPerFrame) * atracSamplesPerFrame;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceAtracGetAtracID(int codecType) {
|
||||
@ -495,7 +506,7 @@ u32 sceAtracGetAtracID(int codecType) {
|
||||
}
|
||||
|
||||
Atrac *atrac = new Atrac();
|
||||
atrac->codeType = codecType;
|
||||
atrac->codecType = codecType;
|
||||
int atracID = createAtrac(atrac, codecType);
|
||||
if (atracID < 0) {
|
||||
ERROR_LOG_REPORT(ME, "sceAtracGetAtracID(%i): no free ID", codecType);
|
||||
@ -571,9 +582,9 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int
|
||||
} else {
|
||||
// TODO: This isn't at all right, but at least it makes the music "last" some time.
|
||||
u32 numSamples = 0;
|
||||
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
u32 atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
#ifdef USE_FFMPEG
|
||||
if (atrac->codeType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
|
||||
if (atrac->codecType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
|
||||
int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample;
|
||||
atrac->SeekToSample(forceseekSample);
|
||||
atrac->SeekToSample(atrac->currentSample);
|
||||
@ -752,7 +763,7 @@ u32 sceAtracGetBitrate(int atracID, u32 outBitrateAddr)
|
||||
return -1;
|
||||
} else {
|
||||
atrac->atracBitrate = ( atrac->atracBytesPerFrame * 352800 ) / 1000;
|
||||
if (atrac->codeType == PSP_MODE_AT_3_PLUS)
|
||||
if (atrac->codecType == PSP_MODE_AT_3_PLUS)
|
||||
atrac->atracBitrate = ((atrac->atracBitrate >> 11) + 8) & 0xFFFFFFF0;
|
||||
else
|
||||
atrac->atracBitrate = (atrac->atracBitrate + 511) >> 10;
|
||||
@ -816,7 +827,7 @@ u32 sceAtracGetMaxSample(int atracID, u32 maxSamplesAddr)
|
||||
//return -1;
|
||||
} else {
|
||||
if (Memory::IsValidAddress(maxSamplesAddr)) {
|
||||
int atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
int atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
Memory::Write_U32(atracSamplesPerFrame, maxSamplesAddr);
|
||||
}
|
||||
}
|
||||
@ -851,7 +862,7 @@ u32 sceAtracGetNextSample(int atracID, u32 outNAddr)
|
||||
Memory::Write_U32(0, outNAddr);
|
||||
} else {
|
||||
u32 numSamples = atrac->endSample - atrac->currentSample;
|
||||
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
u32 atracSamplesPerFrame = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
if (numSamples > atracSamplesPerFrame)
|
||||
numSamples = atracSamplesPerFrame;
|
||||
if (Memory::IsValidAddress(outNAddr))
|
||||
@ -948,7 +959,7 @@ u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFirstBuf,
|
||||
sceAtracAddStreamData(atracID, bytesWrittenFirstBuf);
|
||||
atrac->currentSample = sample;
|
||||
#ifdef USE_FFMPEG
|
||||
if (atrac->codeType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
|
||||
if (atrac->codecType == PSP_MODE_AT_3 && atrac->pCodecCtx) {
|
||||
atrac->SeekToSample(sample);
|
||||
} else
|
||||
#endif // USE_FFMPEG
|
||||
@ -1034,7 +1045,7 @@ int __AtracUpdateOutputMode(Atrac *atrac, int wanted_channels) {
|
||||
|
||||
int __AtracSetContext(Atrac *atrac)
|
||||
{
|
||||
if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
|
||||
if (atrac->codecType == PSP_MODE_AT_3_PLUS) {
|
||||
atrac->decoder_context = Atrac3plus_Decoder::OpenContext();
|
||||
return 0;
|
||||
}
|
||||
@ -1101,7 +1112,7 @@ int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize)
|
||||
atrac->CleanStuff();
|
||||
|
||||
|
||||
if (atrac->codeType == PSP_MODE_AT_3) {
|
||||
if (atrac->codecType == PSP_MODE_AT_3) {
|
||||
if (atrac->atracChannels == 1) {
|
||||
WARN_LOG(ME, "This is an atrac3 mono audio");
|
||||
} else {
|
||||
@ -1114,7 +1125,7 @@ int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize)
|
||||
return __AtracSetContext(atrac);
|
||||
#endif // USE_FFMPEG
|
||||
|
||||
} else if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
|
||||
} else if (atrac->codecType == PSP_MODE_AT_3_PLUS) {
|
||||
if (atrac->atracChannels == 1) {
|
||||
WARN_LOG(ME, "This is an atrac3+ mono audio");
|
||||
} else {
|
||||
@ -1171,17 +1182,25 @@ u32 sceAtracSetSecondBuffer(int atracID, u32 secondBuffer, u32 secondBufferSize)
|
||||
|
||||
u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize)
|
||||
{
|
||||
INFO_LOG(ME, "sceAtracSetData(%i, %08x, %08x)", atracID, buffer, bufferSize);
|
||||
Atrac *atrac = getAtrac(atracID);
|
||||
int ret = 0;
|
||||
if (atrac != NULL) {
|
||||
INFO_LOG(ME, "sceAtracSetData(%i, %08x, %08x)", atracID, buffer, bufferSize);
|
||||
atrac->first.addr = buffer;
|
||||
atrac->first.size = bufferSize;
|
||||
atrac->Analyze();
|
||||
atrac->atracOutputChannels = 2;
|
||||
ret = _AtracSetData(atracID, buffer, bufferSize);
|
||||
int ret = atrac->Analyze();
|
||||
if (ret == 0 && atrac->codecType != atracIDTypes[atracID]) {
|
||||
ERROR_LOG(ME, "sceAtracSetData(%i, %08x, %08x): atracID uses different codec type than data", atracID, buffer, bufferSize);
|
||||
ret = ATRAC_ERROR_WRONG_CODECTYPE;
|
||||
}
|
||||
if (ret == 0) {
|
||||
atrac->atracOutputChannels = 2;
|
||||
ret = _AtracSetData(atracID, buffer, bufferSize);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
ERROR_LOG(ME, "sceAtracSetData(%i, %08x, %08x): bad atrac ID", atracID, buffer, bufferSize);
|
||||
return ATRAC_ERROR_BAD_ATRACID;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
|
||||
@ -1191,7 +1210,11 @@ int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
|
||||
Atrac *atrac = new Atrac();
|
||||
atrac->first.addr = buffer;
|
||||
atrac->first.size = bufferSize;
|
||||
atrac->Analyze();
|
||||
int ret = atrac->Analyze();
|
||||
if (ret < 0) {
|
||||
delete atrac;
|
||||
return ret;
|
||||
}
|
||||
atrac->atracOutputChannels = 2;
|
||||
int atracID = createAtrac(atrac, codecType);
|
||||
if (atracID < 0) {
|
||||
@ -1200,7 +1223,7 @@ int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize)
|
||||
return atracID;
|
||||
}
|
||||
INFO_LOG(ME, "%d=sceAtracSetDataAndGetID(%08x, %08x)", atracID, buffer, bufferSize);
|
||||
int ret = _AtracSetData(atracID, buffer, bufferSize, true);
|
||||
ret = _AtracSetData(atracID, buffer, bufferSize, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return atracID;
|
||||
@ -1436,7 +1459,7 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) {
|
||||
context->info.bufferByte = atrac->atracBufSize;
|
||||
context->info.secondBuffer = atrac->second.addr;
|
||||
context->info.secondBufferByte = atrac->second.size;
|
||||
context->info.codec = atrac->codeType;
|
||||
context->info.codec = atrac->codecType;
|
||||
context->info.loopNum = atrac->loopNum;
|
||||
context->info.loopStart = atrac->loopStartSample > 0 ? atrac->loopStartSample : 0;
|
||||
context->info.loopEnd = atrac->loopEndSample > 0 ? atrac->loopEndSample : 0;
|
||||
@ -1453,7 +1476,7 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) {
|
||||
// state 6, lack some data, has loop info
|
||||
context->info.state = 6;
|
||||
}
|
||||
context->info.samplesPerChan = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
context->info.samplesPerChan = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
context->info.sampleSize = atrac->atracBytesPerFrame;
|
||||
context->info.numChan = atrac->atracChannels;
|
||||
context->info.dataOff = atrac->firstSampleoffset;
|
||||
@ -1593,7 +1616,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
|
||||
INFO_LOG(ME, "Channels: %i outputChannels: %i bytesperFrame: %x",
|
||||
atrac->atracChannels, atrac->atracOutputChannels, atrac->atracBytesPerFrame);
|
||||
#ifdef USE_FFMPEG
|
||||
if (atrac->codeType == PSP_MODE_AT_3) {
|
||||
if (atrac->codecType == PSP_MODE_AT_3) {
|
||||
if (atrac->atracChannels == 1) {
|
||||
WARN_LOG(ME, "This is an atrac3 mono audio (low level)");
|
||||
} else {
|
||||
@ -1612,7 +1635,7 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
|
||||
}
|
||||
#endif // USE_FFMPEG
|
||||
|
||||
if (atrac->codeType == PSP_MODE_AT_3_PLUS){
|
||||
if (atrac->codecType == PSP_MODE_AT_3_PLUS){
|
||||
if (atrac->atracChannels == 1) {
|
||||
WARN_LOG(ME, "This is an atrac3+ mono audio (low level)");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user