From 20379772921944cdec03ebbb074cc93892f07a3f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 17:51:25 -0700 Subject: [PATCH 01/13] Revert compatibility flag for GTA Music Hack. This reverts commit eb4ca0cf81b74c842eab7a3ee6f8934abcef50bd. --- Core/Compatibility.cpp | 1 - Core/Compatibility.h | 1 - Core/HLE/sceAtrac.cpp | 76 +++++++----------------------------------- assets/compat.ini | 49 --------------------------- 4 files changed, 12 insertions(+), 115 deletions(-) diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 6be33200bf..c5744afc41 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -42,5 +42,4 @@ void Compatibility::Clear() { void Compatibility::LoadIniSection(IniFile &iniFile, std::string section) { iniFile.Get(section.c_str(), "NoDepthRounding", &flags_.NoDepthRounding, flags_.NoDepthRounding); iniFile.Get(section.c_str(), "PixelDepthRounding", &flags_.PixelDepthRounding, flags_.PixelDepthRounding); - iniFile.Get(section.c_str(), "GTAMusicFix", &flags_.GTAMusicFix, flags_.GTAMusicFix); } diff --git a/Core/Compatibility.h b/Core/Compatibility.h index a5a3a7fa07..0a7d3c64b4 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -47,7 +47,6 @@ struct CompatFlags { bool NoDepthRounding; bool PixelDepthRounding; - bool GTAMusicFix; }; class IniFile; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6861010417..9b37f90961 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -17,16 +17,13 @@ #include -#include "Core/CoreParameter.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" #include "Core/CoreTiming.h" -#include "Core/Compatibility.h" #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/Config.h" -#include "Core/System.h" #include "Core/Debugger/Breakpoints.h" #include "Core/HW/MediaEngine.h" #include "Core/HW/BufferQueue.h" @@ -335,12 +332,6 @@ struct Atrac { } void SeekToSample(int sample) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - s64 seek_pos = (s64)sample; - av_seek_frame(pFormatCtx, audio_stream_index, seek_pos, 0); - return; - } - const u32 atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); // Discard any pending packet data. @@ -403,19 +394,11 @@ struct Atrac { packet->size = 0; if (FillPacket()) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - if (packet->size >= needed) { - memcpy(tempPacket.data + initialSize, packet->data, needed); - packet->size -= needed; - packet->data += needed; - } - } else { - int to_copy = packet->size >= needed ? needed : packet->size; - memcpy(tempPacket.data + initialSize, packet->data, to_copy); - packet->size -= to_copy; - packet->data += to_copy; - tempPacket.size = initialSize + to_copy; - } + int to_copy = packet->size >= needed ? needed : packet->size; + memcpy(tempPacket.data + initialSize, packet->data, to_copy); + packet->size -= to_copy; + packet->data += to_copy; + tempPacket.size = initialSize + to_copy; } else { tempPacket.size = initialSize; } @@ -893,28 +876,17 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 // It seems like the PSP aligns the sample position to 0x800...? int offsetSamples = atrac->firstSampleoffset + firstOffsetExtra; int skipSamples = 0; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - skipSamples = atrac->currentSample == 0 ? offsetSamples : 0; - } u32 maxSamples = atrac->endSample - atrac->currentSample; u32 unalignedSamples = (offsetSamples + atrac->currentSample) % atracSamplesPerFrame; if (unalignedSamples != 0) { // We're off alignment, possibly due to a loop. Force it back on. maxSamples = atracSamplesPerFrame - unalignedSamples; - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - skipSamples = unalignedSamples; - } + skipSamples = unalignedSamples; } #ifdef USE_FFMPEG if (!atrac->failedDecode && (atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample; - atrac->SeekToSample(forceseekSample); - atrac->SeekToSample(atrac->currentSample == 0 ? 0 : atrac->currentSample + offsetSamples); - } else { - atrac->SeekToSample(atrac->currentSample); - } + atrac->SeekToSample(atrac->currentSample); AtracDecodeResult res = ATDECODE_FEEDME; while (atrac->FillPacket()) { @@ -990,11 +962,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int finishFlag = 0; if (atrac->loopNum != 0 && (atrac->currentSample > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = 0; - } else { - atrac->SeekToSample(atrac->loopStartSample); - } + atrac->SeekToSample(atrac->loopStartSample); if (atrac->loopNum > 0) atrac->loopNum --; } else if (atrac->currentSample >= atrac->endSample || @@ -1344,9 +1312,7 @@ static u32 sceAtracGetStreamDataInfo(int atracID, u32 writeAddr, u32 writableByt // Reset temp buf for adding more stream data and set full filled buffer. atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->atracBufSize); } else { - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); - } + atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); } atrac->first.offset = 0; @@ -1388,18 +1354,13 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi INFO_LOG(ME, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); if (bytesWrittenFirstBuf > 0) sceAtracAddStreamData(atracID, bytesWrittenFirstBuf); - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = sample; - } #ifdef USE_FFMPEG if ((atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { atrac->SeekToSample(sample); } else #endif // USE_FFMPEG { - if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = sample; - } + atrac->currentSample = sample; atrac->decodePos = atrac->getDecodePosBySample(sample); } } @@ -2187,13 +2148,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo } int numSamples = 0; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - int forceseekSample = 0x200000; - atrac->SeekToSample(forceseekSample); - atrac->SeekToSample(atrac->currentSample); - } else { - atrac->ForceSeekToSample(atrac->currentSample); - } + atrac->ForceSeekToSample(atrac->currentSample); if (!atrac->failedDecode) { AtracDecodeResult res; @@ -2222,18 +2177,11 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo atrac->currentSample += numSamples; numSamples = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr); - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->SeekToSample(atrac->currentSample); - } if (atrac->bufferPos >= atrac->first.size) { atrac->first.writableBytes = atrac->atracBytesPerFrame; atrac->first.size = atrac->firstSampleoffset; - if (PSP_CoreParameter().compat.flags().GTAMusicFix) { - atrac->currentSample = 0; - } else { - atrac->ForceSeekToSample(0); - } + atrac->ForceSeekToSample(0); } else atrac->first.writableBytes = 0; diff --git a/assets/compat.ini b/assets/compat.ini index 155751c110..518b1e25ec 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -73,52 +73,3 @@ PixelDepthRounding = true PixelDepthRounding = true [ULJS00454] PixelDepthRounding = true - - -# GTA audio issues -# These games stream their radio stations from disc as giant audio files. They seek into -# the correct position. Our ATRAC3 module (sceAtrac) implementation is still not very accurate -# and needs some special handling for this to work correctly, for unknown reasons. - -# GTAMusicFix removes the effect of pull #6976, which fixed many games but broke GTA. -# Issue #7863 has some more information. - -# GTA Liberty City Stories -[ULUS10041] -GTAMusicFix = true -[ULES00151] -GTAMusicFix = true -[ULJM05255] -GTAMusicFix = true -[ULJM05359] -GTAMusicFix = true -[ULJM05885] -GTAMusicFix = true -[NPJH50825] -GTAMusicFix = true - -# GTA Vice City Stories -[ULES00502] -GTAMusicFix = true -[ULUS10160] -GTAMusicFix = true -[ULJM05297] -GTAMusicFix = true -[ULJM05395] -GTAMusicFix = true -[ULJM05884] -GTAMusicFix = true -[NPJH50827] -GTAMusicFix = true - -# GTA Chinatown Wars -[ULUS10490] -GTAMusicFix = true -[ULES01347] -GTAMusicFix = true -[ULJM05604] -GTAMusicFix = true -[ULJM05804] -GTAMusicFix = true -[NPJH00138] -GTAMusicFix = true From 7d0dd0b94a46d56c41b2772a54a5c303801db087 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Sep 2015 10:15:46 -0700 Subject: [PATCH 02/13] Atrac: Stop using avio/avformat entirely. Probably breaks AA3 support at this point... --- Core/HLE/sceAtrac.cpp | 171 +++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 102 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 9b37f90961..e04a9a5e46 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -137,13 +137,11 @@ struct Atrac { memset(&first, 0, sizeof(first)); memset(&second, 0, sizeof(second)); #ifdef USE_FFMPEG - pFormatCtx = nullptr; - pAVIOCtx = nullptr; + pCodec = nullptr; pCodecCtx = nullptr; pSwrCtx = nullptr; pFrame = nullptr; packet = nullptr; - audio_stream_index = 0; #endif // USE_FFMPEG atracContext = 0; } @@ -234,6 +232,12 @@ struct Atrac { return (u32)(firstSampleoffset + sample / atracSamplesPerFrame * atracBytesPerFrame ); } + u32 getFileOffsetBySample(int sample) const { + int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); + // This matches where ffmpeg was getting the packets, but it's not clear why the first atracBytesPerFrame is there... + return (u32)(dataOff + atracBytesPerFrame + (sample + atracSamplesPerFrame - 1) / atracSamplesPerFrame * atracBytesPerFrame); + } + int getRemainFrames() const { // games would like to add atrac data when it wants. // Do not try to guess when it want to add data. @@ -288,32 +292,28 @@ struct Atrac { PSPPointer atracContext; #ifdef USE_FFMPEG - AVFormatContext *pFormatCtx; - AVIOContext *pAVIOCtx; + const AVCodec *pCodec; AVCodecContext *pCodecCtx; SwrContext *pSwrCtx; AVFrame *pFrame; AVPacket *packet; - int audio_stream_index; void ReleaseFFMPEGContext() { if (pFrame) av_free(pFrame); - if (pAVIOCtx && pAVIOCtx->buffer) - av_free(pAVIOCtx->buffer); - if (pAVIOCtx) - av_free(pAVIOCtx); if (pSwrCtx) swr_free(&pSwrCtx); + if (pCodecCtx && pCodecCtx->extradata) { + delete [] pCodecCtx->extradata; + pCodecCtx->extradata = nullptr; + pCodecCtx->extradata_size = 0; + } if (pCodecCtx) avcodec_close(pCodecCtx); - if (pFormatCtx) - avformat_close_input(&pFormatCtx); if (packet) av_free_packet(packet); delete packet; - pFormatCtx = nullptr; - pAVIOCtx = nullptr; + pCodec = nullptr; pCodecCtx = nullptr; pSwrCtx = nullptr; pFrame = nullptr; @@ -321,8 +321,6 @@ struct Atrac { } void ForceSeekToSample(int sample) { - av_seek_frame(pFormatCtx, audio_stream_index, sample + 0x200000, 0); - av_seek_frame(pFormatCtx, audio_stream_index, sample, 0); avcodec_flush_buffers(pCodecCtx); // Discard any pending packet data. @@ -345,19 +343,6 @@ struct Atrac { int seekFrame = sample + offsetSamples - unalignedSamples; if (sample != currentSample) { - // "Seeking" by reading frames seems to work much better. - av_seek_frame(pFormatCtx, audio_stream_index, 0, AVSEEK_FLAG_BACKWARD); - avcodec_flush_buffers(pCodecCtx); - - for (int i = 0; i < seekFrame; i += atracSamplesPerFrame) { - while (FillPacket() && DecodePacket() == ATDECODE_FEEDME) { - continue; - } - } - } else { - // For some reason, if we skip seeking, we get the wrong amount of data. - // (even without flushing the packet...) - av_seek_frame(pFormatCtx, audio_stream_index, seekFrame, 0); avcodec_flush_buffers(pCodecCtx); } currentSample = sample; @@ -367,55 +352,33 @@ struct Atrac { if (packet->size > 0) { return true; } - do { - // This is double-free safe, so we just call it before each read and at the end. - av_free_packet(packet); - if (av_read_frame(pFormatCtx, packet) < 0) { - return false; - } - // We keep reading until we get the right stream index. - } while (packet->stream_index != audio_stream_index); + + u32 off = getFileOffsetBySample(currentSample); + if (off < first.filesize) { + av_init_packet(packet); + packet->data = data_buf + off; + packet->size = atracBytesPerFrame; + packet->pos = off; + bufferPos = off + atracBytesPerFrame; + } else { + av_init_packet(packet); + packet->data = data_buf + dataOff; + packet->size = atracBytesPerFrame; + packet->pos = dataOff; + bufferPos = dataOff + atracBytesPerFrame; + } return true; } AtracDecodeResult DecodePacket() { - AVPacket tempPacket; - AVPacket *decodePacket = packet; - if (packet->size < (int)atracBytesPerFrame) { - // Whoops, we have a packet that is smaller than a frame. Let's meld a new one. - u32 initialSize = packet->size; - int needed = atracBytesPerFrame - initialSize; - av_init_packet(&tempPacket); - av_copy_packet(&tempPacket, packet); - av_grow_packet(&tempPacket, needed); - - // Okay, we're "out of data", let's get more. - packet->size = 0; - - if (FillPacket()) { - int to_copy = packet->size >= needed ? needed : packet->size; - memcpy(tempPacket.data + initialSize, packet->data, to_copy); - packet->size -= to_copy; - packet->data += to_copy; - tempPacket.size = initialSize + to_copy; - } else { - tempPacket.size = initialSize; - } - decodePacket = &tempPacket; - } - int got_frame = 0; - int bytes_read = avcodec_decode_audio4(pCodecCtx, pFrame, &got_frame, decodePacket); - if (packet != decodePacket) { - av_free_packet(&tempPacket); - } + int bytes_read = avcodec_decode_audio4(pCodecCtx, pFrame, &got_frame, packet); + av_free_packet(packet); if (bytes_read == AVERROR_PATCHWELCOME) { ERROR_LOG(ME, "Unsupported feature in ATRAC audio."); // Let's try the next packet. - if (packet == decodePacket) { - packet->size = 0; - } + packet->size = 0; // TODO: Or actually, should we return a blank frame and pretend it worked? return ATDECODE_FEEDME; } else if (bytes_read < 0) { @@ -424,10 +387,6 @@ struct Atrac { return ATDECODE_FAILED; } - if (packet == decodePacket) { - packet->size -= bytes_read; - packet->data += bytes_read; - } return got_frame ? ATDECODE_GOTFRAME : ATDECODE_FEEDME; } #endif // USE_FFMPEG @@ -753,6 +712,7 @@ int Atrac::AnalyzeAA3() { atracBytesPerFrame = (codecParams & 0x03FF) * 8; atracBitrate = at3SampleRates[(codecParams >> 13) & 7] * atracBytesPerFrame * 8 / 1024; atracChannels = 2; + // TODO: "extradata"? break; case 1: codecType = PSP_MODE_AT_3_PLUS; @@ -769,6 +729,7 @@ int Atrac::AnalyzeAA3() { return ATRAC_ERROR_AA3_INVALID_DATA; } + // TODO: Wrong, probably? Need to set after "EA3" header. dataOff = 0; firstSampleoffset = 0; if (endSample < 0 && atracBytesPerFrame != 0) { @@ -1444,49 +1405,54 @@ int __AtracSetContext(Atrac *atrac) { u8* tempbuf = (u8*)av_malloc(atrac->atracBufSize); - atrac->pFormatCtx = avformat_alloc_context(); - atrac->pAVIOCtx = avio_alloc_context(tempbuf, atrac->atracBufSize, 0, (void*)atrac, _AtracReadbuffer, NULL, _AtracSeekbuffer); - atrac->pFormatCtx->pb = atrac->pAVIOCtx; - - int ret; - // Load audio buffer - if((ret = avformat_open_input((AVFormatContext**)&atrac->pFormatCtx, NULL, NULL, NULL)) != 0) { - ERROR_LOG(ME, "avformat_open_input: Cannot open input %d", ret); - // TODO: This is not exactly correct, but if the header is right and there's not enough data - // (which is likely the case here), this is the correct error. - return ATRAC_ERROR_ALL_DATA_DECODED; - } - - if((ret = avformat_find_stream_info(atrac->pFormatCtx, NULL)) < 0) { - ERROR_LOG(ME, "avformat_find_stream_info: Cannot find stream information %d", ret); + AVCodecID ff_codec; + if (atrac->codecType == PSP_MODE_AT_3) { + ff_codec = AV_CODEC_ID_ATRAC3; + } else if (atrac->codecType == PSP_MODE_AT_3_PLUS) { + ff_codec = AV_CODEC_ID_ATRAC3P; + } else { + ERROR_LOG_REPORT(ME, "Unexpected codec type %d", atrac->codecType); return -1; } - AVCodec *pCodec; - // select the audio stream - ret = av_find_best_stream(atrac->pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0); - if (ret < 0) { - if (ret == AVERROR_DECODER_NOT_FOUND) { - ERROR_LOG(HLE, "av_find_best_stream: No appropriate decoder found"); - } else { - ERROR_LOG(HLE, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret); - } - return -1; + atrac->pCodec = avcodec_find_decoder(ff_codec); + atrac->pCodecCtx = avcodec_alloc_context3(atrac->pCodec); + + if (atrac->codecType == PSP_MODE_AT_3) { + // For ATRAC3, we need the "extradata" in the RIFF header. + // TODO: Fix, TODO dealloc, etc. + atrac->pCodecCtx->extradata = new u8[14]; + atrac->pCodecCtx->extradata_size = 14; + // TODO: These are common values, but this ignores the "joint stereo" flag. + memset(atrac->pCodecCtx->extradata, 0, 14); + atrac->pCodecCtx->extradata[0] = 1; + atrac->pCodecCtx->extradata[3] = 0x10; + atrac->pCodecCtx->extradata[10] = 1; } - atrac->audio_stream_index = ret; - atrac->pCodecCtx = atrac->pFormatCtx->streams[atrac->audio_stream_index]->codec; // Appears we need to force mono in some cases. (See CPkmn's comments in issue #4248) - if (atrac->atracChannels == 1) + if (atrac->atracChannels == 1) { + atrac->pCodecCtx->channels = 1; atrac->pCodecCtx->channel_layout = AV_CH_LAYOUT_MONO; + } else if (atrac->atracChannels == 2) { + atrac->pCodecCtx->channels = 2; + atrac->pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; + } else { + ERROR_LOG_REPORT(ME, "Unexpected channel count %d", atrac->atracChannels); + return -1; + } + // Explicitly set the block_align value (needed by newer FFmpeg versions, see #5772.) if (atrac->pCodecCtx->block_align == 0) { atrac->pCodecCtx->block_align = atrac->atracBytesPerFrame; } + // Only one supported, it seems? + atrac->pCodecCtx->sample_rate = 44100; atrac->pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16; - if ((ret = avcodec_open2(atrac->pCodecCtx, pCodec, NULL)) < 0) { + int ret; + if ((ret = avcodec_open2(atrac->pCodecCtx, atrac->pCodec, NULL)) < 0) { ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret); return -1; } @@ -2097,6 +2063,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { atrac->data_buf = new u8[atrac->first.filesize]; memcpy(atrac->data_buf, at3Header, headersize); atrac->currentSample = 0; + // TODO: Check failure? __AtracSetContext(atrac); return 0; } From 27a10bc49fb6aeab9f71eaaa324b171ef222f57b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Sep 2015 10:33:46 -0700 Subject: [PATCH 03/13] Atrac: Fix AA3 dataOff value. Note: will still be wrong in savestates... --- Core/HLE/sceAtrac.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index e04a9a5e46..ee438c4c6b 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -729,8 +729,7 @@ int Atrac::AnalyzeAA3() { return ATRAC_ERROR_AA3_INVALID_DATA; } - // TODO: Wrong, probably? Need to set after "EA3" header. - dataOff = 0; + dataOff = 10 + tagSize + 96; firstSampleoffset = 0; if (endSample < 0 && atracBytesPerFrame != 0) { int atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); From 5174f7df697733ef0f5a401cb28f172d36e5d2ca Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Sep 2015 10:52:41 -0700 Subject: [PATCH 04/13] Atrac: Read in the jointStereo flag for ATRAC3. --- Core/HLE/sceAtrac.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index ee438c4c6b..2b357affb9 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -130,7 +130,7 @@ struct AtracLoopInfo { struct Atrac { Atrac() : atracID(-1), data_buf(0), decodePos(0), decodeEnd(0), bufferPos(0), atracChannels(0),atracOutputChannels(2), - atracBitrate(64), atracBytesPerFrame(0), atracBufSize(0), + atracBitrate(64), atracBytesPerFrame(0), atracBufSize(0), jointStereo(0), currentSample(0), endSample(0), firstSampleoffset(0), dataOff(0), loopinfoNum(0), loopStartSample(-1), loopEndSample(-1), loopNum(0), failedDecode(false), resetBuffer(false), codecType(0) { @@ -164,12 +164,15 @@ struct Atrac { } void DoState(PointerWrap &p) { - auto s = p.Section("Atrac", 1, 4); + auto s = p.Section("Atrac", 1, 5); if (!s) return; p.Do(atracChannels); p.Do(atracOutputChannels); + if (s >= 5) { + p.Do(jointStereo); + } p.Do(atracID); p.Do(first); @@ -267,6 +270,7 @@ struct Atrac { u32 atracBitrate; u16 atracBytesPerFrame; u32 atracBufSize; + int jointStereo; int currentSample; int endSample; @@ -607,6 +611,12 @@ int Atrac::Analyze() { } // TODO: There are some format specific bytes here which seem to have fixed values? + // Probably don't need them. + + if (at3fmt->fmtTag == AT3_MAGIC) { + // This is the offset to the jointStereo field. + jointStereo = Memory::Read_U32(first.addr + offset + 24); + } } break; case FACT_CHUNK_MAGIC: @@ -712,7 +722,7 @@ int Atrac::AnalyzeAA3() { atracBytesPerFrame = (codecParams & 0x03FF) * 8; atracBitrate = at3SampleRates[(codecParams >> 13) & 7] * atracBytesPerFrame * 8 / 1024; atracChannels = 2; - // TODO: "extradata"? + jointStereo = (codecParams >> 17) & 1; break; case 1: codecType = PSP_MODE_AT_3_PLUS; @@ -1419,13 +1429,16 @@ int __AtracSetContext(Atrac *atrac) { if (atrac->codecType == PSP_MODE_AT_3) { // For ATRAC3, we need the "extradata" in the RIFF header. - // TODO: Fix, TODO dealloc, etc. atrac->pCodecCtx->extradata = new u8[14]; atrac->pCodecCtx->extradata_size = 14; - // TODO: These are common values, but this ignores the "joint stereo" flag. memset(atrac->pCodecCtx->extradata, 0, 14); + + // We don't pull this from the RIFF so that we can support OMA also. + // The only thing that changes are the jointStereo values. atrac->pCodecCtx->extradata[0] = 1; atrac->pCodecCtx->extradata[3] = 0x10; + atrac->pCodecCtx->extradata[6] = atrac->jointStereo; + atrac->pCodecCtx->extradata[8] = atrac->jointStereo; atrac->pCodecCtx->extradata[10] = 1; } From 6420b679d431598f75f1b02cbcf9990b618b13f6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Sep 2015 11:00:27 -0700 Subject: [PATCH 05/13] Atrac: Split out low-level packet handling. So we don't have the hack in the other code at all. --- Core/HLE/sceAtrac.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 2b357affb9..c9c0cc7546 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -263,6 +263,7 @@ struct Atrac { u32 decodePos; u32 decodeEnd; + // Used only by low-level decoding. u32 bufferPos; u16 atracChannels; @@ -353,28 +354,34 @@ struct Atrac { } bool FillPacket() { - if (packet->size > 0) { - return true; - } - u32 off = getFileOffsetBySample(currentSample); if (off < first.filesize) { av_init_packet(packet); packet->data = data_buf + off; packet->size = atracBytesPerFrame; packet->pos = off; - bufferPos = off + atracBytesPerFrame; + + return true; } else { - av_init_packet(packet); - packet->data = data_buf + dataOff; - packet->size = atracBytesPerFrame; - packet->pos = dataOff; - bufferPos = dataOff + atracBytesPerFrame; + return false; } return true; } + bool FillLowLevelPacket() { + av_init_packet(packet); + if (bufferPos < (u32)dataOff) { + bufferPos = dataOff; + } + + packet->data = data_buf + bufferPos; + packet->size = atracBytesPerFrame; + packet->pos = bufferPos; + bufferPos += atracBytesPerFrame; + return true; + } + AtracDecodeResult DecodePacket() { int got_frame = 0; int bytes_read = avcodec_decode_audio4(pCodecCtx, pFrame, &got_frame, packet); @@ -2131,7 +2138,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo if (!atrac->failedDecode) { AtracDecodeResult res; - while (atrac->FillPacket()) { + while (atrac->FillLowLevelPacket()) { res = atrac->DecodePacket(); if (res == ATDECODE_FAILED) { break; @@ -2161,6 +2168,7 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo atrac->first.writableBytes = atrac->atracBytesPerFrame; atrac->first.size = atrac->firstSampleoffset; atrac->ForceSeekToSample(0); + atrac->bufferPos = atrac->dataOff; } else atrac->first.writableBytes = 0; From 310aa6ed472ca60ba4d741cc04553efbd758b033 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 27 Sep 2015 11:03:22 -0700 Subject: [PATCH 06/13] Atrac: Remove avio helpers. --- Core/HLE/sceAtrac.cpp | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index c9c0cc7546..8b67035f23 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1344,44 +1344,6 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return 0; } -#ifdef USE_FFMPEG -static int _AtracReadbuffer(void *opaque, uint8_t *buf, int buf_size) { - Atrac *atrac = (Atrac *)opaque; - if (atrac->bufferPos > atrac->first.filesize) - return -1; - int size = std::min((int)atrac->atracBufSize, buf_size); - size = std::max(std::min(((int)atrac->first.size - (int)atrac->bufferPos), size), 0); - if (size > 0) - memcpy(buf, atrac->data_buf + atrac->bufferPos, size); - atrac->bufferPos += size; - return size; -} - -static int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence) { - Atrac *atrac = (Atrac*)opaque; - if (offset > atrac->first.filesize) - return -1; - - switch (whence) { - case SEEK_SET: - atrac->bufferPos = (u32)offset; - break; - case SEEK_CUR: - atrac->bufferPos += (u32)offset; - break; - case SEEK_END: - atrac->bufferPos = atrac->first.filesize - (u32)offset; - break; -#ifdef USE_FFMPEG - case AVSEEK_SIZE: - return atrac->first.filesize; -#endif - } - return atrac->bufferPos; -} - -#endif // USE_FFMPEG - #ifdef USE_FFMPEG static int __AtracUpdateOutputMode(Atrac *atrac, int wanted_channels) { if (atrac->pSwrCtx && atrac->atracOutputChannels == wanted_channels) @@ -1532,7 +1494,6 @@ static int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize) { return __AtracSetContext(atrac); } - return 0; } From 5177f16c8df36847fcd8216f25f98278ec5aaaf0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 18:12:29 -0700 Subject: [PATCH 07/13] Atrac: Use constants for the states, more clarity. --- Core/HLE/sceAtrac.cpp | 8 ++++---- Core/HLE/sceAtrac.h | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 8b67035f23..12c33d0b76 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1903,16 +1903,16 @@ void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) { // TODO: Should we just keep this in PSP ram then, or something? } else if (!atrac->data_buf) { // State 1, no buffer yet. - context->info.state = 1; + context->info.state = ATRAC_STATUS_NO_DATA; } else if (atrac->first.size >= atrac->first.filesize) { // state 2, all data loaded - context->info.state = 2; + context->info.state = ATRAC_STATUS_ALL_DATA_LOADED; } else if (atrac->loopinfoNum == 0) { // state 3, lack some data, no loop info - context->info.state = 3; + context->info.state = ATRAC_STATUS_STREAMED_WITHOUT_LOOP; } else { // state 6, lack some data, has loop info - context->info.state = 6; + context->info.state = ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER; } context->info.samplesPerChan = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); context->info.sampleSize = atrac->atracBytesPerFrame; diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index aa4d2789c3..41d3b62a0f 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -26,6 +26,26 @@ void __AtracInit(); void __AtracDoState(PointerWrap &p); void __AtracShutdown(); +enum AtracStatus : u8 { + ATRAC_STATUS_NO_DATA = 1, + ATRAC_STATUS_ALL_DATA_LOADED = 2, + ATRAC_STATUS_HALFWAY_BUFFER = 3, + ATRAC_STATUS_STREAMED_WITHOUT_LOOP = 4, + ATRAC_STATUS_STREAMED_LOOP_FROM_END = 5, + // This means there's additional audio after the loop. + // i.e. ~~before loop~~ [ ~~this part loops~~ ] ~~after loop~~ + // The "fork in the road" means a second buffer is needed for the second path. + ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER = 6, + ATRAC_STATUS_LOW_LEVEL = 8, + ATRAC_STATUS_FOR_SCESAS = 16, +}; + +#if COMMON_LITTLE_ENDIAN +typedef AtracStatus AtracStatus_le; +#else +typedef swap_struct_t > AtracStatus_le; +#endif + typedef struct { u32_le decodePos; // 0 @@ -36,7 +56,7 @@ typedef struct char numFrame; // 20 // 2: all the stream data on the buffer // 6: looping -> second buffer needed - char state; // 21 + AtracStatus_le state; // 21 char unk22; char numChan; // 23 u16_le sampleSize; // 24 From b47458eabb6ec348e2c12cf766999a9c5d4a8e77 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 18:14:23 -0700 Subject: [PATCH 08/13] Atrac: fix loading certain savestates. Some worked with it that high, but others not. --- Core/HLE/sceAtrac.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 12c33d0b76..c9c7e49c24 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -188,7 +188,7 @@ struct Atrac { dataOff = firstSampleoffset; } - u32 has_data_buf = data_buf != NULL; + u32 has_data_buf = data_buf != nullptr; p.Do(has_data_buf); if (has_data_buf) { if (p.mode == p.MODE_READ) { @@ -198,9 +198,6 @@ struct Atrac { } p.DoArray(data_buf, first.filesize); } - if (p.mode == p.MODE_READ && data_buf != NULL) { - __AtracSetContext(this); - } p.Do(second); p.Do(decodePos); @@ -222,6 +219,11 @@ struct Atrac { p.Do(loopNum); p.Do(atracContext); + + // Make sure to do this late; it depends on things like atracBytesPerFrame. + if (p.mode == p.MODE_READ && data_buf != nullptr) { + __AtracSetContext(this); + } if (s >= 2) p.Do(resetBuffer); From 7d328766103cf366436c539dd9a8104e37135d2f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 18:27:35 -0700 Subject: [PATCH 09/13] Atrac: Cleanup FFmpeg context ptr management. --- Core/HLE/sceAtrac.cpp | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index c9c7e49c24..79399c4752 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -137,7 +137,6 @@ struct Atrac { memset(&first, 0, sizeof(first)); memset(&second, 0, sizeof(second)); #ifdef USE_FFMPEG - pCodec = nullptr; pCodecCtx = nullptr; pSwrCtx = nullptr; pFrame = nullptr; @@ -299,31 +298,19 @@ struct Atrac { PSPPointer atracContext; #ifdef USE_FFMPEG - const AVCodec *pCodec; AVCodecContext *pCodecCtx; SwrContext *pSwrCtx; AVFrame *pFrame; AVPacket *packet; void ReleaseFFMPEGContext() { - if (pFrame) - av_free(pFrame); - if (pSwrCtx) - swr_free(&pSwrCtx); - if (pCodecCtx && pCodecCtx->extradata) { - delete [] pCodecCtx->extradata; - pCodecCtx->extradata = nullptr; - pCodecCtx->extradata_size = 0; - } - if (pCodecCtx) - avcodec_close(pCodecCtx); - if (packet) - av_free_packet(packet); + // All of these allow null pointers. + av_freep(&pFrame); + swr_free(&pSwrCtx); + // If necessary, extradata is automatically freed. + avcodec_free_context(&pCodecCtx); + av_free_packet(packet); delete packet; - pCodec = nullptr; - pCodecCtx = nullptr; - pSwrCtx = nullptr; - pFrame = nullptr; packet = nullptr; } @@ -1395,14 +1382,13 @@ int __AtracSetContext(Atrac *atrac) { return -1; } - atrac->pCodec = avcodec_find_decoder(ff_codec); - atrac->pCodecCtx = avcodec_alloc_context3(atrac->pCodec); + const AVCodec *codec = avcodec_find_decoder(ff_codec); + atrac->pCodecCtx = avcodec_alloc_context3(codec); if (atrac->codecType == PSP_MODE_AT_3) { // For ATRAC3, we need the "extradata" in the RIFF header. - atrac->pCodecCtx->extradata = new u8[14]; + atrac->pCodecCtx->extradata = (uint8_t *)av_mallocz(14); atrac->pCodecCtx->extradata_size = 14; - memset(atrac->pCodecCtx->extradata, 0, 14); // We don't pull this from the RIFF so that we can support OMA also. // The only thing that changes are the jointStereo values. @@ -1435,7 +1421,7 @@ int __AtracSetContext(Atrac *atrac) { atrac->pCodecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16; int ret; - if ((ret = avcodec_open2(atrac->pCodecCtx, atrac->pCodec, NULL)) < 0) { + if ((ret = avcodec_open2(atrac->pCodecCtx, codec, nullptr)) < 0) { ERROR_LOG(ME, "avcodec_open2: Cannot open audio decoder %d", ret); return -1; } From 0e8d3d9c562eb213203898d845bbb1c2781b11e1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 18:37:15 -0700 Subject: [PATCH 10/13] Fix leak in FFmpeg codec ctx usage. Turns out we were leaking these here too. --- Core/HW/SimpleAudioDec.cpp | 52 +++++++------------------------------- Core/HW/SimpleAudioDec.h | 3 --- 2 files changed, 9 insertions(+), 46 deletions(-) diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index c66e03e079..4dc0a9591f 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -55,7 +55,7 @@ int SimpleAudio::GetAudioCodecID(int audioType) { SimpleAudio::SimpleAudio(int audioType, int sample_rate, int channels) : ctxPtr(0xFFFFFFFF), audioType(audioType), sample_rate_(sample_rate), channels_(channels), outSamples(0), srcPos(0), wanted_resample_freq(44100), frame_(0), codec_(0), codecCtx_(0), swrCtx_(0), - extradata_(0), codecOpen_(false) { + codecOpen_(false) { Init(); } @@ -114,62 +114,28 @@ bool SimpleAudio::OpenCodec(int block_align) { #endif // USE_FFMPEG } -bool SimpleAudio::ResetCodecCtx(int channels, int samplerate) { -#ifdef USE_FFMPEG - if (codecCtx_) - avcodec_close(codecCtx_); - - // Find decoder - int audioCodecId = GetAudioCodecID(audioType); - codec_ = avcodec_find_decoder((AVCodecID)audioCodecId); - if (!codec_) { - // Eh, we shouldn't even have managed to compile. But meh. - ERROR_LOG(ME, "This version of FFMPEG does not support AV_CODEC_ctx for audio (%s). Update your submodule.", GetCodecName(audioType)); - return false; - } - - codecCtx_->channels = channels; - codecCtx_->channel_layout = channels==2?AV_CH_LAYOUT_STEREO:AV_CH_LAYOUT_MONO; - codecCtx_->sample_rate = samplerate; - codecOpen_ = false; - return true; -#endif - return false; -} - void SimpleAudio::SetExtraData(u8 *data, int size, int wav_bytes_per_packet) { - delete [] extradata_; - extradata_ = 0; - - if (data != 0) { - extradata_ = new u8[size]; - memcpy(extradata_, data, size); - } - #ifdef USE_FFMPEG if (codecCtx_) { - codecCtx_->extradata = extradata_; + codecCtx_->extradata = (uint8_t *)av_mallocz(size); codecCtx_->extradata_size = size; codecCtx_->block_align = wav_bytes_per_packet; codecOpen_ = false; + + if (data != nullptr) { + memcpy(codecCtx_->extradata, data, size); + } } #endif } SimpleAudio::~SimpleAudio() { #ifdef USE_FFMPEG - if (swrCtx_) - swr_free(&swrCtx_); - if (frame_) - av_frame_free(&frame_); - if (codecCtx_) - avcodec_close(codecCtx_); - frame_ = 0; - codecCtx_ = 0; + swr_free(&swrCtx_); + av_frame_free(&frame_); + avcodec_free_context(&codecCtx_); codec_ = 0; #endif // USE_FFMPEG - delete [] extradata_; - extradata_ = 0; } bool SimpleAudio::IsOK() const { diff --git a/Core/HW/SimpleAudioDec.h b/Core/HW/SimpleAudioDec.h index 7b24443e58..d480ddd8d2 100644 --- a/Core/HW/SimpleAudioDec.h +++ b/Core/HW/SimpleAudioDec.h @@ -51,7 +51,6 @@ public: int GetOutSamples(); int GetSourcePos(); - bool ResetCodecCtx(int channels, int samplerate); int GetAudioCodecID(int audioType); // Get audioCodecId from audioType // Not save stated, only used by UI. Used for ATRAC3 (non+) files. @@ -82,8 +81,6 @@ private: AVCodecContext *codecCtx_; SwrContext *swrCtx_; - // Not savestated, only used by UI. - u8 *extradata_; bool codecOpen_; }; From 60378dd59d3c72df9bb89db57540840b7da907a3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 19:11:39 -0700 Subject: [PATCH 11/13] Atrac: Hack to make seeking in GTA work. --- Core/HLE/sceAtrac.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 79399c4752..b39b27a0fa 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -772,7 +772,7 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { atrac->first.size += bytesToAdd; if (atrac->first.size > atrac->first.filesize) atrac->first.size = atrac->first.filesize; - atrac->first.fileoffset = atrac->first.size; + atrac->first.fileoffset += addbytes; atrac->first.writableBytes = 0; if (atrac->atracContext.IsValid()) { // refresh atracContext @@ -806,11 +806,11 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { if (bytesToAdd > 0) { int addbytes = std::min(bytesToAdd, atrac->first.filesize - atrac->first.fileoffset); Memory::Memcpy(atrac->data_buf + atrac->first.fileoffset, atrac->first.addr + atrac->first.offset, addbytes); + atrac->first.fileoffset += addbytes; } atrac->first.size += bytesToAdd; if (atrac->first.size > atrac->first.filesize) atrac->first.size = atrac->first.filesize; - atrac->first.fileoffset = atrac->first.size; atrac->first.writableBytes -= bytesToAdd; atrac->first.offset += bytesToAdd; } @@ -1001,7 +1001,7 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer return ATRAC_ERROR_BAD_SAMPLE; } - int Sampleoffset = atrac->getDecodePosBySample(sample); + int Sampleoffset = atrac->getFileOffsetBySample(sample); int minWritebytes = std::max(Sampleoffset - (int)atrac->first.size, 0); // Reset temp buf for adding more stream data and set full filled buffer atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->atracBufSize); @@ -1009,10 +1009,6 @@ static u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 buffer // minWritebytes should not be bigger than writeablebytes minWritebytes = std::min(minWritebytes, (int)atrac->first.writableBytes); - if (atrac->first.fileoffset <= 2*atrac->atracBufSize){ - Sampleoffset = atrac->first.fileoffset; - } - // If we've already loaded everything, the answer is 0. if (atrac->first.size >= atrac->first.filesize) { Sampleoffset = 0; @@ -1318,6 +1314,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi return ATRAC_ERROR_NO_DATA; } else { INFO_LOG(ME, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); + atrac->first.fileoffset = atrac->getFileOffsetBySample(sample); if (bytesWrittenFirstBuf > 0) sceAtracAddStreamData(atracID, bytesWrittenFirstBuf); #ifdef USE_FFMPEG From d30508ac43b871ced38360fbecbfe68130f4adf2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 19:44:39 -0700 Subject: [PATCH 12/13] Buildfix for Symbian/Blackberry/etc. --- Core/HLE/sceAtrac.cpp | 8 ++++++++ Core/HW/SimpleAudioDec.cpp | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index b39b27a0fa..870a6904e6 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -307,8 +307,16 @@ struct Atrac { // All of these allow null pointers. av_freep(&pFrame); swr_free(&pSwrCtx); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) // If necessary, extradata is automatically freed. avcodec_free_context(&pCodecCtx); +#else + // Future versions may add other things to free, but avcodec_free_context didn't exist yet here. + avcodec_close(pCodecCtx); + av_freep(&pCodecCtx->extradata); + av_freep(&pCodecCtx->subtitle_header); + av_freep(&pCodecCtx); +#endif av_free_packet(packet); delete packet; packet = nullptr; diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp index 4dc0a9591f..f8074f0e99 100644 --- a/Core/HW/SimpleAudioDec.cpp +++ b/Core/HW/SimpleAudioDec.cpp @@ -133,7 +133,15 @@ SimpleAudio::~SimpleAudio() { #ifdef USE_FFMPEG swr_free(&swrCtx_); av_frame_free(&frame_); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) avcodec_free_context(&codecCtx_); +#else + // Future versions may add other things to free, but avcodec_free_context didn't exist yet here. + avcodec_close(codecCtx_); + av_freep(&codecCtx_->extradata); + av_freep(&codecCtx_->subtitle_header); + av_freep(&codecCtx_); +#endif codec_ = 0; #endif // USE_FFMPEG } From 8fa843bbc317bcd62aca99edc138da7a81766fa0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Oct 2015 20:23:34 -0700 Subject: [PATCH 13/13] Atrac: attempt to power through bad frames. --- Core/HLE/sceAtrac.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 870a6904e6..d873b4b2ec 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -102,6 +102,7 @@ enum AtracDecodeResult { ATDECODE_FAILED = -1, ATDECODE_FEEDME = 0, ATDECODE_GOTFRAME = 1, + ATDECODE_BADFRAME = 2, }; struct InputBuffer { @@ -387,8 +388,7 @@ struct Atrac { ERROR_LOG(ME, "Unsupported feature in ATRAC audio."); // Let's try the next packet. packet->size = 0; - // TODO: Or actually, should we return a blank frame and pretend it worked? - return ATDECODE_FEEDME; + return ATDECODE_BADFRAME; } else if (bytes_read < 0) { ERROR_LOG_REPORT(ME, "avcodec_decode_audio4: Error decoding audio %d / %08x", bytes_read, bytes_read); failedDecode = true; @@ -911,7 +911,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 } } } - if (res == ATDECODE_GOTFRAME) { + if (res == ATDECODE_GOTFRAME || res == ATDECODE_BADFRAME) { // We only want one frame per call, let's continue the next time. break; } @@ -2110,6 +2110,8 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo ERROR_LOG(ME, "swr_convert: Error while converting %d", avret); } break; + } else if (res == ATDECODE_BADFRAME) { + break; } } }