diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index 8a2b6fb941..b92d67e614 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -26,6 +26,7 @@ template > class SMutexBase { + static_assert(sizeof(T) == sizeof(std::atomic), "Invalid SMutexBase type"); std::atomic owner; public: diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index e25cb587b9..8c5915d6ff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -714,13 +714,13 @@ int cellAudioSetNotifyEventQueue(u64 key) m_config.event_key = key; - EventQueue* eq; + /*EventQueue* eq; if (!Emu.GetEventManager().GetEventQueue(key, eq)) { return CELL_AUDIO_ERROR_PARAM; - } + }*/ - // TODO: connect port + // TODO: connect port (?????) return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 99346a4252..aadfaf1a85 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -167,6 +167,7 @@ u32 dmuxOpen(Demuxer* data) stream = backup; continue; } + //stream = backup; es.push(stream, len - pes.size - 3, pes); } else diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index fad19dd63a..51e805ab07 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -373,12 +373,11 @@ struct PesHeader , dts(0xffffffffffffffff) , ch(0) , size(0) - , new_au(false) + , new_au(true) { u16 header; stream.get(header); stream.get(size); - new_au = true; if (size) { //ConLog.Write(">>>>> Pes Header (size=%d)", size); @@ -571,7 +570,7 @@ public: { SMutexLocker lock(mutex); //ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - if (isfull()) + if (isfull()) { ConLog.Error("ElementaryStream::push(): buffer is full"); Emu.Pause(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 2ded407750..c0dd39dcfe 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -6,6 +6,7 @@ extern "C" { #include "libavcodec\avcodec.h" +#include "libavformat\avformat.h" #include "libavutil\imgutils.h" } @@ -14,6 +15,29 @@ extern "C" void cellVdec_init(); Module cellVdec(0x0005, cellVdec_init); +int vdecRead(void* opaque, u8* buf, int buf_size) +{ + VideoDecoder& vdec = *(VideoDecoder*)opaque; + + if (vdec.reader.size < (u32)buf_size) buf_size = vdec.reader.size; + if (!buf_size) + { + return AVERROR_EOF; + } + else if (!Memory.CopyToReal(buf, vdec.reader.addr, buf_size)) + { + ConLog.Error("vdecRead: data reading failed (buf_size=0x%x)", buf_size); + Emu.Pause(); + return 0; + } + else + { + vdec.reader.addr += buf_size; + vdec.reader.size -= buf_size; + return buf_size; + } +} + u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 */, mem_ptr_t attr) { switch (type) // TODO: check profile levels @@ -98,42 +122,66 @@ u32 vdecOpen(VideoDecoder* data) { vdecPacket(u32 size) { - av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE); + av_init_packet(this); + data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - this->size -= FF_INPUT_BUFFER_PADDING_SIZE; // ???????????????????? + this->size = size + FF_INPUT_BUFFER_PADDING_SIZE; } ~vdecPacket() { - av_free_packet(this); + av_free(data); + //av_free_packet(this); } } au(task.size); - if (task.pts || task.dts) + if ((task.pts || task.dts) && task.pts != ~0 && task.dts != ~0) { vdec.pts = task.pts; vdec.dts = task.dts; + au.pts = vdec.pts; + au.dts = vdec.dts; + au.flags = AV_PKT_FLAG_KEY; } - au.pts = vdec.pts; - au.dts = vdec.dts; - + else + { + au.pts = vdec.pts; + au.dts = vdec.dts; + } + if (task.mode != CELL_VDEC_DEC_MODE_NORMAL) { ConLog.Error("vdecDecodeAu: unsupported decoding mode(%d)", task.mode); break; } + vdec.reader.addr = task.addr; + vdec.reader.size = task.size; + if (!Memory.CopyToReal(au.data, task.addr, task.size)) { ConLog.Error("vdecDecodeAu: AU data accessing failed(addr=0x%x, size=0x%x)", task.addr, task.size); break; } + /*{ + wxFile dump; + dump.Open(wxString::Format("0x%llx-0x%llx.dump", au.pts, au.dts), wxFile::write); + dump.Write(au.data, task.size + FF_INPUT_BUFFER_PADDING_SIZE); + dump.Close(); + }*/ + int got_picture = 0; //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED; //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS; + vdec.ctx->flags2 |= CODEC_FLAG2_LOCAL_HEADER; + vdec.ctx->codec_tag = *(u32*)"DAVC"; + //vdec.ctx->stream_codec_tag = *(u32*)"DAVC"; + + //avcodec_get_frame_defaults(vdec.frame); + int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au); if (decode < 0) @@ -141,23 +189,11 @@ u32 vdecOpen(VideoDecoder* data) ConLog.Error("vdecDecodeAu: AU decoding error(%d)", decode); break; } - - ConLog.Write("Frame decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, result=0x%x)", - au.pts, au.dts, task.addr, decode); - - - Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, 0, vdec.cbArg); - cb.Branch(false); if (got_picture) { ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, vdec.pts, vdec.dts); - - vdec.pts += 3003; - vdec.dts += 3003; - + /*if (vdec.out_data[0]) av_freep(vdec.out_data[0]); int err = av_image_alloc(vdec.out_data, vdec.linesize, vdec.ctx->width, vdec.ctx->height, vdec.ctx->pix_fmt, 1); @@ -167,15 +203,13 @@ u32 vdecOpen(VideoDecoder* data) Emu.Pause(); return; } - + vdec.buf_size = err; av_image_copy(vdec.out_data, vdec.linesize, (const u8**)(vdec.frame->data), vdec.frame->linesize, vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height);*/ vdec.buf_size = a128(av_image_get_buffer_size(vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height, 1)); - vdec.dts = task.dts; - vdec.pts = task.pts; vdec.userdata = task.userData; vdec.has_picture = true; @@ -184,6 +218,13 @@ u32 vdecOpen(VideoDecoder* data) cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg); cb.Branch(false); } + + ConLog.Write("Frame decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, result=0x%x)", au.pts, au.dts, task.addr, decode); + + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, 0, vdec.cbArg); + cb.Branch(false); } break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index e1c37aa250..f2ca2320fd 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -679,6 +679,8 @@ struct VdecTask } }; +int vdecRead(void* opaque, u8* buf, int buf_size); + class VideoDecoder { public: @@ -689,14 +691,23 @@ public: AVCodec* codec; AVCodecContext* ctx; + AVFormatContext* fmt; AVFrame* frame; AVDictionary* opts; + u8* io_buf; u32 buf_size; u64 pts; u64 dts; + u64 pos; u64 userdata; volatile bool has_picture; + struct VideoReader + { + u32 addr; + u32 size; + } reader; + const CellVdecCodecType type; const u32 profile; const u32 memAddr; @@ -714,6 +725,7 @@ public: , is_finished(false) , is_running(false) , has_picture(false) + , pos(0) { codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) @@ -744,12 +756,32 @@ public: Emu.Pause(); return; } + fmt = avformat_alloc_context(); + if (!fmt) + { + ConLog.Error("VideoDecoder(): avformat_alloc_context failed"); + Emu.Pause(); + return; + } + io_buf = (u8*)av_malloc(4096); + fmt->pb = avio_alloc_context(io_buf, 4096, 0, this, vdecRead, NULL, NULL); + if (!fmt->pb) + { + ConLog.Error("VideoDecoder(): avio_alloc_context failed"); + Emu.Pause(); + return; + } //memset(&out_data, 0, sizeof(out_data)); //memset(&linesize, 0, sizeof(linesize)); } ~VideoDecoder() { + if (io_buf) av_free(io_buf); + if (fmt) + { + avformat_free_context(fmt); + } if (frame) av_frame_free(&frame); if (ctx) {