From cb694f944c7281258fdffc9535d9457133c06a6a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 9 Dec 2014 19:13:03 +0300 Subject: [PATCH 1/5] Added DivX and MP3 support --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 185 ++++++++----- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 2 + rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 5 + rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 335 ++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellVdec.h | 4 + 5 files changed, 375 insertions(+), 156 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 9ae92e6dc6..4c22615d2e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -31,23 +31,52 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptrError("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::ptrpb = 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 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::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 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 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 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 pcmItem_ptr) pcm->auInfo.startAddr = af.auAddr; pcm->auInfo.userData = af.userdata; - auto atx = vm::ptr::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::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::make(pcm.addr() + sizeof(CellAdecPcmItem)); + + memset(mp3.get_ptr(), 0, sizeof(CellAdecMP3Info)); } *pcmItem_ptr = pcm.addr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 414d986dee..9b8528d74b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1100,6 +1100,8 @@ public: bool just_started; bool just_finished; + AVCodec* codec; + AVInputFormat* input_format; AVCodecContext* ctx; AVFormatContext* fmt; u8* io_buf; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 4248c35d74..d4735492da 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -568,6 +568,8 @@ s64 spursInit( } else while (true) { + if (Emu.IsStopped()) break; + spurs->m.xD64.exchange(0); if (spurs->m.exception.ToBE() == 0) { @@ -629,6 +631,9 @@ s64 spursInit( return; } } + + if (Emu.IsStopped()) continue; + if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex())) { assert(!"sys_lwmutex_unlock() failed"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 12b28591c8..5db5ca92b9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -31,23 +31,59 @@ VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 si , is_closed(false) , just_started(false) , just_finished(false) + , frc_set(0) + , codec(nullptr) + , input_format(nullptr) , ctx(nullptr) , vdecCb(nullptr) { av_register_all(); avcodec_register_all(); - AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); + switch (type) + { + case CELL_VDEC_CODEC_TYPE_MPEG2: + { + codec = avcodec_find_decoder(AV_CODEC_ID_MPEG2VIDEO); + input_format = av_find_input_format("mpeg"); + break; + } + case CELL_VDEC_CODEC_TYPE_AVC: + { + codec = avcodec_find_decoder(AV_CODEC_ID_H264); + input_format = av_find_input_format("mpeg"); + break; + } + case CELL_VDEC_CODEC_TYPE_DIVX: + { + codec = avcodec_find_decoder(AV_CODEC_ID_MPEG4); + input_format = av_find_input_format("mpeg"); + break; + } + default: + { + cellVdec->Error("VideoDecoder(): unknown type (0x%x)", type); + Emu.Pause(); + return; + } + } + if (!codec) { - cellVdec->Error("VideoDecoder(): avcodec_find_decoder(H264) failed"); + cellVdec->Error("VideoDecoder(): avcodec_find_decoder() failed"); + Emu.Pause(); + return; + } + if (!input_format) + { + cellVdec->Error("VideoDecoder(): av_find_input_format() failed"); Emu.Pause(); return; } fmt = avformat_alloc_context(); if (!fmt) { - cellVdec->Error("VideoDecoder(): avformat_alloc_context failed"); + cellVdec->Error("VideoDecoder(): avformat_alloc_context() failed"); Emu.Pause(); return; } @@ -55,7 +91,7 @@ VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 si fmt->pb = avio_alloc_context(io_buf, 4096, 0, this, vdecRead, NULL, NULL); if (!fmt->pb) { - cellVdec->Error("VideoDecoder(): avio_alloc_context failed"); + cellVdec->Error("VideoDecoder(): avio_alloc_context() failed"); Emu.Pause(); return; } @@ -163,8 +199,8 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 switch (type) // TODO: check profile levels { case CELL_VDEC_CODEC_TYPE_AVC: cellVdec->Warning("cellVdecQueryAttr: AVC (profile=%d)", profile); break; - case CELL_VDEC_CODEC_TYPE_MPEG2: cellVdec->Todo("MPEG2 not supported"); break; - case CELL_VDEC_CODEC_TYPE_DIVX: cellVdec->Todo("DIVX not supported"); break; + case CELL_VDEC_CODEC_TYPE_MPEG2: cellVdec->Warning("cellVdecQueryAttr: MPEG2 (profile=%d)", profile); break; + case CELL_VDEC_CODEC_TYPE_DIVX: cellVdec->Warning("cellVdecQueryAttr: DivX (profile=%d)", profile); break; default: return CELL_VDEC_ERROR_ARG; } @@ -225,9 +261,10 @@ u32 vdecOpen(VideoDecoder* data) cellVdec->Warning("vdecStartSeq:"); vdec.reader = {}; + vdec.frc_set = 0; vdec.just_started = true; + break; } - break; case vdecEndSeq: { @@ -237,8 +274,8 @@ u32 vdecOpen(VideoDecoder* data) vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); vdec.just_finished = true; + break; } - break; case vdecDecodeAu: { @@ -257,7 +294,7 @@ u32 vdecOpen(VideoDecoder* data) if (vdec.just_started) { vdec.first_pts = task.pts; - vdec.last_pts = task.pts; + vdec.last_pts = -1; vdec.first_dts = task.dts; } @@ -296,38 +333,31 @@ u32 vdecOpen(VideoDecoder* data) } else if (vdec.just_started) // deferred initialization { - err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL); + err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); if (err) { cellVdec->Error("vdecDecodeAu: avformat_open_input() failed"); Emu.Pause(); break; } - AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ??? - if (!codec) + if (vdec.type == CELL_VDEC_CODEC_TYPE_DIVX) { - cellVdec->Error("vdecDecodeAu: avcodec_find_decoder() failed"); - Emu.Pause(); - break; + err = avformat_find_stream_info(vdec.fmt, NULL); + if (err || !vdec.fmt->nb_streams) + { + cellVdec->Error("vdecDecodeAu: avformat_find_stream_info() failed (err=0x%x)", err); + Emu.Pause(); + break; + } } - /*err = avformat_find_stream_info(vdec.fmt, NULL); - if (err) + else { - LOG_ERROR(HLE, "vdecDecodeAu: avformat_find_stream_info() failed"); - Emu.Pause(); - break; - } - if (!vdec.fmt->nb_streams) - { - LOG_ERROR(HLE, "vdecDecodeAu: no stream found"); - Emu.Pause(); - break; - }*/ - if (!avformat_new_stream(vdec.fmt, codec)) - { - cellVdec->Error("vdecDecodeAu: avformat_new_stream() failed"); - Emu.Pause(); - break; + if (!avformat_new_stream(vdec.fmt, vdec.codec)) + { + cellVdec->Error("vdecDecodeAu: avformat_new_stream() failed"); + Emu.Pause(); + break; + } } vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data @@ -336,7 +366,7 @@ u32 vdecOpen(VideoDecoder* data) { std::lock_guard lock(g_mutex_avcodec_open2); // not multithread-safe (???) - err = avcodec_open2(vdec.ctx, codec, &opts); + err = avcodec_open2(vdec.ctx, vdec.codec, &opts); } if (err) { @@ -344,6 +374,7 @@ u32 vdecOpen(VideoDecoder* data) Emu.Pause(); break; } + vdec.just_started = false; } @@ -406,19 +437,99 @@ u32 vdecOpen(VideoDecoder* data) if (got_picture) { - u64 ts = av_frame_get_best_effort_timestamp(frame.data); - if (ts != AV_NOPTS_VALUE) + if (frame.data->interlaced_frame) { - frame.pts = ts/* - vdec.first_pts*/; // ??? - vdec.last_pts = frame.pts; + cellVdec->Error("vdecDecodeAu: interlaced frames not supported (0x%x)", frame.data->interlaced_frame); + Emu.Pause(); + } + + if (frame.data->repeat_pict) + { + cellVdec->Error("vdecDecodeAu: repeated frames not supported (0x%x)", frame.data->repeat_pict); + Emu.Pause(); + } + + if (vdec.frc_set) + { + if (vdec.last_pts == -1) + { + vdec.last_pts = 0x8000; //av_frame_get_best_effort_timestamp(frame.data); + } + else switch (vdec.frc_set) + { + case CELL_VDEC_FRC_24000DIV1001: vdec.last_pts += 1001 * 90000 / 24000; break; + case CELL_VDEC_FRC_24: vdec.last_pts += 90000 / 24; break; + case CELL_VDEC_FRC_25: vdec.last_pts += 90000 / 25; break; + case CELL_VDEC_FRC_30000DIV1001: vdec.last_pts += 1001 * 90000 / 30000; break; + case CELL_VDEC_FRC_30: vdec.last_pts += 90000 / 30; break; + case CELL_VDEC_FRC_50: vdec.last_pts += 90000 / 50; break; + case CELL_VDEC_FRC_60000DIV1001: vdec.last_pts += 1001 * 90000 / 60000; break; + case CELL_VDEC_FRC_60: vdec.last_pts += 90000 / 60; break; + default: + { + cellVdec->Error("vdecDecodeAu: invalid frame rate code set (0x%x)", vdec.frc_set); + Emu.Pause(); + } + } + + frame.frc = vdec.frc_set; } else { - vdec.last_pts += vdec.ctx->time_base.num * 90000 / (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame); - frame.pts = vdec.last_pts; + u64 ts = av_frame_get_best_effort_timestamp(frame.data); + if (ts != AV_NOPTS_VALUE) + { + vdec.last_pts = ts; + } + else if (vdec.last_pts == -1) + { + vdec.last_pts = 0; + } + else + { + vdec.last_pts += vdec.ctx->time_base.num * 90000 * vdec.ctx->ticks_per_frame / vdec.ctx->time_base.den; + } + + if (vdec.ctx->time_base.num == 1) + { + switch ((u64)vdec.ctx->time_base.den + (u64)(vdec.ctx->ticks_per_frame - 1) * 0x100000000ull) + { + case 24: case 48 + 0x100000000: frame.frc = CELL_VDEC_FRC_24; break; + case 25: case 50 + 0x100000000: frame.frc = CELL_VDEC_FRC_25; break; + case 30: case 60 + 0x100000000: frame.frc = CELL_VDEC_FRC_30; break; + case 50: case 100 + 0x100000000: frame.frc = CELL_VDEC_FRC_50; break; + case 60: case 120 + 0x100000000: frame.frc = CELL_VDEC_FRC_60; break; + default: + { + cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); + Emu.Pause(); + } + } + } + else if (vdec.ctx->time_base.num == 1001) + { + if (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame == 24000) + { + frame.frc = CELL_VDEC_FRC_24000DIV1001; + } + else if (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame == 30000) + { + frame.frc = CELL_VDEC_FRC_30000DIV1001; + } + else + { + cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1001, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); + Emu.Pause(); + } + } + else + { + cellVdec->Error("vdecDecodeAu: unsupported time_base.num (%d)", vdec.ctx->time_base.num); + Emu.Pause(); + } } - //frame.pts = vdec.last_pts; - //vdec.last_pts += 3754; + + frame.pts = vdec.last_pts; frame.dts = (frame.pts - vdec.first_pts) + vdec.first_dts; frame.userdata = task.userData; @@ -433,15 +544,15 @@ u32 vdecOpen(VideoDecoder* data) } vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); + break; } - break; case vdecSetFrameRate: { - cellVdec->Error("TODO: vdecSetFrameRate(%d)", task.frc); - Emu.Pause(); + cellVdec->Error("vdecSetFrameRate(0x%x)", task.frc); + vdec.frc_set = task.frc; + break; } - break; case vdecClose: break; @@ -679,67 +790,103 @@ int cellVdecGetPicItem(u32 handle, vm::ptr picItem_ptr) info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL; info->picInfo_addr = info.addr() + sizeof(CellVdecPicItem); - auto avc = vm::ptr::make(info.addr() + sizeof(CellVdecPicItem)); + if (vdec->type == CELL_VDEC_CODEC_TYPE_AVC) + { + auto avc = vm::ptr::make(info.addr() + sizeof(CellVdecPicItem)); - avc->horizontalSize = frame.width; - avc->verticalSize = frame.height; - switch (frame.pict_type) - { - case AV_PICTURE_TYPE_I: avc->pictureType[0] = CELL_VDEC_AVC_PCT_I; break; - case AV_PICTURE_TYPE_P: avc->pictureType[0] = CELL_VDEC_AVC_PCT_P; break; - case AV_PICTURE_TYPE_B: avc->pictureType[0] = CELL_VDEC_AVC_PCT_B; break; - default: avc->pictureType[0] = CELL_VDEC_AVC_PCT_UNKNOWN; break; // ??? + avc->horizontalSize = frame.width; + avc->verticalSize = frame.height; + switch (frame.pict_type) + { + case AV_PICTURE_TYPE_I: avc->pictureType[0] = CELL_VDEC_AVC_PCT_I; break; + case AV_PICTURE_TYPE_P: avc->pictureType[0] = CELL_VDEC_AVC_PCT_P; break; + case AV_PICTURE_TYPE_B: avc->pictureType[0] = CELL_VDEC_AVC_PCT_B; break; + default: cellVdec->Error("cellVdecGetPicItem(AVC): unknown pict_type value (0x%x)", frame.pict_type); + } + avc->pictureType[1] = CELL_VDEC_AVC_PCT_UNKNOWN; // ??? + avc->idrPictureFlag = false; // ??? + avc->aspect_ratio_idc = CELL_VDEC_AVC_ARI_SAR_UNSPECIFIED; // ??? + avc->sar_height = 0; + avc->sar_width = 0; + avc->pic_struct = CELL_VDEC_AVC_PSTR_FRAME; // ??? + avc->picOrderCount[0] = 0; // ??? + avc->picOrderCount[1] = 0; + avc->vui_parameters_present_flag = true; // ??? + avc->frame_mbs_only_flag = true; // ??? progressive + avc->video_signal_type_present_flag = true; // ??? + avc->video_format = CELL_VDEC_AVC_VF_COMPONENT; // ??? + avc->video_full_range_flag = false; // ??? + avc->colour_description_present_flag = true; + avc->colour_primaries = CELL_VDEC_AVC_CP_ITU_R_BT_709_5; // ??? + avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5; + avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important + avc->timing_info_present_flag = true; + + switch (vf.frc) + { + case CELL_VDEC_FRC_24000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001; break; + case CELL_VDEC_FRC_24: avc->frameRateCode = CELL_VDEC_AVC_FRC_24; break; + case CELL_VDEC_FRC_25: avc->frameRateCode = CELL_VDEC_AVC_FRC_25; break; + case CELL_VDEC_FRC_30000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001; break; + case CELL_VDEC_FRC_30: avc->frameRateCode = CELL_VDEC_AVC_FRC_30; break; + case CELL_VDEC_FRC_50: avc->frameRateCode = CELL_VDEC_AVC_FRC_50; break; + case CELL_VDEC_FRC_60000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_60000DIV1001; break; + case CELL_VDEC_FRC_60: avc->frameRateCode = CELL_VDEC_AVC_FRC_60; break; + default: cellVdec->Error("cellVdecGetPicItem(AVC): unknown frc value (0x%x)", vf.frc); break; + } + + avc->fixed_frame_rate_flag = true; + avc->low_delay_hrd_flag = true; // ??? + avc->entropy_coding_mode_flag = true; // ??? + avc->nalUnitPresentFlags = 0; // ??? + avc->ccDataLength[0] = 0; + avc->ccDataLength[1] = 0; + avc->reserved[0] = 0; + avc->reserved[1] = 0; } - avc->pictureType[1] = CELL_VDEC_AVC_PCT_UNKNOWN; // ??? - avc->idrPictureFlag = false; // ??? - avc->aspect_ratio_idc = CELL_VDEC_AVC_ARI_SAR_UNSPECIFIED; // ??? - avc->sar_height = 0; - avc->sar_width = 0; - avc->pic_struct = CELL_VDEC_AVC_PSTR_FRAME; // ??? - avc->picOrderCount[0] = 0; // ??? - avc->picOrderCount[1] = 0; - avc->vui_parameters_present_flag = true; // ??? - avc->frame_mbs_only_flag = true; // ??? progressive - avc->video_signal_type_present_flag = true; // ??? - avc->video_format = CELL_VDEC_AVC_VF_COMPONENT; // ??? - avc->video_full_range_flag = false; // ??? - avc->colour_description_present_flag = true; - avc->colour_primaries = CELL_VDEC_AVC_CP_ITU_R_BT_709_5; // ??? - avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5; - avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important - avc->timing_info_present_flag = true; - if (vdec->ctx->time_base.num == 1001) + else if (vdec->type == CELL_VDEC_CODEC_TYPE_DIVX) { - if (vdec->ctx->time_base.den == 48000 && vdec->ctx->ticks_per_frame == 2) + auto dvx = vm::ptr::make(info.addr() + sizeof(CellVdecPicItem)); + + switch (frame.pict_type) { - avc->frameRateCode = CELL_VDEC_AVC_FRC_24000DIV1001; + case AV_PICTURE_TYPE_I: dvx->pictureType = CELL_VDEC_DIVX_VCT_I; break; + case AV_PICTURE_TYPE_P: dvx->pictureType = CELL_VDEC_DIVX_VCT_P; break; + case AV_PICTURE_TYPE_B: dvx->pictureType = CELL_VDEC_DIVX_VCT_B; break; + default: cellVdec->Error("cellVdecGetPicItem(DivX): unknown pict_type value (0x%x)", frame.pict_type); } - else if (vdec->ctx->time_base.den == 60000 && vdec->ctx->ticks_per_frame == 2) + dvx->horizontalSize = frame.width; + dvx->verticalSize = frame.height; + dvx->pixelAspectRatio = CELL_VDEC_DIVX_ARI_PAR_1_1; // ??? + dvx->parHeight = 0; + dvx->parWidth = 0; + dvx->colourDescription = false; // ??? + dvx->colourPrimaries = CELL_VDEC_DIVX_CP_ITU_R_BT_709; // ??? + dvx->transferCharacteristics = CELL_VDEC_DIVX_TC_ITU_R_BT_709; // ??? + dvx->matrixCoefficients = CELL_VDEC_DIVX_MXC_ITU_R_BT_709; // ??? + dvx->pictureStruct = CELL_VDEC_DIVX_PSTR_FRAME; // ??? + switch (vf.frc) { - avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001; - } - else - { - cellVdec->Error("cellVdecGetPicItem: unsupported time_base.den (%d)", vdec->ctx->time_base.den); - Emu.Pause(); + case CELL_VDEC_FRC_24000DIV1001: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_24000DIV1001; break; + case CELL_VDEC_FRC_24: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_24; break; + case CELL_VDEC_FRC_25: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_25; break; + case CELL_VDEC_FRC_30000DIV1001: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_30000DIV1001; break; + case CELL_VDEC_FRC_30: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_30; break; + case CELL_VDEC_FRC_50: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_50; break; + case CELL_VDEC_FRC_60000DIV1001: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_60000DIV1001; break; + case CELL_VDEC_FRC_60: dvx->frameRateCode = CELL_VDEC_DIVX_FRC_60; break; + default: cellVdec->Error("cellVdecGetPicItem(DivX): unknown frc value (0x%x)", vf.frc); } } - else + else if (vdec->type == CELL_VDEC_CODEC_TYPE_MPEG2) { - cellVdec->Error("cellVdecGetPicItem: unsupported time_base.num (%d)", vdec->ctx->time_base.num); + auto mp2 = vm::ptr::make(info.addr() + sizeof(CellVdecPicItem)); + + cellVdec->Todo("cellVdecGetPicItem(MPEG2)"); Emu.Pause(); } - avc->fixed_frame_rate_flag = true; - avc->low_delay_hrd_flag = true; // ??? - avc->entropy_coding_mode_flag = true; // ??? - avc->nalUnitPresentFlags = 0; // ??? - avc->ccDataLength[0] = 0; - avc->ccDataLength[1] = 0; - avc->reserved[0] = 0; - avc->reserved[1] = 0; - - *picItem_ptr = info.addr(); + *picItem_ptr = info.addr(); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 144c0766ad..5ea31ff840 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -685,6 +685,7 @@ struct VdecFrame u64 dts; u64 pts; u64 userdata; + u32 frc; }; int vdecRead(void* opaque, u8* buf, int buf_size); @@ -699,6 +700,8 @@ public: bool just_started; bool just_finished; + AVCodec* codec; + AVInputFormat* input_format; AVCodecContext* ctx; AVFormatContext* fmt; u8* io_buf; @@ -721,6 +724,7 @@ public: VdecTask task; // current task variable u64 last_pts, first_pts, first_dts; + u32 frc_set; // frame rate overwriting AVRational rfr, afr; PPUThread* vdecCb; From 2b4f858caff84b493ea639661aca711a29066222 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 9 Dec 2014 20:24:50 +0300 Subject: [PATCH 2/5] Fixes --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 94 ++++++++++++++++++++----- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 11 ++- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 4 ++ 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 4c22615d2e..1dbfb57e23 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -41,7 +41,10 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr> 2) & 0x7; + adec.ch_cfg = (code1 >> 2) & 0x7; adec.frame_size = ((((u32)code1 & 0x3) << 8) | (u32)code2) * 8 + 8; adec.sample_rate = at3freq[code1 >> 5]; @@ -135,9 +138,9 @@ next: adec.reader.has_ats = false; } - if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH && !adec.reader.init) + if (adecIsAtracX(adec.type) && !adec.reader.init) { - OMAHeader oma(1 /* atrac3p id */, adec.sample_rate, adec.channels, adec.frame_size); + OMAHeader oma(1 /* atrac3p id */, adec.sample_rate, adec.ch_cfg, adec.frame_size); if (buf_size < sizeof(oma)) { cellAdec->Error("adecRead(): OMAHeader writing failed"); @@ -273,9 +276,10 @@ u32 adecOpen(AudioDecoder* data) adec.reader.has_ats = false; adec.just_started = true; - if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH) + if (adecIsAtracX(adec.type)) { - adec.channels = task.at3p.channels; + adec.ch_cfg = task.at3p.channel_config; + adec.ch_out = 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; @@ -306,7 +310,7 @@ u32 adecOpen(AudioDecoder* data) { adec.first_pts = task.au.pts; adec.last_pts = task.au.pts; - if (adec.type == CELL_ADEC_TYPE_ATRACX_2CH) adec.last_pts -= 0x10000; // hack + if (adecIsAtracX(adec.type)) adec.last_pts -= 0x10000; // hack } struct AVPacketHolder : AVPacket @@ -515,12 +519,12 @@ bool adecCheckType(AudioCodecType type) { switch (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: cellAdec->Notice("adecCheckType(): ATRAC3plus"); break; + case CELL_ADEC_TYPE_ATRACX_2CH: cellAdec->Notice("adecCheckType(): ATRAC3plus 2ch"); break; + case CELL_ADEC_TYPE_ATRACX_6CH: cellAdec->Notice("adecCheckType(): ATRAC3plus 6ch"); break; + case CELL_ADEC_TYPE_ATRACX_8CH: cellAdec->Notice("adecCheckType(): ATRAC3plus 8ch"); 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_ATRAC3: @@ -528,10 +532,12 @@ bool adecCheckType(AudioCodecType type) case CELL_ADEC_TYPE_CELP: case CELL_ADEC_TYPE_M4AAC: case CELL_ADEC_TYPE_CELP8: + { cellAdec->Todo("Unimplemented audio codec type (%d)", type); + Emu.Pause(); break; - default: - return false; + } + default: return false; } return true; @@ -617,7 +623,10 @@ int cellAdecStartSeq(u32 handle, u32 param_addr) switch (adec->type) { + case CELL_ADEC_TYPE_ATRACX: case CELL_ADEC_TYPE_ATRACX_2CH: + case CELL_ADEC_TYPE_ATRACX_6CH: + case CELL_ADEC_TYPE_ATRACX_8CH: { auto param = vm::ptr::make(param_addr); @@ -729,7 +738,49 @@ int cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i * 2 + 1] = in_f[1][i]; } } - else if (frame->format = AV_SAMPLE_FMT_S16P && frame->channels == 1) + else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 6) + { + float* in_f[6]; + in_f[0] = (float*)frame->extended_data[0]; + in_f[1] = (float*)frame->extended_data[1]; + in_f[2] = (float*)frame->extended_data[2]; + in_f[3] = (float*)frame->extended_data[3]; + in_f[4] = (float*)frame->extended_data[4]; + in_f[5] = (float*)frame->extended_data[5]; + for (u32 i = 0; i < af.size / 24; i++) + { + outBuffer[i * 6 + 0] = in_f[0][i]; + outBuffer[i * 6 + 1] = in_f[1][i]; + outBuffer[i * 6 + 2] = in_f[2][i]; + outBuffer[i * 6 + 3] = in_f[3][i]; + outBuffer[i * 6 + 4] = in_f[4][i]; + outBuffer[i * 6 + 5] = in_f[5][i]; + } + } + else if (frame->format == AV_SAMPLE_FMT_FLTP && frame->channels == 8) + { + float* in_f[8]; + in_f[0] = (float*)frame->extended_data[0]; + in_f[1] = (float*)frame->extended_data[1]; + in_f[2] = (float*)frame->extended_data[2]; + in_f[3] = (float*)frame->extended_data[3]; + in_f[4] = (float*)frame->extended_data[4]; + in_f[5] = (float*)frame->extended_data[5]; + in_f[6] = (float*)frame->extended_data[6]; + in_f[7] = (float*)frame->extended_data[7]; + for (u32 i = 0; i < af.size / 24; i++) + { + outBuffer[i * 8 + 0] = in_f[0][i]; + outBuffer[i * 8 + 1] = in_f[1][i]; + outBuffer[i * 8 + 2] = in_f[2][i]; + outBuffer[i * 8 + 3] = in_f[3][i]; + outBuffer[i * 8 + 4] = in_f[4][i]; + outBuffer[i * 8 + 5] = in_f[5][i]; + outBuffer[i * 8 + 6] = in_f[6][i]; + outBuffer[i * 8 + 7] = in_f[7][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++) @@ -737,7 +788,7 @@ int cellAdecGetPcm(u32 handle, vm::ptr outBuffer) outBuffer[i] = (float)in_i[i] / 0x8000; } } - else if (frame->format = AV_SAMPLE_FMT_S16P && frame->channels == 2) + else if (frame->format == AV_SAMPLE_FMT_S16P && frame->channels == 2) { s16* in_i[2]; in_i[0] = (s16*)frame->extended_data[0]; @@ -798,7 +849,7 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr pcmItem_ptr) pcm->auInfo.startAddr = af.auAddr; pcm->auInfo.userData = af.userdata; - if (adec->type == CELL_ADEC_TYPE_ATRACX_2CH) + if (adecIsAtracX(adec->type)) { auto atx = vm::ptr::make(pcm.addr() + sizeof(CellAdecPcmItem)); @@ -812,6 +863,14 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr pcmItem_ptr) { atx->channelConfigIndex = 2; } + else if (frame->channels == 6) + { + atx->channelConfigIndex = 6; + } + else if (frame->channels == 8) + { + atx->channelConfigIndex = 7; + } else { cellAdec->Error("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->channels); @@ -822,6 +881,7 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr pcmItem_ptr) { auto mp3 = vm::ptr::make(pcm.addr() + sizeof(CellAdecPcmItem)); + // TODO memset(mp3.get_ptr(), 0, sizeof(CellAdecMP3Info)); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 9b8528d74b..fbe6707351 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -284,6 +284,14 @@ enum AudioCodecType CELL_ADEC_TYPE_RESERVED25, }; +static bool adecIsAtracX(const AudioCodecType type) +{ + return type == CELL_ADEC_TYPE_ATRACX + || type == CELL_ADEC_TYPE_ATRACX_2CH + || type == CELL_ADEC_TYPE_ATRACX_6CH + || type == CELL_ADEC_TYPE_ATRACX_8CH; +} + // Output Channel Number enum CellAdecChannel { @@ -1132,7 +1140,8 @@ public: AdecTask task; u64 last_pts, first_pts; - u32 channels; + u32 ch_out; + u32 ch_cfg; u32 frame_size; u32 sample_rate; bool use_ats_headers; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 5db5ca92b9..d923273dde 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -516,6 +516,10 @@ u32 vdecOpen(VideoDecoder* data) { frame.frc = CELL_VDEC_FRC_30000DIV1001; } + else if (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame == 60000) + { + frame.frc = CELL_VDEC_FRC_60000DIV1001; + } else { cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1001, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); From 855761432235369badffb320de03009496a5c9f7 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 11 Dec 2014 22:25:11 +0300 Subject: [PATCH 3/5] cellPamf improved --- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 417 +++++++++++++----------- rpcs3/Emu/SysCalls/Modules/cellPamf.h | 53 ++- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 12 +- 3 files changed, 269 insertions(+), 213 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 16a5064293..4be694dac8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -1,157 +1,201 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "cellPamf.h" Module *cellPamf = nullptr; -int pamfStreamTypeToEsFilterId(u8 type, u8 ch, vm::ptr pEsFilterId) +s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId) { - //TODO: convert type and ch to EsFilterId - pEsFilterId->filterIdMajor = 0; - pEsFilterId->filterIdMinor = 0; - pEsFilterId->supplementalInfo1 = 0; - pEsFilterId->supplementalInfo2 = 0; - + // convert type and ch to EsFilterId + assert(ch < 16); + pEsFilterId.supplementalInfo1 = type == CELL_PAMF_STREAM_TYPE_AVC; + pEsFilterId.supplementalInfo2 = 0; + switch (type) { case CELL_PAMF_STREAM_TYPE_AVC: - { - if (ch < 16) - { - pEsFilterId->filterIdMajor = 0xe0 + ch; - pEsFilterId->filterIdMinor = 0; - pEsFilterId->supplementalInfo1 = 0x01; - pEsFilterId->supplementalInfo2 = 0; - } - else - cellPamf->Error("pamfStreamTypeToEsFilterId: invalid CELL_PAMF_STREAM_TYPE_AVC channel (ch=%d)", ch); - } - break; - case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: - if (ch == 0) - { - pEsFilterId->filterIdMajor = 0xbd; - pEsFilterId->filterIdMinor = 0; - pEsFilterId->supplementalInfo1 = 0; - pEsFilterId->supplementalInfo2 = 0; - } - else - cellPamf->Todo("pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_ATRAC3PLUS (ch=%d)", ch); - break; - case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: - if (ch == 0) - { - pEsFilterId->filterIdMajor = 0xbd; - pEsFilterId->filterIdMinor = 0x40; - pEsFilterId->supplementalInfo1 = 0; - pEsFilterId->supplementalInfo2 = 0; - } - else - cellPamf->Todo("pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_LPCM (ch=%d)", ch); - break; - case CELL_PAMF_STREAM_TYPE_USER_DATA: - if (ch == 0) - { - pEsFilterId->filterIdMajor = 0xbd; - pEsFilterId->filterIdMinor = 0x20; - pEsFilterId->supplementalInfo1 = 0; - pEsFilterId->supplementalInfo2 = 0; - } - else - cellPamf->Todo("pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_USER_DATA (ch=%d)", ch); - break; - case CELL_PAMF_STREAM_TYPE_AC3: - cellPamf->Todo("pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_AC3 (ch=%d)", ch); + { + // code = 0x1b + pEsFilterId.filterIdMajor = 0xe0 | ch; + pEsFilterId.filterIdMinor = 0; break; + } + case CELL_PAMF_STREAM_TYPE_M2V: - cellPamf->Todo("pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_M2V (ch=%d)", ch); + { + // code = 0x02 + pEsFilterId.filterIdMajor = 0xe0 | ch; + pEsFilterId.filterIdMinor = 0; break; + } + + case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: + { + // code = 0xdc + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = ch; + break; + } + + case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: + { + // code = 0x80 + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = 0x40 | ch; + break; + } + + case CELL_PAMF_STREAM_TYPE_AC3: + { + // code = 0x81 + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = 0x30 | ch; + break; + } + + case CELL_PAMF_STREAM_TYPE_USER_DATA: + { + // code = 0xdd + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = 0x20 | ch; + break; + } + + case 6: + { + // code = 0xff + pEsFilterId.filterIdMajor = 0xe0 | ch; + pEsFilterId.filterIdMinor = 0; + break; + } + + case 7: + { + // code = 0xff + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = ch; + break; + } + + case 8: + { + // code = 0xff + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = 0x10 | ch; + break; + } + + case 9: + { + // code = 0xff + pEsFilterId.filterIdMajor = 0xbd; + pEsFilterId.filterIdMinor = 0x20 | ch; + break; + } + default: + { + cellPamf->Error("pamfStreamTypeToEsFilterId(): unknown type (%d, ch=%d)", type, ch); + Emu.Pause(); return CELL_PAMF_ERROR_INVALID_ARG; } + } + return CELL_OK; } u8 pamfGetStreamType(vm::ptr pSelf, u8 stream) { - //TODO: get stream type correctly - switch (pSelf->pAddr->stream_headers[stream].type) + // TODO: get stream type correctly + auto& header = pSelf->pAddr->stream_headers[stream]; + + switch (header.type) { case 0x1b: return CELL_PAMF_STREAM_TYPE_AVC; + case 0x02: return CELL_PAMF_STREAM_TYPE_M2V; case 0xdc: return CELL_PAMF_STREAM_TYPE_ATRAC3PLUS; case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM; + case 0x81: return CELL_PAMF_STREAM_TYPE_AC3; case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA; - default: - cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type); - return 0; } + + cellPamf->Todo("pamfGetStreamType(): unsupported stream type found(0x%x)", header.type); + Emu.Pause(); + return 0xff; } u8 pamfGetStreamChannel(vm::ptr pSelf, u8 stream) { - //TODO: get stream channel correctly + // TODO: get stream channel correctly + auto& header = pSelf->pAddr->stream_headers[stream]; - switch (pSelf->pAddr->stream_headers[stream].type) + switch (header.type) { - case 0x1b: - if ((pSelf->pAddr->stream_headers[stream].stream_id >= 0xe0) && (pSelf->pAddr->stream_headers[stream].stream_id <= 0xef)) - { - return pSelf->pAddr->stream_headers[stream].stream_id - 0xe0; - } - else - { - cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x", - pSelf->pAddr->stream_headers[stream].type, pSelf->pAddr->stream_headers[stream].stream_id); - return 0; - } - case 0xdc: - cellPamf->Todo("pamfGetStreamChannel: CELL_PAMF_STREAM_TYPE_ATRAC3PLUS"); - return 0; - case 0x80: - cellPamf->Todo("pamfGetStreamChannel: CELL_PAMF_STREAM_TYPE_PAMF_LPCM"); - return 0; + case 0x1b: // AVC + case 0x02: // M2V + { + assert((header.fid_major & 0xf0) == 0xe0 && header.fid_minor == 0); + return header.fid_major % 16; + } + + case 0xdc: // ATRAC3PLUS + { + assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0); + return header.fid_minor % 16; + } + + case 0x80: // LPCM + { + assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x40); + return header.fid_minor % 16; + } + case 0x81: // AC3 + { + assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x30); + return header.fid_minor % 16; + } case 0xdd: - cellPamf->Todo("pamfGetStreamChannel: CELL_PAMF_STREAM_TYPE_USER_DATA"); - return 0; - default: - cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type); - return 0; + { + assert(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x20); + return header.fid_minor % 16; + } } + cellPamf->Todo("pamfGetStreamChannel(): unsupported stream type found(0x%x)", header.type); + Emu.Pause(); + return 0xff; } -int cellPamfGetHeaderSize(vm::ptr pAddr, u64 fileSize, vm::ptr pSize) +s32 cellPamfGetHeaderSize(vm::ptr pAddr, u64 fileSize, vm::ptr pSize) { cellPamf->Warning("cellPamfGetHeaderSize(pAddr=0x%x, fileSize=%d, pSize_addr=0x%x)", pAddr.addr(), fileSize, pSize.addr()); - //if ((u32)pAddr->magic != 0x464d4150) - //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + //if ((u32)pAddr->magic != 0x464d4150) return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; *pSize = offset; return CELL_OK; } -int cellPamfGetHeaderSize2(vm::ptr pAddr, u64 fileSize, u32 attribute, vm::ptr pSize) +s32 cellPamfGetHeaderSize2(vm::ptr pAddr, u64 fileSize, u32 attribute, vm::ptr pSize) { cellPamf->Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=0x%x, pSize_addr=0x%x)", pAddr.addr(), fileSize, attribute, pSize.addr()); - //if ((u32)pAddr->magic != 0x464d4150) - //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + //if ((u32)pAddr->magic != 0x464d4150) return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; *pSize = offset; return CELL_OK; } -int cellPamfGetStreamOffsetAndSize(vm::ptr pAddr, u64 fileSize, vm::ptr pOffset, vm::ptr pSize) +s32 cellPamfGetStreamOffsetAndSize(vm::ptr pAddr, u64 fileSize, vm::ptr pOffset, vm::ptr pSize) { cellPamf->Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)", pAddr.addr(), fileSize, pOffset.addr(), pSize.addr()); - //if ((u32)pAddr->magic != 0x464d4150) - //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + //if ((u32)pAddr->magic != 0x464d4150) return CELL_PAMF_ERROR_UNKNOWN_TYPE; const u64 offset = (u64)pAddr->data_offset << 11; *pOffset = offset; @@ -160,14 +204,15 @@ int cellPamfGetStreamOffsetAndSize(vm::ptr pAddr, u64 fileSize, vm:: return CELL_OK; } -int cellPamfVerify(vm::ptr pAddr, u64 fileSize) +s32 cellPamfVerify(vm::ptr pAddr, u64 fileSize) { - cellPamf->Warning("cellPamfVerify(pAddr=0x%x, fileSize=%d)", pAddr.addr(), fileSize); + cellPamf->Todo("cellPamfVerify(pAddr=0x%x, fileSize=%d)", pAddr.addr(), fileSize); + // TODO return CELL_OK; } -int cellPamfReaderInitialize(vm::ptr pSelf, vm::ptr pAddr, u64 fileSize, u32 attribute) +s32 cellPamfReaderInitialize(vm::ptr pSelf, vm::ptr pAddr, u64 fileSize, u32 attribute) { cellPamf->Warning("cellPamfReaderInitialize(pSelf=0x%x, pAddr=0x%x, fileSize=%d, attribute=0x%x)", pSelf.addr(), pAddr.addr(), fileSize, attribute); @@ -175,7 +220,7 @@ int cellPamfReaderInitialize(vm::ptr pSelf, vm::ptrfileSize = fileSize; } - else //if fileSize is unknown + else // if fileSize is unknown { pSelf->fileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11); } @@ -183,70 +228,59 @@ int cellPamfReaderInitialize(vm::ptr pSelf, vm::ptrTodo("cellPamfReaderInitialize(): verification"); } - pSelf->stream = 0; //??? currently set stream + pSelf->stream = 0; // currently set stream return CELL_OK; } -int cellPamfReaderGetPresentationStartTime(vm::ptr pSelf, vm::ptr pTimeStamp) +s32 cellPamfReaderGetPresentationStartTime(vm::ptr pSelf, vm::ptr pTimeStamp) { cellPamf->Warning("cellPamfReaderGetPresentationStartTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", pSelf.addr(), pTimeStamp.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } + // always returns CELL_OK pTimeStamp->upper = (u32)(u16)pSelf->pAddr->start_pts_high; pTimeStamp->lower = pSelf->pAddr->start_pts_low; return CELL_OK; } -int cellPamfReaderGetPresentationEndTime(vm::ptr pSelf, vm::ptr pTimeStamp) +s32 cellPamfReaderGetPresentationEndTime(vm::ptr pSelf, vm::ptr pTimeStamp) { cellPamf->Warning("cellPamfReaderGetPresentationEndTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", pSelf.addr(), pTimeStamp.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } + // always returns CELL_OK pTimeStamp->upper = (u32)(u16)pSelf->pAddr->end_pts_high; pTimeStamp->lower = pSelf->pAddr->end_pts_low; return CELL_OK; } -int cellPamfReaderGetMuxRateBound(vm::ptr pSelf) +u32 cellPamfReaderGetMuxRateBound(vm::ptr pSelf) { cellPamf->Warning("cellPamfReaderGetMuxRateBound(pSelf=0x%x)", pSelf.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - + // cannot return error code return pSelf->pAddr->mux_rate_max; } -int cellPamfReaderGetNumberOfStreams(vm::ptr pSelf) +u8 cellPamfReaderGetNumberOfStreams(vm::ptr pSelf) { cellPamf->Warning("cellPamfReaderGetNumberOfStreams(pSelf=0x%x)", pSelf.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - + // cannot return error code return pSelf->pAddr->stream_count; } -int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr pSelf, u8 streamType) +u8 cellPamfReaderGetNumberOfSpecificStreams(vm::ptr pSelf, u8 streamType) { cellPamf->Warning("cellPamfReaderGetNumberOfSpecificStreams(pSelf=0x%x, streamType=%d)", pSelf.addr(), streamType); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } + // cannot return error code - int counts[6] = {0, 0, 0, 0, 0, 0}; + u8 counts[256] = {}; for (u8 i = 0; i < pSelf->pAddr->stream_count; i++) { @@ -261,46 +295,48 @@ int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr pSelf, u8 s case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: case CELL_PAMF_STREAM_TYPE_AC3: case CELL_PAMF_STREAM_TYPE_USER_DATA: + { return counts[streamType]; - case CELL_PAMF_STREAM_TYPE_VIDEO: - return counts[CELL_PAMF_STREAM_TYPE_AVC] + counts[CELL_PAMF_STREAM_TYPE_M2V]; - case CELL_PAMF_STREAM_TYPE_AUDIO: - return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] + counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; - default: - return 0; } + + case CELL_PAMF_STREAM_TYPE_VIDEO: + { + return counts[CELL_PAMF_STREAM_TYPE_AVC] + counts[CELL_PAMF_STREAM_TYPE_M2V]; + } + + case CELL_PAMF_STREAM_TYPE_AUDIO: + { + return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] + counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; + } + } + + cellPamf->Todo("cellPamfReaderGetNumberOfSpecificStreams(): unsupported stream type (0x%x)", streamType); + Emu.Pause(); + return 0; } -int cellPamfReaderSetStreamWithIndex(vm::ptr pSelf, u8 streamIndex) +s32 cellPamfReaderSetStreamWithIndex(vm::ptr pSelf, u8 streamIndex) { cellPamf->Warning("cellPamfReaderSetStreamWithIndex(pSelf=0x%x, streamIndex=%d)", pSelf.addr(), streamIndex); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - - if (streamIndex < pSelf->pAddr->stream_count) + if (streamIndex >= pSelf->pAddr->stream_count) { - pSelf->stream = streamIndex; - return CELL_OK; + return CELL_PAMF_ERROR_INVALID_ARG; } - cellPamf->Error("cellPamfReaderSetStreamWithIndex: CELL_PAMF_ERROR_INVALID_ARG"); - return CELL_PAMF_ERROR_INVALID_ARG; + pSelf->stream = streamIndex; + return CELL_OK; } -int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 streamType, u8 ch) +s32 cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 streamType, u8 ch) { cellPamf->Warning("cellPamfReaderSetStreamWithTypeAndChannel(pSelf=0x%x, streamType=%d, ch=%d)", pSelf.addr(), streamType, ch); - - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - if (streamType > 5) + // it probably doesn't support "any audio" or "any video" argument + if (streamType > 5 || ch >= 16) { - cellPamf->Error("cellPamfReaderSetStreamWithTypeAndChannel: invalid stream type(%d)", streamType); - //it probably doesn't support "any audio" or "any video" argument + cellPamf->Error("cellPamfReaderSetStreamWithTypeAndChannel(): invalid arguments (streamType=%d, ch=%d)", streamType, ch); + Emu.Pause(); return CELL_PAMF_ERROR_INVALID_ARG; } @@ -319,14 +355,10 @@ int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 return CELL_PAMF_ERROR_STREAM_NOT_FOUND; } -int cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr pSelf, u8 streamType, u8 streamIndex) +s32 cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr pSelf, u8 streamType, u8 streamIndex) { cellPamf->Warning("cellPamfReaderSetStreamWithTypeAndIndex(pSelf=0x%x, streamType=%d, streamIndex=%d)", pSelf.addr(), streamType, streamIndex); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - u32 found = 0; for (u8 i = 0; i < pSelf->pAddr->stream_count; i++) @@ -340,23 +372,31 @@ int cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr pSelf, u8 st else switch(streamType) { case CELL_PAMF_STREAM_TYPE_VIDEO: - if (type == CELL_PAMF_STREAM_TYPE_AVC || type == CELL_PAMF_STREAM_TYPE_M2V) + { + if (type == CELL_PAMF_STREAM_TYPE_AVC || type == CELL_PAMF_STREAM_TYPE_M2V) { found++; } break; + } + case CELL_PAMF_STREAM_TYPE_AUDIO: + { if (type == CELL_PAMF_STREAM_TYPE_ATRAC3PLUS || type == CELL_PAMF_STREAM_TYPE_AC3 || type == CELL_PAMF_STREAM_TYPE_PAMF_LPCM) { found++; } break; + } + default: + { if (streamType > 5) { return CELL_PAMF_ERROR_INVALID_ARG; } } + } if (found > streamIndex) { @@ -368,46 +408,57 @@ int cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr pSelf, u8 st return CELL_PAMF_ERROR_STREAM_NOT_FOUND; } -int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, vm::ptr pEsFilterId) +s32 cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, vm::ptr pEsFilterId) { cellPamf->Warning("cellPamfStreamTypeToEsFilterId(type=%d, ch=%d, pEsFilterId_addr=0x%x)", type, ch, pEsFilterId.addr()); + + if (!pEsFilterId) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } - return pamfStreamTypeToEsFilterId(type, ch, pEsFilterId); + return pamfStreamTypeToEsFilterId(type, ch, *pEsFilterId); } -int cellPamfReaderGetStreamIndex(vm::ptr pSelf) +s32 cellPamfReaderGetStreamIndex(vm::ptr pSelf) { cellPamf->Log("cellPamfReaderGetStreamIndex(pSelf=0x%x)", pSelf.addr()); + // seems that CELL_PAMF_ERROR_INVALID_PAMF must be already written in pSelf->stream if it's the case return pSelf->stream; } -int cellPamfReaderGetStreamTypeAndChannel(vm::ptr pSelf, vm::ptr pType, vm::ptr pCh) +s32 cellPamfReaderGetStreamTypeAndChannel(vm::ptr pSelf, vm::ptr pType, vm::ptr pCh) { cellPamf->Warning("cellPamfReaderGetStreamTypeAndChannel(pSelf=0x%x (stream=%d), pType_addr=0x%x, pCh_addr=0x%x", pSelf.addr(), pSelf->stream, pType.addr(), pCh.addr()); + // unclear + *pType = pamfGetStreamType(pSelf, pSelf->stream); *pCh = pamfGetStreamChannel(pSelf, pSelf->stream); return CELL_OK; } -int cellPamfReaderGetEsFilterId(vm::ptr pSelf, vm::ptr pEsFilterId) +s32 cellPamfReaderGetEsFilterId(vm::ptr pSelf, vm::ptr pEsFilterId) { cellPamf->Warning("cellPamfReaderGetEsFilterId(pSelf=0x%x (stream=%d), pEsFilterId_addr=0x%x)", pSelf.addr(), pSelf->stream, pEsFilterId.addr()); - return pamfStreamTypeToEsFilterId(pamfGetStreamType(pSelf, pSelf->stream), - pamfGetStreamChannel(pSelf, pSelf->stream), pEsFilterId); + // always returns CELL_OK + + auto& header = pSelf->pAddr->stream_headers[pSelf->stream]; + pEsFilterId->filterIdMajor = header.fid_major; + pEsFilterId->filterIdMinor = header.fid_minor; + pEsFilterId->supplementalInfo1 = header.type == 0x1b ? 1 : 0; + pEsFilterId->supplementalInfo2 = 0; + return CELL_OK; } -int cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u32 size) +s32 cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u32 size) { cellPamf->Warning("cellPamfReaderGetStreamInfo(pSelf=0x%x, stream=%d, pInfo_addr=0x%x, size=%d)", pSelf.addr(), pSelf->stream, pInfo_addr, size); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - + // TODO (many parameters are wrong) memset(vm::get_ptr(pInfo_addr), 0, size); switch (pamfGetStreamType(pSelf, pSelf->stream)) @@ -509,58 +560,46 @@ int cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u return CELL_OK; } -int cellPamfReaderGetNumberOfEp(vm::ptr pSelf) +u32 cellPamfReaderGetNumberOfEp(vm::ptr pSelf) { cellPamf->Warning("cellPamfReaderGetNumberOfEp(pSelf=0x%x, stream=%d)", pSelf.addr(), pSelf->stream); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - + // cannot return error code return pSelf->pAddr->stream_headers[pSelf->stream].ep_num; } -int cellPamfReaderGetEpIteratorWithIndex(vm::ptr pSelf, u32 epIndex, vm::ptr pIt) +s32 cellPamfReaderGetEpIteratorWithIndex(vm::ptr pSelf, u32 epIndex, vm::ptr pIt) { cellPamf->Todo("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x, stream=%d, epIndex=%d, pIt_addr=0x%x)", pSelf.addr(), pSelf->stream, epIndex, pIt.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - - //TODO: + // TODO return CELL_OK; } -int cellPamfReaderGetEpIteratorWithTimeStamp(vm::ptr pSelf, vm::ptr pTimeStamp, vm::ptr pIt) +s32 cellPamfReaderGetEpIteratorWithTimeStamp(vm::ptr pSelf, vm::ptr pTimeStamp, vm::ptr pIt) { cellPamf->Todo("cellPamfReaderGetEpIteratorWithTimeStamp(pSelf=0x%x, pTimeStamp_addr=0x%x, pIt_addr=0x%x)", pSelf.addr(), pTimeStamp.addr(), pIt.addr()); - if (!pSelf->pAddr) { - return CELL_PAMF_ERROR_INVALID_PAMF; - } - - //TODO: - + // TODO return CELL_OK; } -int cellPamfEpIteratorGetEp(vm::ptr pIt, vm::ptr pEp) +s32 cellPamfEpIteratorGetEp(vm::ptr pIt, vm::ptr pEp) { cellPamf->Todo("cellPamfEpIteratorGetEp(pIt_addr=0x%x, pEp_addr=0x%x)", pIt.addr(), pEp.addr()); - //TODO: - + // always returns CELL_OK + // TODO return CELL_OK; } -int cellPamfEpIteratorMove(vm::ptr pIt, s32 steps, vm::ptr pEp) +s32 cellPamfEpIteratorMove(vm::ptr pIt, s32 steps, vm::ptr pEp) { cellPamf->Todo("cellPamfEpIteratorMove(pIt_addr=0x%x, steps=%d, pEp_addr=0x%x)", pIt.addr(), steps, pEp.addr()); - //TODO: - - return CELL_OK; + // cannot return error code + // TODO + return 0; } void cellPamf_init(Module *pxThis) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/SysCalls/Modules/cellPamf.h index 639b02b662..e740ca006d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.h @@ -168,7 +168,8 @@ struct CellCodecEsFilterId }; // AVC (MPEG4 AVC Video) Specific Information -struct CellPamfAvcInfo { +struct CellPamfAvcInfo +{ u8 profileIdc; u8 levelIdc; u8 frameMbsOnlyFlag; @@ -196,7 +197,8 @@ struct CellPamfAvcInfo { }; // M2V (MPEG2 Video) Specific Information -struct CellPamfM2vInfo { +struct CellPamfM2vInfo +{ u8 profileAndLevelIndication; bool progressiveSequence; u8 videoSignalInfoFlag; @@ -216,27 +218,32 @@ struct CellPamfM2vInfo { }; // LPCM Audio Specific Information -struct CellPamfLpcmInfo { +struct CellPamfLpcmInfo +{ be_t samplingFrequency; u8 numberOfChannels; be_t bitsPerSample; }; // ATRAC3+ Audio Specific Information -struct CellPamfAtrac3plusInfo { +struct CellPamfAtrac3plusInfo +{ be_t samplingFrequency; u8 numberOfChannels; }; // AC3 Audio Specific Information -struct CellPamfAc3Info { +struct CellPamfAc3Info +{ be_t samplingFrequency; u8 numberOfChannels; }; -#pragma pack(push, 1) //file data +#pragma pack(push, 1) // file data -struct PamfStreamHeader_AVC { //AVC specific information +// AVC specific information +struct PamfStreamHeader_AVC +{ u8 profileIdc; u8 levelIdc; u8 unk0; @@ -256,11 +263,15 @@ struct PamfStreamHeader_AVC { //AVC specific information u32 unk12; //0 }; -struct PamfStreamHeader_M2V { //M2V specific information - u8 unknown[32]; //no information yet +// M2V specific information +struct PamfStreamHeader_M2V +{ + u8 unknown[32]; }; -struct PamfStreamHeader_Audio { //Audio specific information +// Audio specific information +struct PamfStreamHeader_Audio +{ u16 unknown; //== 0 u8 channels; //number of channels (1, 2, 6 or 8) u8 freq; //== 1 (always 48000) @@ -268,14 +279,14 @@ struct PamfStreamHeader_Audio { //Audio specific information u8 reserved[27]; //probably nothing }; -struct PamfStreamHeader //48 bytes +struct PamfStreamHeader { //TODO: look for correct beginning of stream header u8 type; //0x1B for video (AVC), 0xDC ATRAC3+, 0x80 LPCM, 0xDD userdata u8 unknown[3]; //0 //TODO: examine stream_ch encoding - u8 stream_id; - u8 private_stream_id; + u8 fid_major; + u8 fid_minor; u8 unknown1; //????? u8 unknown2; //????? //Entry Point Info @@ -285,6 +296,8 @@ struct PamfStreamHeader //48 bytes u8 data[32]; }; +static_assert(sizeof(PamfStreamHeader) == 48, "Invalid PamfStreamHeader size"); + struct PamfHeader { u32 magic; //"PAMF" @@ -317,21 +330,25 @@ struct PamfHeader PamfStreamHeader stream_headers[256]; }; -struct PamfEpHeader { //12 bytes +struct PamfEpHeader +{ be_t value0; //mixed indexN (probably left 2 bits) and nThRefPictureOffset be_t pts_high; be_t pts_low; be_t rpnOffset; }; +static_assert(sizeof(PamfEpHeader) == 12, "Invalid PamfEpHeader size"); + #pragma pack(pop) +// not directly accessed by virtual CPU, fields are unknown struct CellPamfReader { - //this struct can be used in any way, if it is not accessed directly by virtual CPU - //be_t internalData[16]; vm::ptr pAddr; - int stream; + s32 stream; u64 fileSize; u32 internalData[28]; -}; \ No newline at end of file +}; + +static_assert(sizeof(CellPamfReader) == 128, "Invalid CellPamfReader size"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index d923273dde..9482895b54 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -494,11 +494,11 @@ u32 vdecOpen(VideoDecoder* data) { switch ((u64)vdec.ctx->time_base.den + (u64)(vdec.ctx->ticks_per_frame - 1) * 0x100000000ull) { - case 24: case 48 + 0x100000000: frame.frc = CELL_VDEC_FRC_24; break; - case 25: case 50 + 0x100000000: frame.frc = CELL_VDEC_FRC_25; break; - case 30: case 60 + 0x100000000: frame.frc = CELL_VDEC_FRC_30; break; - case 50: case 100 + 0x100000000: frame.frc = CELL_VDEC_FRC_50; break; - case 60: case 120 + 0x100000000: frame.frc = CELL_VDEC_FRC_60; break; + case 24: case 0x100000000ull + 48: frame.frc = CELL_VDEC_FRC_24; break; + case 25: case 0x100000000ull + 50: frame.frc = CELL_VDEC_FRC_25; break; + case 30: case 0x100000000ull + 60: frame.frc = CELL_VDEC_FRC_30; break; + case 50: case 0x100000000ull + 100: frame.frc = CELL_VDEC_FRC_50; break; + case 60: case 0x100000000ull + 120: frame.frc = CELL_VDEC_FRC_60; break; default: { cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); @@ -553,7 +553,7 @@ u32 vdecOpen(VideoDecoder* data) case vdecSetFrameRate: { - cellVdec->Error("vdecSetFrameRate(0x%x)", task.frc); + cellVdec->Warning("vdecSetFrameRate(0x%x)", task.frc); vdec.frc_set = task.frc; break; } From 058eb9e709d1d5c77e1ff736cb70803c0809c730 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Dec 2014 03:21:34 +0300 Subject: [PATCH 4/5] Demuxer improved --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 65 ++--- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 369 +++++++++++++++--------- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 42 +-- rpcs3/Emu/SysCalls/Modules/cellPamf.h | 2 + rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 93 +++--- 5 files changed, 306 insertions(+), 265 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 1dbfb57e23..8cabbae3b4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -19,6 +19,8 @@ extern "C" Module *cellAdec = nullptr; +#define ADEC_ERROR(...) { cellAdec->Error(__VA_ARGS__); Emu.Pause(); return; } // only for decoder thread + AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) , memAddr(addr) @@ -58,38 +60,28 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptrError("AudioDecoder(): unknown type (0x%x)", type); - Emu.Pause(); - return; + ADEC_ERROR("AudioDecoder(): unknown type (0x%x)", type); } } if (!codec) { - cellAdec->Error("AudioDecoder(): avcodec_find_decoder() failed"); - Emu.Pause(); - return; + ADEC_ERROR("AudioDecoder(): avcodec_find_decoder() failed"); } if (!input_format) { - cellAdec->Error("AudioDecoder(): av_find_input_format() failed"); - Emu.Pause(); - return; + ADEC_ERROR("AudioDecoder(): av_find_input_format() failed"); } fmt = avformat_alloc_context(); if (!fmt) { - cellAdec->Error("AudioDecoder(): avformat_alloc_context() failed"); - Emu.Pause(); - return; + ADEC_ERROR("AudioDecoder(): avformat_alloc_context() failed"); } io_buf = (u8*)av_malloc(4096); fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL); if (!fmt->pb) { - cellAdec->Error("AudioDecoder(): avio_alloc_context() failed"); - Emu.Pause(); - return; + ADEC_ERROR("AudioDecoder(): avio_alloc_context() failed"); } } @@ -353,28 +345,16 @@ u32 adecOpen(AudioDecoder* data) 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; + ADEC_ERROR("adecDecodeAu: avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0); } //err = avformat_find_stream_info(adec.fmt, NULL); - //if (err) + //if (err || !adec.fmt->nb_streams) //{ - // cellAdec->Error("adecDecodeAu: avformat_find_stream_info() failed"); - // Emu.Pause(); - // break; - //} - //if (!adec.fmt->nb_streams) - //{ - // cellAdec->Error("adecDecodeAu: no stream found"); - // Emu.Pause(); - // break; + // ADEC_ERROR("adecDecodeAu: avformat_find_stream_info() failed (err=0x%x, nb_streams=%d)", err, adec.fmt->nb_streams); //} if (!avformat_new_stream(adec.fmt, adec.codec)) { - cellAdec->Error("adecDecodeAu: avformat_new_stream() failed"); - Emu.Pause(); - break; + ADEC_ERROR("adecDecodeAu: avformat_new_stream() failed"); } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data @@ -387,9 +367,7 @@ u32 adecOpen(AudioDecoder* data) } if (err || opts) { - cellAdec->Error("adecDecodeAu: avcodec_open2() failed"); - Emu.Pause(); - break; + ADEC_ERROR("adecDecodeAu: avcodec_open2() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0); } adec.just_started = false; } @@ -433,9 +411,7 @@ u32 adecOpen(AudioDecoder* data) if (!frame.data) { - cellAdec->Error("adecDecodeAu: av_frame_alloc() failed"); - Emu.Pause(); - break; + ADEC_ERROR("adecDecodeAu: av_frame_alloc() failed"); } int got_frame = 0; @@ -444,7 +420,7 @@ u32 adecOpen(AudioDecoder* data) if (decode <= 0) { - if (!last_frame && decode < 0) + if (decode < 0) { cellAdec->Error("adecDecodeAu: AU decoding error(0x%x)", decode); } @@ -469,9 +445,7 @@ u32 adecOpen(AudioDecoder* data) case AV_SAMPLE_FMT_S16P: break; default: { - cellAdec->Error("adecDecodeAu: unsupported frame format(%d)", frame.data->format); - Emu.Pause(); - break; + ADEC_ERROR("adecDecodeAu: unsupported frame format(%d)", frame.data->format); } } frame.auAddr = task.au.addr; @@ -494,13 +468,14 @@ u32 adecOpen(AudioDecoder* data) break; } - case adecClose: break; + case adecClose: + { + break; + } default: { - cellAdec->Error("Audio Decoder thread error: unknown task(%d)", task.type); - Emu.Pause(); - return; + ADEC_ERROR("Audio Decoder thread error: unknown task(%d)", task.type); } } } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 57ee842309..d97603efa6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -10,52 +10,96 @@ Module *cellDmux = nullptr; +#define DMUX_ERROR(...) { cellDmux->Error(__VA_ARGS__); Emu.Pause(); return; } // only for demuxer thread + PesHeader::PesHeader(DemuxerStream& stream) - : pts(0xffffffffffffffffull) - , dts(0xffffffffffffffffull) + : pts(CODEC_TS_INVALID) + , dts(CODEC_TS_INVALID) , size(0) , has_ts(false) + , is_ok(false) { u16 header; - stream.get(header); - stream.get(size); - if (size) + if (!stream.get(header)) + { + DMUX_ERROR("PesHeader(): end of stream (header)"); + } + if (!stream.get(size)) + { + DMUX_ERROR("PesHeader(): end of stream (size)"); + } + if (!stream.check(size)) + { + DMUX_ERROR("PesHeader(): end of stream (size=%d)", size); + } + + u8 pos = 0; + while (pos++ < size) { - u8 empty = 0; u8 v; - while (true) + if (!stream.get(v)) { - stream.get(v); - if (v != 0xFF) break; // skip padding bytes - empty++; - if (empty == size) return; - }; + return; // should never occur + } - if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only + if (v == 0xff) // skip padding bytes { - has_ts = true; + continue; + } + + if ((v & 0xf0) == 0x20 && (size - pos) >= 4) // pts only + { + pos += 4; pts = stream.get_ts(v); - stream.skip(size - empty - 5); + has_ts = true; + } + else if ((v & 0xf0) == 0x30 && (size - pos) >= 9) // pts and dts + { + pos += 5; + pts = stream.get_ts(v); + stream.get(v); + has_ts = true; + + if ((v & 0xf0) != 0x10) + { + cellDmux->Error("PesHeader(): dts not found (v=0x%x, size=%d, pos=%d)", v, size, pos - 1); + stream.skip(size - pos); + return; + } + pos += 4; + dts = stream.get_ts(v); } else { - has_ts = true; - if ((v & 0xF0) != 0x30 || (size - empty) < 10) - { - cellDmux->Error("PesHeader(): pts not found"); - Emu.Pause(); - } - pts = stream.get_ts(v); - stream.get(v); - if ((v & 0xF0) != 0x10) - { - cellDmux->Error("PesHeader(): dts not found"); - Emu.Pause(); - } - dts = stream.get_ts(v); - stream.skip(size - empty - 10); + cellDmux->Notice("PesHeader(): unknown code (v=0x%x, size=%d, pos=%d)", v, size, pos - 1); + stream.skip(size - pos); + pos = size; + break; } } + + is_ok = true; +} + +ElementaryStream::ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec) + : dmux(dmux) + , memAddr(a128(addr)) + , memSize(size - (addr - memAddr)) + , fidMajor(fidMajor) + , fidMinor(fidMinor) + , sup1(sup1) + , sup2(sup2) + , cbFunc(cbFunc) + , cbArg(cbArg) + , spec(spec) + , put(memAddr) + , put_count(0) + , got_count(0) + , released(0) + , raw_pos(0) + , last_dts(CODEC_TS_INVALID) + , last_pts(CODEC_TS_INVALID) +{ } bool ElementaryStream::is_full(u32 space) @@ -70,7 +114,8 @@ bool ElementaryStream::is_full(u32 space) u32 first = 0; if (!entries.Peek(first, &dmux->is_closed) || !first) { - throw "es::is_full() error: entries.Peek() failed"; + assert(!"es::is_full() error: entries.Peek() failed"); + return false; } else if (first >= put) { @@ -103,10 +148,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra { std::lock_guard lock(m_mutex); - if (is_full(size)) - { - throw "es::push_au() error: buffer is full"; - } + assert(!is_full(size)); if (put + size + 128 > memAddr + memSize) { @@ -148,7 +190,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra } if (!entries.Push(addr, &dmux->is_closed)) { - throw "es::push_au() error: entries.Push() failed"; + assert(!"es::push_au() error: entries.Push() failed"); } } @@ -277,13 +319,13 @@ u32 dmuxOpen(Demuxer* data) DemuxerTask task; DemuxerStream stream = {}; - ElementaryStream* esALL[192]; memset(esALL, 0, sizeof(esALL)); - ElementaryStream** esAVC = &esALL[0]; // AVC (max 16) - ElementaryStream** esM2V = &esALL[16]; // MPEG-2 (max 16) + ElementaryStream* esALL[96]; memset(esALL, 0, sizeof(esALL)); + ElementaryStream** esAVC = &esALL[0]; // AVC (max 16 minus M2V count) + ElementaryStream** esM2V = &esALL[16]; // M2V (max 16 minus AVC count) ElementaryStream** esDATA = &esALL[32]; // user data (max 16) - ElementaryStream** esATX = &esALL[48]; // ATRAC3+ (max 48) - ElementaryStream** esAC3 = &esALL[96]; // AC3 (max 48) - ElementaryStream** esPCM = &esALL[144]; // LPCM (max 48) + ElementaryStream** esATX = &esALL[48]; // ATRAC3+ (max 16) + ElementaryStream** esAC3 = &esALL[64]; // AC3 (max 16) + ElementaryStream** esPCM = &esALL[80]; // LPCM (max 16) u32 cb_add = 0; @@ -299,7 +341,6 @@ u32 dmuxOpen(Demuxer* data) // default task (demuxing) (if there is no other work) be_t code; be_t len; - u8 ch; if (!stream.peek(code)) { @@ -310,53 +351,104 @@ u32 dmuxOpen(Demuxer* data) dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg); dmux.is_running = false; + continue; } - else switch (code.ToLE()) + + switch (code.ToLE()) { case PACK_START_CODE: { + if (!stream.check(14)) + { + DMUX_ERROR("End of stream (PACK_START_CODE)"); + } stream.skip(14); + break; } - break; case SYSTEM_HEADER_START_CODE: { + if (!stream.check(18)) + { + DMUX_ERROR("End of stream (SYSTEM_HEADER_START_CODE)"); + } stream.skip(18); + break; } - break; case PADDING_STREAM: { + if (!stream.check(6)) + { + DMUX_ERROR("End of stream (PADDING_STREAM)"); + } stream.skip(4); stream.get(len); + + if (!stream.check(len.ToLE())) + { + DMUX_ERROR("End of stream (PADDING_STREAM, len=%d)", len.ToLE()); + } stream.skip(len); + break; } - break; case PRIVATE_STREAM_2: { + if (!stream.check(6)) + { + DMUX_ERROR("End of stream (PRIVATE_STREAM_2)"); + } stream.skip(4); stream.get(len); + + cellDmux->Notice("PRIVATE_STREAM_2 (%d)", len.ToLE()); + + if (!stream.check(len.ToLE())) + { + DMUX_ERROR("End of stream (PRIVATE_STREAM_2, len=%d)", len.ToLE()); + } stream.skip(len); + break; } - break; case PRIVATE_STREAM_1: { + // audio and user data stream DemuxerStream backup = stream; - // audio AT3+ (and probably LPCM or user data) + if (!stream.check(6)) + { + DMUX_ERROR("End of stream (PRIVATE_STREAM_1)"); + } stream.skip(4); stream.get(len); - PesHeader pes(stream); + if (!stream.check(len.ToLE())) + { + DMUX_ERROR("End of stream (PRIVATE_STREAM_1, len=%d)", len.ToLE()); + } - // read additional header: - stream.peek(ch); // ??? - //stream.skip(4); - //pes.size += 4; + const PesHeader pes(stream); + if (!pes.is_ok) + { + DMUX_ERROR("PesHeader error (PRIVATE_STREAM_1, len=%d)", len.ToLE()); + } - if (esATX[ch]) + if (len < pes.size + 4) + { + DMUX_ERROR("End of block (PRIVATE_STREAM_1, PesHeader + fid_minor, len=%d)", len.ToLE()); + } + len -= pes.size + 4; + + u8 fid_minor; + if (!stream.get(fid_minor)) + { + DMUX_ERROR("End of stream (PRIVATE_STREAM1, fid_minor)"); + } + + const u32 ch = fid_minor % 16; + if ((fid_minor & -0x10) == 0 && esATX[ch]) { ElementaryStream& es = *esATX[ch]; if (es.raw_data.size() > 1024 * 1024) @@ -366,8 +458,12 @@ u32 dmuxOpen(Demuxer* data) continue; } - stream.skip(4); - len -= 4; + if (len < 3 || !stream.check(3)) + { + DMUX_ERROR("End of block (ATX, unknown header, len=%d)", len.ToLE()); + } + len -= 3; + stream.skip(3); if (pes.has_ts) { @@ -375,7 +471,7 @@ u32 dmuxOpen(Demuxer* data) es.last_pts = pes.pts; } - es.push(stream, len - pes.size - 3); + es.push(stream, len); while (true) { @@ -386,9 +482,7 @@ u32 dmuxOpen(Demuxer* data) if (data[0] != 0x0f || data[1] != 0xd0) { - cellDmux->Error("ATX: 0x0fd0 header not found (ats=0x%llx)", ((be_t*)data)->ToLE()); - Emu.Pause(); - return; + DMUX_ERROR("ATX: 0x0fd0 header not found (ats=0x%llx)", ((be_t*)data)->ToLE()); } u32 frame_size = ((((u32)data[2] & 0x3) << 8) | (u32)data[3]) * 8 + 8; @@ -399,6 +493,8 @@ u32 dmuxOpen(Demuxer* data) es.push_au(frame_size + 8, es.last_dts, es.last_pts, stream.userdata, false /* TODO: set correct value */, 0); + cellDmux->Notice("ATX AU pushed (ats=0x%llx, frame_size=%d)", ((be_t*)data)->ToLE(), frame_size); + auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; @@ -407,26 +503,48 @@ u32 dmuxOpen(Demuxer* data) } else { - stream.skip(len - pes.size - 3); + cellDmux->Notice("PRIVATE_STREAM_1 (len=%d, fid_minor=0x%x)", len.ToLE(), fid_minor); + stream.skip(len); } + break; } - break; case 0x1e0: case 0x1e1: case 0x1e2: case 0x1e3: case 0x1e4: case 0x1e5: case 0x1e6: case 0x1e7: case 0x1e8: case 0x1e9: case 0x1ea: case 0x1eb: case 0x1ec: case 0x1ed: case 0x1ee: case 0x1ef: { - // video AVC - ch = code - 0x1e0; + // video stream (AVC or M2V) + DemuxerStream backup = stream; + + if (!stream.check(6)) + { + DMUX_ERROR("End of stream (video, code=0x%x)", code.ToLE()); + } + stream.skip(4); + stream.get(len); + + if (!stream.check(len.ToLE())) + { + DMUX_ERROR("End of stream (video, code=0x%x, len=%d)", code.ToLE(), len.ToLE()); + } + + const PesHeader pes(stream); + if (!pes.is_ok) + { + DMUX_ERROR("PesHeader error (video, code=0x%x, len=%d)", code.ToLE(), len.ToLE()); + } + + if (len < pes.size + 3) + { + DMUX_ERROR("End of block (video, code=0x%x, PesHeader)", code.ToLE()); + } + len -= pes.size + 3; + + const u32 ch = code.ToLE() % 16; if (esAVC[ch]) { ElementaryStream& es = *esAVC[ch]; - DemuxerStream backup = stream; - - stream.skip(4); - stream.get(len); - PesHeader pes(stream); const u32 old_size = (u32)es.raw_data.size(); if (es.isfull(old_size)) @@ -436,9 +554,9 @@ u32 dmuxOpen(Demuxer* data) continue; } - if ((pes.has_ts && old_size) || old_size >= 0x70000) + if ((pes.has_ts && old_size) || old_size >= 0x69800) { - // push AU if it becomes too big or the next packet contains ts data + // push AU if it becomes too big or the next packet contains PTS/DTS es.push_au(old_size, es.last_dts, es.last_pts, stream.userdata, false /* TODO: set correct value */, 0); // callback @@ -456,53 +574,34 @@ u32 dmuxOpen(Demuxer* data) } // reconstruction of MPEG2-PS stream for vdec module - const u32 size = len + 6 /*- pes.size - 3*/; + const u32 size = (u32)len.ToLE() + pes.size + 9; stream = backup; es.push(stream, size); } else { - stream.skip(4); - stream.get(len); + cellDmux->Notice("Video stream (code=0x%x, len=%d)", code.ToLE(), len.ToLE()); stream.skip(len); } - } - break; - - case 0x1c0: case 0x1c1: case 0x1c2: case 0x1c3: - case 0x1c4: case 0x1c5: case 0x1c6: case 0x1c7: - case 0x1c8: case 0x1c9: case 0x1ca: case 0x1cb: - case 0x1cc: case 0x1cd: case 0x1ce: case 0x1cf: - case 0x1d0: case 0x1d1: case 0x1d2: case 0x1d3: - case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7: - case 0x1d8: case 0x1d9: case 0x1da: case 0x1db: - case 0x1dc: case 0x1dd: case 0x1de: case 0x1df: - { - // unknown - cellDmux->Warning("Unknown MPEG stream found"); - stream.skip(4); - stream.get(len); - stream.skip(len); - } - break; - - case USER_DATA_START_CODE: - { - cellDmux->Error("USER_DATA_START_CODE found"); - Emu.Pause(); - return; + break; } default: { + if ((code.ToLE() & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) + { + DMUX_ERROR("Unknown code found (0x%x)", code.ToLE()); + } + // search stream.skip(1); } } + continue; } - // wait for task with yielding (if no default work) + // wait for task if no work if (!dmux.job.Pop(task, &dmux.is_closed)) { break; // Emu is stopped @@ -515,7 +614,7 @@ u32 dmuxOpen(Demuxer* data) if (task.stream.discontinuity) { cellDmux->Warning("dmuxSetStream (beginning)"); - for (u32 i = 0; i < 192; i++) + for (u32 i = 0; i < sizeof(esALL) / sizeof(esALL[0]); i++) { if (esALL[i]) { @@ -527,8 +626,8 @@ u32 dmuxOpen(Demuxer* data) stream = task.stream; //LOG_NOTICE(HLE, "*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", //stream.addr, stream.size, stream.discontinuity, stream.userdata); + break; } - break; case dmuxResetStream: case dmuxResetStreamAndWaitDone: @@ -543,44 +642,55 @@ u32 dmuxOpen(Demuxer* data) //if (task.type == dmuxResetStreamAndWaitDone) //{ //} + break; } - break; case dmuxEnableEs: { ElementaryStream& es = *task.es.es_ptr; - if (es.fidMajor >= 0xe0 && - es.fidMajor <= 0xef && - es.fidMinor == 0 && - es.sup1 == 1 && - es.sup2 == 0) + + // TODO: uncomment when ready to use + if ((es.fidMajor & -0x10) == 0xe0 && es.fidMinor == 0 && es.sup1 == 1 && !es.sup2) { - esAVC[es.fidMajor - 0xe0] = task.es.es_ptr; + esAVC[es.fidMajor % 16] = task.es.es_ptr; } - else if (es.fidMajor == 0xbd && - es.fidMinor == 0 && - es.sup1 == 0 && - es.sup2 == 0) + //else if ((es.fidMajor & -0x10) == 0xe0 && es.fidMinor == 0 && !es.sup1 && !es.sup2) + //{ + // esM2V[es.fidMajor % 16] = task.es.es_ptr; + //} + else if (es.fidMajor == 0xbd && (es.fidMinor & -0x10) == 0 && !es.sup1 && !es.sup2) { - esATX[0] = task.es.es_ptr; + esATX[es.fidMinor % 16] = task.es.es_ptr; } + //else if (es.fidMajor == 0xbd && (es.fidMinor & -0x10) == 0x20 && !es.sup1 && !es.sup2) + //{ + // esDATA[es.fidMinor % 16] = task.es.es_ptr; + //} + //else if (es.fidMajor == 0xbd && (es.fidMinor & -0x10) == 0x30 && !es.sup1 && !es.sup2) + //{ + // esAC3[es.fidMinor % 16] = task.es.es_ptr; + //} + //else if (es.fidMajor == 0xbd && (es.fidMinor & -0x10) == 0x40 && !es.sup1 && !es.sup2) + //{ + // esPCM[es.fidMinor % 16] = task.es.es_ptr; + //} else { - cellDmux->Warning("dmuxEnableEs: (TODO) unsupported filter (0x%x, 0x%x, 0x%x, 0x%x)", es.fidMajor, es.fidMinor, es.sup1, es.sup2); + DMUX_ERROR("dmuxEnableEs: unknown filter (0x%x, 0x%x, 0x%x, 0x%x)", es.fidMajor, es.fidMinor, es.sup1, es.sup2); } es.dmux = &dmux; + break; } - break; case dmuxDisableEs: { ElementaryStream& es = *task.es.es_ptr; if (es.dmux != &dmux) { - cellDmux->Warning("dmuxDisableEs: invalid elementary stream"); - break; + DMUX_ERROR("dmuxDisableEs: invalid elementary stream"); } - for (u32 i = 0; i < 192; i++) + + for (u32 i = 0; i < sizeof(esALL) / sizeof(esALL[0]); i++) { if (esALL[i] == &es) { @@ -589,15 +699,15 @@ u32 dmuxOpen(Demuxer* data) } es.dmux = nullptr; Emu.GetIdManager().RemoveID(task.es.es); + break; } - break; case dmuxFlushEs: { ElementaryStream& es = *task.es.es_ptr; const u32 old_size = (u32)es.raw_data.size(); - if (old_size && (es.fidMajor & 0xf0) == 0xe0) + if (old_size && (es.fidMajor & -0x10) == 0xe0) { // TODO (it's only for AVC, some ATX data may be lost) while (es.isfull(old_size)) @@ -626,22 +736,23 @@ u32 dmuxOpen(Demuxer* data) esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE; esMsg->supplementalInfo = stream.userdata; es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg); + break; } - break; case dmuxResetEs: { task.es.es_ptr->reset(); + break; + } + + case dmuxClose: + { + break; } - break; - - case dmuxClose: break; default: { - cellDmux->Error("Demuxer thread error: unknown task(%d)", task.type); - Emu.Pause(); - return; + DMUX_ERROR("Demuxer thread error: unknown task (0x%x)", task.type); } } } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 5da9258bb0..e2212a3385 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -288,15 +288,8 @@ enum PACKET_START_CODE_MASK = 0xffffff00, PACKET_START_CODE_PREFIX = 0x00000100, - USER_DATA_START_CODE = 0x000001b2, - SEQUENCE_START_CODE = 0x000001b3, - EXT_START_CODE = 0x000001b5, - SEQUENCE_END_CODE = 0x000001b7, - GOP_START_CODE = 0x000001b8, - ISO_11172_END_CODE = 0x000001b9, PACK_START_CODE = 0x000001ba, SYSTEM_HEADER_START_CODE = 0x000001bb, - PROGRAM_STREAM_MAP = 0x000001bc, PRIVATE_STREAM_1 = 0x000001bd, PADDING_STREAM = 0x000001be, PRIVATE_STREAM_2 = 0x000001bf, @@ -336,6 +329,11 @@ struct DemuxerStream size = size > count ? size - count : 0; } + bool check(u32 count) const + { + return count <= size; + } + u64 get_ts(u8 c) { u8 v[4]; get((u32&)v); @@ -345,12 +343,6 @@ struct DemuxerStream (((u64)v[1] & 0x7e) << 15) | (((u64)v[2]) << 7) | ((u64)v[3] >> 1); } - - u64 get_ts() - { - u8 v; get(v); - return get_ts(v); - } }; struct PesHeader @@ -359,6 +351,7 @@ struct PesHeader u64 dts; u8 size; bool has_ts; + bool is_ok; PesHeader(DemuxerStream& stream); }; @@ -446,6 +439,8 @@ class ElementaryStream bool is_full(u32 space); public: + ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec); + Demuxer* dmux; u32 id; const u32 memAddr; @@ -465,27 +460,6 @@ public: void push(DemuxerStream& stream, u32 size); // called by demuxer thread (not multithread-safe) - ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec) - : dmux(dmux) - , memAddr(a128(addr)) - , memSize(size - (addr - memAddr)) - , fidMajor(fidMajor) - , fidMinor(fidMinor) - , sup1(sup1) - , sup2(sup2) - , cbFunc(cbFunc) - , cbArg(cbArg) - , spec(spec) - , put(memAddr) - , put_count(0) - , got_count(0) - , released(0) - , raw_pos(0) - , last_dts(0xffffffffffffffffull) - , last_pts(0xffffffffffffffffull) - { - } - bool isfull(u32 space); void push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool rap, u32 specific); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/SysCalls/Modules/cellPamf.h index e740ca006d..681c43ca4e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.h @@ -141,6 +141,8 @@ struct CellCodecTimeStamp be_t lower; }; +static const u64 CODEC_TS_INVALID = 0xffffffffffffffffull; + // Entry point information struct CellPamfEp { diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 9482895b54..95f9285f86 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -19,6 +19,8 @@ extern "C" Module *cellVdec = nullptr; +#define VDEC_ERROR(...) { cellVdec->Error(__VA_ARGS__); Emu.Pause(); return; } // only for decoder thread + VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) , profile(profile) @@ -62,38 +64,28 @@ VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 si } default: { - cellVdec->Error("VideoDecoder(): unknown type (0x%x)", type); - Emu.Pause(); - return; + VDEC_ERROR("VideoDecoder(): unknown type (0x%x)", type); } } if (!codec) { - cellVdec->Error("VideoDecoder(): avcodec_find_decoder() failed"); - Emu.Pause(); - return; + VDEC_ERROR("VideoDecoder(): avcodec_find_decoder() failed"); } if (!input_format) { - cellVdec->Error("VideoDecoder(): av_find_input_format() failed"); - Emu.Pause(); - return; + VDEC_ERROR("VideoDecoder(): av_find_input_format() failed"); } fmt = avformat_alloc_context(); if (!fmt) { - cellVdec->Error("VideoDecoder(): avformat_alloc_context() failed"); - Emu.Pause(); - return; + VDEC_ERROR("VideoDecoder(): avformat_alloc_context() failed"); } io_buf = (u8*)av_malloc(4096); fmt->pb = avio_alloc_context(io_buf, 4096, 0, this, vdecRead, NULL, NULL); if (!fmt->pb) { - cellVdec->Error("VideoDecoder(): avio_alloc_context() failed"); - Emu.Pause(); - return; + VDEC_ERROR("VideoDecoder(): avio_alloc_context() failed"); } } @@ -333,46 +325,40 @@ u32 vdecOpen(VideoDecoder* data) } else if (vdec.just_started) // deferred initialization { - err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); - if (err) + AVDictionary* opts = nullptr; + av_dict_set(&opts, "probesize", "4096", 0); + err = avformat_open_input(&vdec.fmt, NULL, NULL, &opts); + if (err || opts) { - cellVdec->Error("vdecDecodeAu: avformat_open_input() failed"); - Emu.Pause(); - break; + VDEC_ERROR("vdecDecodeAu: avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0); } if (vdec.type == CELL_VDEC_CODEC_TYPE_DIVX) { err = avformat_find_stream_info(vdec.fmt, NULL); if (err || !vdec.fmt->nb_streams) { - cellVdec->Error("vdecDecodeAu: avformat_find_stream_info() failed (err=0x%x)", err); - Emu.Pause(); - break; + VDEC_ERROR("vdecDecodeAu: avformat_find_stream_info() failed (err=0x%x, nb_streams=%d)", err, vdec.fmt->nb_streams); } } else { if (!avformat_new_stream(vdec.fmt, vdec.codec)) { - cellVdec->Error("vdecDecodeAu: avformat_new_stream() failed"); - Emu.Pause(); - break; + VDEC_ERROR("vdecDecodeAu: avformat_new_stream() failed"); } } vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data - AVDictionary* opts = nullptr; + opts = nullptr; av_dict_set(&opts, "refcounted_frames", "1", 0); { std::lock_guard lock(g_mutex_avcodec_open2); // not multithread-safe (???) err = avcodec_open2(vdec.ctx, vdec.codec, &opts); } - if (err) + if (err || opts) { - cellVdec->Error("vdecDecodeAu: avcodec_open2() failed"); - Emu.Pause(); - break; + VDEC_ERROR("vdecDecodeAu: avcodec_open2() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0); } vdec.just_started = false; @@ -417,9 +403,7 @@ u32 vdecOpen(VideoDecoder* data) if (!frame.data) { - cellVdec->Error("vdecDecodeAu: av_frame_alloc() failed"); - Emu.Pause(); - break; + VDEC_ERROR("vdecDecodeAu: av_frame_alloc() failed"); } int got_picture = 0; @@ -428,7 +412,7 @@ u32 vdecOpen(VideoDecoder* data) if (decode <= 0) { - if (!last_frame && decode < 0) + if (decode < 0) { cellVdec->Error("vdecDecodeAu: AU decoding error(0x%x)", decode); } @@ -439,14 +423,12 @@ u32 vdecOpen(VideoDecoder* data) { if (frame.data->interlaced_frame) { - cellVdec->Error("vdecDecodeAu: interlaced frames not supported (0x%x)", frame.data->interlaced_frame); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: interlaced frames not supported (0x%x)", frame.data->interlaced_frame); } if (frame.data->repeat_pict) { - cellVdec->Error("vdecDecodeAu: repeated frames not supported (0x%x)", frame.data->repeat_pict); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: repeated frames not supported (0x%x)", frame.data->repeat_pict); } if (vdec.frc_set) @@ -467,8 +449,7 @@ u32 vdecOpen(VideoDecoder* data) case CELL_VDEC_FRC_60: vdec.last_pts += 90000 / 60; break; default: { - cellVdec->Error("vdecDecodeAu: invalid frame rate code set (0x%x)", vdec.frc_set); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: invalid frame rate code set (0x%x)", vdec.frc_set); } } @@ -501,8 +482,7 @@ u32 vdecOpen(VideoDecoder* data) case 60: case 0x100000000ull + 120: frame.frc = CELL_VDEC_FRC_60; break; default: { - cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: unsupported time_base.den (%d/1, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); } } } @@ -522,14 +502,12 @@ u32 vdecOpen(VideoDecoder* data) } else { - cellVdec->Error("vdecDecodeAu: unsupported time_base.den (%d/1001, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: unsupported time_base.den (%d/1001, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame); } } else { - cellVdec->Error("vdecDecodeAu: unsupported time_base.num (%d)", vdec.ctx->time_base.num); - Emu.Pause(); + VDEC_ERROR("vdecDecodeAu: unsupported time_base.num (%d)", vdec.ctx->time_base.num); } } @@ -558,13 +536,14 @@ u32 vdecOpen(VideoDecoder* data) break; } - case vdecClose: break; + case vdecClose: + { + break; + } default: { - cellVdec->Error("Video Decoder thread error: unknown task(%d)", task.type); - Emu.Pause(); - return; + VDEC_ERROR("Video Decoder thread error: unknown task(%d)", task.type); } } } @@ -739,7 +718,7 @@ int cellVdecGetPicture(u32 handle, vm::ptr format, vm:: int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1); if (err < 0) { - cellVdec->Error("cellVdecGetPicture: av_image_copy_to_buffer failed(%d)", err); + cellVdec->Error("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err); Emu.Pause(); } } @@ -782,12 +761,12 @@ int cellVdecGetPicItem(u32 handle, vm::ptr picItem_ptr) info->auNum = 1; info->auPts[0].lower = (u32)vf.pts; info->auPts[0].upper = vf.pts >> 32; - info->auPts[1].lower = 0xffffffff; - info->auPts[1].upper = 0xffffffff; + info->auPts[1].lower = (u32)CODEC_TS_INVALID; + info->auPts[1].upper = (u32)CODEC_TS_INVALID; info->auDts[0].lower = (u32)vf.dts; info->auDts[0].upper = vf.dts >> 32; - info->auDts[1].lower = 0xffffffff; - info->auDts[1].upper = 0xffffffff; + info->auDts[1].lower = (u32)CODEC_TS_INVALID; + info->auDts[1].upper = (u32)CODEC_TS_INVALID; info->auUserData[0] = vf.userdata; info->auUserData[1] = 0; info->status = CELL_OK; @@ -836,7 +815,7 @@ int cellVdecGetPicItem(u32 handle, vm::ptr picItem_ptr) case CELL_VDEC_FRC_50: avc->frameRateCode = CELL_VDEC_AVC_FRC_50; break; case CELL_VDEC_FRC_60000DIV1001: avc->frameRateCode = CELL_VDEC_AVC_FRC_60000DIV1001; break; case CELL_VDEC_FRC_60: avc->frameRateCode = CELL_VDEC_AVC_FRC_60; break; - default: cellVdec->Error("cellVdecGetPicItem(AVC): unknown frc value (0x%x)", vf.frc); break; + default: cellVdec->Error("cellVdecGetPicItem(AVC): unknown frc value (0x%x)", vf.frc); } avc->fixed_frame_rate_flag = true; From 154433b2e92bae3821d05910c29b9008a59f133f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Dec 2014 04:27:27 +0300 Subject: [PATCH 5/5] Bugfix --- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index d97603efa6..96e7eddaa9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -71,7 +71,7 @@ PesHeader::PesHeader(DemuxerStream& stream) } else { - cellDmux->Notice("PesHeader(): unknown code (v=0x%x, size=%d, pos=%d)", v, size, pos - 1); + cellDmux->Warning("PesHeader(): unknown code (v=0x%x, size=%d, pos=%d)", v, size, pos - 1); stream.skip(size - pos); pos = size; break; @@ -493,7 +493,7 @@ u32 dmuxOpen(Demuxer* data) es.push_au(frame_size + 8, es.last_dts, es.last_pts, stream.userdata, false /* TODO: set correct value */, 0); - cellDmux->Notice("ATX AU pushed (ats=0x%llx, frame_size=%d)", ((be_t*)data)->ToLE(), frame_size); + //cellDmux->Notice("ATX AU pushed (ats=0x%llx, frame_size=%d)", ((be_t*)data)->ToLE(), frame_size); auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;