mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 11:18:36 +12:00
Added DivX and MP3 support
This commit is contained in:
parent
1ba5b27f45
commit
cb694f944c
5 changed files with 375 additions and 156 deletions
|
@ -31,23 +31,52 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<Cell
|
|||
, is_finished(false)
|
||||
, just_started(false)
|
||||
, just_finished(false)
|
||||
, codec(nullptr)
|
||||
, input_format(nullptr)
|
||||
, ctx(nullptr)
|
||||
, fmt(nullptr)
|
||||
{
|
||||
av_register_all();
|
||||
avcodec_register_all();
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
|
||||
switch (type)
|
||||
{
|
||||
case CELL_ADEC_TYPE_ATRACX_2CH:
|
||||
{
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P);
|
||||
input_format = av_find_input_format("oma");
|
||||
break;
|
||||
}
|
||||
case CELL_ADEC_TYPE_MP3:
|
||||
{
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
|
||||
input_format = av_find_input_format("mp3");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cellAdec->Error("AudioDecoder(): unknown type (0x%x)", type);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!codec)
|
||||
{
|
||||
cellAdec->Error("AudioDecoder(): avcodec_find_decoder(ATRAC3P) failed");
|
||||
cellAdec->Error("AudioDecoder(): avcodec_find_decoder() failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
if (!input_format)
|
||||
{
|
||||
cellAdec->Error("AudioDecoder(): av_find_input_format() failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
fmt = avformat_alloc_context();
|
||||
if (!fmt)
|
||||
{
|
||||
cellAdec->Error("AudioDecoder(): avformat_alloc_context failed");
|
||||
cellAdec->Error("AudioDecoder(): avformat_alloc_context() failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
@ -55,7 +84,7 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr<Cell
|
|||
fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL);
|
||||
if (!fmt->pb)
|
||||
{
|
||||
cellAdec->Error("AudioDecoder(): avio_alloc_context failed");
|
||||
cellAdec->Error("AudioDecoder(): avio_alloc_context() failed");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
@ -93,7 +122,7 @@ int adecRead(void* opaque, u8* buf, int buf_size)
|
|||
int res = 0;
|
||||
|
||||
next:
|
||||
if (adec.reader.has_ats)
|
||||
if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH && adec.reader.has_ats)
|
||||
{
|
||||
u8 code1 = vm::read8(adec.reader.addr + 2);
|
||||
u8 code2 = vm::read8(adec.reader.addr + 3);
|
||||
|
@ -106,7 +135,7 @@ next:
|
|||
adec.reader.has_ats = false;
|
||||
}
|
||||
|
||||
if (!adec.reader.init)
|
||||
if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH && !adec.reader.init)
|
||||
{
|
||||
OMAHeader oma(1 /* atrac3p id */, adec.sample_rate, adec.channels, adec.frame_size);
|
||||
if (buf_size < sizeof(oma))
|
||||
|
@ -244,12 +273,15 @@ u32 adecOpen(AudioDecoder* data)
|
|||
adec.reader.has_ats = false;
|
||||
adec.just_started = true;
|
||||
|
||||
adec.channels = task.at3p.channels;
|
||||
adec.frame_size = task.at3p.frame_size;
|
||||
adec.sample_rate = task.at3p.sample_rate;
|
||||
adec.use_ats_headers = task.at3p.ats_header == 1;
|
||||
if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH)
|
||||
{
|
||||
adec.channels = task.at3p.channels;
|
||||
adec.frame_size = task.at3p.frame_size;
|
||||
adec.sample_rate = task.at3p.sample_rate;
|
||||
adec.use_ats_headers = task.at3p.ats_header == 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case adecEndSeq:
|
||||
{
|
||||
|
@ -258,8 +290,8 @@ u32 adecOpen(AudioDecoder* data)
|
|||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
|
||||
|
||||
adec.just_finished = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case adecDecodeAu:
|
||||
{
|
||||
|
@ -273,7 +305,8 @@ u32 adecOpen(AudioDecoder* data)
|
|||
if (adec.just_started)
|
||||
{
|
||||
adec.first_pts = task.au.pts;
|
||||
adec.last_pts = task.au.pts - 0x10000; // hack?
|
||||
adec.last_pts = task.au.pts;
|
||||
if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH) adec.last_pts -= 0x10000; // hack
|
||||
}
|
||||
|
||||
struct AVPacketHolder : AVPacket
|
||||
|
@ -313,21 +346,13 @@ u32 adecOpen(AudioDecoder* data)
|
|||
{
|
||||
AVDictionary* opts = nullptr;
|
||||
av_dict_set(&opts, "probesize", "96", 0);
|
||||
err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), &opts);
|
||||
err = avformat_open_input(&adec.fmt, NULL, adec.input_format, &opts);
|
||||
if (err || opts)
|
||||
{
|
||||
cellAdec->Error("adecDecodeAu: avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ???
|
||||
if (!codec)
|
||||
{
|
||||
cellAdec->Error("adecDecodeAu: avcodec_find_decoder() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
//err = avformat_find_stream_info(adec.fmt, NULL);
|
||||
//if (err)
|
||||
//{
|
||||
|
@ -341,7 +366,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
// Emu.Pause();
|
||||
// break;
|
||||
//}
|
||||
if (!avformat_new_stream(adec.fmt, codec))
|
||||
if (!avformat_new_stream(adec.fmt, adec.codec))
|
||||
{
|
||||
cellAdec->Error("adecDecodeAu: avformat_new_stream() failed");
|
||||
Emu.Pause();
|
||||
|
@ -354,7 +379,7 @@ u32 adecOpen(AudioDecoder* data)
|
|||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
|
||||
// not multithread-safe (???)
|
||||
err = avcodec_open2(adec.ctx, codec, &opts);
|
||||
err = avcodec_open2(adec.ctx, adec.codec, &opts);
|
||||
}
|
||||
if (err || opts)
|
||||
{
|
||||
|
@ -424,34 +449,34 @@ u32 adecOpen(AudioDecoder* data)
|
|||
|
||||
if (got_frame)
|
||||
{
|
||||
u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||
if (ts != AV_NOPTS_VALUE)
|
||||
{
|
||||
frame.pts = ts/* - adec.first_pts*/;
|
||||
adec.last_pts = frame.pts;
|
||||
}
|
||||
else
|
||||
{
|
||||
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate;
|
||||
frame.pts = adec.last_pts;
|
||||
}
|
||||
//frame.pts = adec.last_pts;
|
||||
//adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ???
|
||||
frame.auAddr = task.au.addr;
|
||||
frame.auSize = task.au.size;
|
||||
frame.userdata = task.au.userdata;
|
||||
frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float);
|
||||
//u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||
//if (ts != AV_NOPTS_VALUE)
|
||||
//{
|
||||
// frame.pts = ts/* - adec.first_pts*/;
|
||||
// adec.last_pts = frame.pts;
|
||||
//}
|
||||
adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate;
|
||||
frame.pts = adec.last_pts;
|
||||
|
||||
if (frame.data->format != AV_SAMPLE_FMT_FLTP)
|
||||
s32 nbps = av_get_bytes_per_sample((AVSampleFormat)frame.data->format);
|
||||
switch (frame.data->format)
|
||||
{
|
||||
cellAdec->Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format);
|
||||
case AV_SAMPLE_FMT_FLTP: break;
|
||||
case AV_SAMPLE_FMT_S16P: break;
|
||||
default:
|
||||
{
|
||||
cellAdec->Error("adecDecodeAu: unsupported frame format(%d)", frame.data->format);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
frame.auAddr = task.au.addr;
|
||||
frame.auSize = task.au.size;
|
||||
frame.userdata = task.au.userdata;
|
||||
frame.size = frame.data->nb_samples * frame.data->channels * nbps;
|
||||
|
||||
//LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)",
|
||||
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate,
|
||||
//av_get_bytes_per_sample((AVSampleFormat)frame.data->format));
|
||||
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, nbps);
|
||||
|
||||
if (adec.frames.Push(frame, &adec.is_closed))
|
||||
{
|
||||
|
@ -462,8 +487,8 @@ u32 adecOpen(AudioDecoder* data)
|
|||
}
|
||||
|
||||
adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case adecClose: break;
|
||||
|
||||
|
@ -492,12 +517,12 @@ bool adecCheckType(AudioCodecType type)
|
|||
{
|
||||
case CELL_ADEC_TYPE_ATRACX: cellAdec->Notice("adecCheckType: ATRAC3plus"); break;
|
||||
case CELL_ADEC_TYPE_ATRACX_2CH: cellAdec->Notice("adecCheckType: ATRAC3plus 2ch"); break;
|
||||
case CELL_ADEC_TYPE_MP3: cellAdec->Notice("adecCheckType: MP3"); break;
|
||||
|
||||
case CELL_ADEC_TYPE_ATRACX_6CH:
|
||||
case CELL_ADEC_TYPE_ATRACX_8CH:
|
||||
case CELL_ADEC_TYPE_LPCM_PAMF:
|
||||
case CELL_ADEC_TYPE_AC3:
|
||||
case CELL_ADEC_TYPE_MP3:
|
||||
case CELL_ADEC_TYPE_ATRAC3:
|
||||
case CELL_ADEC_TYPE_MPEG_L2:
|
||||
case CELL_ADEC_TYPE_CELP:
|
||||
|
@ -608,6 +633,13 @@ int cellAdecStartSeq(u32 handle, u32 param_addr)
|
|||
task.at3p.sample_rate, task.at3p.channel_config, task.at3p.channels, task.at3p.frame_size, (u32&)task.at3p.extra_config, task.at3p.output, task.at3p.downmix, task.at3p.ats_header);
|
||||
break;
|
||||
}
|
||||
case CELL_ADEC_TYPE_MP3:
|
||||
{
|
||||
auto param = vm::ptr<const CellAdecParamMP3>::make(param_addr);
|
||||
|
||||
cellAdec->Todo("*** CellAdecParamMP3: bw_pcm=%d", param->bw_pcm.ToLE());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cellAdec->Todo("cellAdecStartSeq(): Unimplemented audio codec type(%d)", adec->type);
|
||||
|
@ -678,7 +710,7 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
if (outBuffer)
|
||||
{
|
||||
// reverse byte order:
|
||||
if (frame->channels == 1)
|
||||
if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 1)
|
||||
{
|
||||
float* in_f = (float*)frame->extended_data[0];
|
||||
for (u32 i = 0; i < af.size / 4; i++)
|
||||
|
@ -686,7 +718,7 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
outBuffer[i] = in_f[i];
|
||||
}
|
||||
}
|
||||
else if (frame->channels == 2)
|
||||
else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 2)
|
||||
{
|
||||
float* in_f[2];
|
||||
in_f[0] = (float*)frame->extended_data[0];
|
||||
|
@ -697,9 +729,28 @@ int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
outBuffer[i * 2 + 1] = in_f[1][i];
|
||||
}
|
||||
}
|
||||
else if (frame->format = AV_SAMPLE_FMT_S16P && frame->channels == 1)
|
||||
{
|
||||
s16* in_i = (s16*)frame->extended_data[0];
|
||||
for (u32 i = 0; i < af.size / 2; i++)
|
||||
{
|
||||
outBuffer[i] = (float)in_i[i] / 0x8000;
|
||||
}
|
||||
}
|
||||
else if (frame->format = AV_SAMPLE_FMT_S16P && frame->channels == 2)
|
||||
{
|
||||
s16* in_i[2];
|
||||
in_i[0] = (s16*)frame->extended_data[0];
|
||||
in_i[1] = (s16*)frame->extended_data[1];
|
||||
for (u32 i = 0; i < af.size / 4; i++)
|
||||
{
|
||||
outBuffer[i * 2 + 0] = (float)in_i[0][i] / 0x8000;
|
||||
outBuffer[i * 2 + 1] = (float)in_i[1][i] / 0x8000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cellAdec->Error("cellAdecGetPcm(): unsupported channel count (%d)", frame->channels);
|
||||
cellAdec->Error("cellAdecGetPcm(): unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
@ -747,21 +798,31 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr<u32> pcmItem_ptr)
|
|||
pcm->auInfo.startAddr = af.auAddr;
|
||||
pcm->auInfo.userData = af.userdata;
|
||||
|
||||
auto atx = vm::ptr<CellAdecAtracXInfo>::make(pcm.addr() + sizeof(CellAdecPcmItem));
|
||||
atx->samplingFreq = frame->sample_rate;
|
||||
atx->nbytes = frame->nb_samples * sizeof(float);
|
||||
if (frame->channels == 1)
|
||||
if (adec->type == CELL_ADEC_TYPE_ATRACX_2CH)
|
||||
{
|
||||
atx->channelConfigIndex = 1;
|
||||
auto atx = vm::ptr<CellAdecAtracXInfo>::make(pcm.addr() + sizeof(CellAdecPcmItem));
|
||||
|
||||
atx->samplingFreq = frame->sample_rate;
|
||||
atx->nbytes = frame->nb_samples * sizeof(float);
|
||||
if (frame->channels == 1)
|
||||
{
|
||||
atx->channelConfigIndex = 1;
|
||||
}
|
||||
else if (frame->channels == 2)
|
||||
{
|
||||
atx->channelConfigIndex = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellAdec->Error("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->channels);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
else if (frame->channels == 2)
|
||||
else if (adec->type == CELL_ADEC_TYPE_MP3)
|
||||
{
|
||||
atx->channelConfigIndex = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellAdec->Error("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->channels);
|
||||
Emu.Pause();
|
||||
auto mp3 = vm::ptr<CellAdecMP3Info>::make(pcm.addr() + sizeof(CellAdecPcmItem));
|
||||
|
||||
memset(mp3.get_ptr(), 0, sizeof(CellAdecMP3Info));
|
||||
}
|
||||
|
||||
*pcmItem_ptr = pcm.addr();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue