Beispiel #1
0
int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellPngDecSrc> src, u32 openInfo)
{
	cellPngDec.Warning("cellPngDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)",
		mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo);

	if (!subHandle.IsGood() || !src.IsGood())
		return CELL_PNGDEC_ERROR_ARG;

	CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle;

	current_subHandle->fd = NULL;
	current_subHandle->src = *src;

	switch(src->srcSelect.ToBE())
	{
	case const_se_t<u32, CELL_PNGDEC_BUFFER>::value:
		current_subHandle->fileSize = src->streamSize.ToLE();
		break;

	case const_se_t<u32, CELL_PNGDEC_FILE>::value:
		// Get file descriptor
		MemoryAllocator<be_t<u32>> fd;
		int ret = cellFsOpen(src->fileName_addr, 0, fd.GetAddr(), NULL, 0);
		current_subHandle->fd = fd->ToLE();
		if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE;

		// Get size of file
		MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
		ret = cellFsFstat(current_subHandle->fd, sb.GetAddr());
		if(ret != CELL_OK) return ret;
		current_subHandle->fileSize = sb->st_size;	// Get CellFsStat.st_size
		break;
	}

	// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
	subHandle = cellPngDec.GetNewId(current_subHandle);

	return CELL_OK;
}
Beispiel #2
0
// Utility Functions  
int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key)
{
	cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr());

	if (Emu.GetEventManager().CheckKey(0x80004d494f323221))
	{
		return CELL_AUDIO_ERROR_EVENT_QUEUE;
	}

	EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, 0x80004d494f323221, 0x80004d494f323221, 32);

	if (!Emu.GetEventManager().RegisterKey(eq, 0x80004d494f323221))
	{
		delete eq;
		return CELL_AUDIO_ERROR_EVENT_QUEUE;
	}

	id = cellAudio.GetNewId(eq);
	key = 0x80004d494f323221;

	return CELL_OK;
}
Beispiel #3
0
int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t<CellJpgDecSrc> src, mem_ptr_t<CellJpgDecOpnInfo> openInfo)
{
	cellJpgDec.Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)",
		mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo);

	CellJpgDecSubHandle *current_subHandle = new CellJpgDecSubHandle;

	// Get file descriptor
	MemoryAllocator<be_t<u32>> fd;
	int ret = cellFsOpen(src->fileName, 0, fd, NULL, 0);
	current_subHandle->fd = fd->ToLE();
	if(ret != CELL_OK) return CELL_JPGDEC_ERROR_OPEN_FILE;

	// Get size of file
	MemoryAllocator<CellFsStat> sb; // Alloc a CellFsStat struct
	ret = cellFsFstat(current_subHandle->fd, sb.GetAddr());
	if(ret != CELL_OK) return ret;
	current_subHandle->fileSize = sb->st_size;	// Get CellFsStat.st_size

	// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
	subHandle = cellJpgDec.GetNewId(current_subHandle);

	return CELL_OK;
}
Beispiel #4
0
u32 adecOpen(AudioDecoder* data)
{
	AudioDecoder& adec = *data;

	adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);

	u32 adec_id = cellAdec.GetNewId(data);

	adec.id = adec_id;

	adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback");

	thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]()
	{
		ConLog.Write("Audio Decoder enter()");

		AdecTask& task = adec.task;

		while (true)
		{
			if (Emu.IsStopped())
			{
				break;
			}

			if (adec.job.IsEmpty() && adec.is_running)
			{
				Sleep(1);
				continue;
			}

			/*if (adec.frames.GetCount() >= 50)
			{
				Sleep(1);
				continue;
			}*/

			if (!adec.job.Pop(task))
			{
				break;
			}

			switch (task.type)
			{
			case adecStartSeq:
				{
					// TODO: reset data
					ConLog.Warning("adecStartSeq:");

					adec.reader.addr = 0;
					adec.reader.size = 0;
					adec.reader.init = false;
					if (adec.reader.rem) free(adec.reader.rem);
					adec.reader.rem = nullptr;
					adec.reader.rem_size = 0;
					adec.is_running = true;
					adec.just_started = true;
				}
				break;

			case adecEndSeq:
				{
					// TODO: finalize
					ConLog.Warning("adecEndSeq:");

					/*Callback cb;
					cb.SetAddr(adec.cbFunc);
					cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);
					cb.Branch(true); // ???*/
					adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg);

					avcodec_close(adec.ctx);
					avformat_close_input(&adec.fmt);

					adec.is_running = false;
				}
				break;

			case adecDecodeAu:
				{
					int err = 0;

					adec.reader.addr = task.au.addr;
					adec.reader.size = task.au.size;
					//ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts);

					//if (adec.last_pts > task.au.pts || adec.just_started) adec.last_pts = task.au.pts;
					if (adec.just_started) adec.last_pts = task.au.pts;

					struct AVPacketHolder : AVPacket
					{
						AVPacketHolder(u32 size)
						{
							av_init_packet(this);

							if (size)
							{
								data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
								memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
								this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
							}
							else
							{
								data = NULL;
								size = 0;
							}
						}

						~AVPacketHolder()
						{
							av_free(data);
							//av_free_packet(this);
						}

					} au(0);

					/*{
						wxFile dump;
						dump.Open(wxString::Format("audio pts-0x%llx.dump", task.au.pts), wxFile::write);
						u8* buf = (u8*)malloc(task.au.size);
						if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size);
						free(buf);
						dump.Close();
					}*/

					if (adec.just_started) // deferred initialization
					{
						err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL);
						if (err)
						{
							ConLog.Error("adecDecodeAu: avformat_open_input() failed");
							Emu.Pause();
							break;
						}
						AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ???
						if (!codec)
						{
							ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed");
							Emu.Pause();
							break;
						}
						/*err = avformat_find_stream_info(adec.fmt, NULL);
						if (err)
						{
							ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed");
							Emu.Pause();
							break;
						}
						if (!adec.fmt->nb_streams)
						{
							ConLog.Error("adecDecodeAu: no stream found");
							Emu.Pause();
							break;
						}*/
						if (!avformat_new_stream(adec.fmt, codec))
						{
							ConLog.Error("adecDecodeAu: avformat_new_stream() failed");
							Emu.Pause();
							break;
						}
						adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data

						AVDictionary* opts = nullptr;
						av_dict_set(&opts, "refcounted_frames", "1", 0);
						{
							SMutexGeneralLocker lock(g_mutex_avcodec_open2);
							// not multithread-safe
							err = avcodec_open2(adec.ctx, codec, &opts);
						}
						if (err)
						{
							ConLog.Error("adecDecodeAu: avcodec_open2() failed");
							Emu.Pause();
							break;
						}
						adec.just_started = false;
					}

					bool last_frame = false;

					while (true)
					{
						if (Emu.IsStopped())
						{
							ConLog.Warning("adecDecodeAu aborted");
							return;
						}

						/*if (!adec.ctx) // fake
						{
							AdecFrame frame;
							frame.pts = task.au.pts;
							frame.auAddr = task.au.addr;
							frame.auSize = task.au.size;
							frame.userdata = task.au.userdata;
							frame.size = 4096;
							frame.data = nullptr;
							adec.frames.Push(frame);

							adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);

							break;
						}*/

						last_frame = av_read_frame(adec.fmt, &au) < 0;
						if (last_frame)
						{
							//break;
							av_free(au.data);
							au.data = NULL;
							au.size = 0;
						}

						struct AdecFrameHolder : AdecFrame
						{
							AdecFrameHolder()
							{
								data = av_frame_alloc();
							}

							~AdecFrameHolder()
							{
								if (data)
								{
									av_frame_unref(data);
									av_frame_free(&data);
								}
							}

						} frame;

						if (!frame.data)
						{
							ConLog.Error("adecDecodeAu: av_frame_alloc() failed");
							Emu.Pause();
							break;
						}

						int got_frame = 0;

						int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au);

						if (decode <= 0)
						{
							if (!last_frame && decode < 0)
							{
								ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode);
							}
							if (!got_frame && adec.reader.size == 0) break;
						}

						if (got_frame)
						{
							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);

							if (frame.data->format != AV_SAMPLE_FMT_FLTP)
							{
								ConLog.Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format);
								Emu.Pause();
								break;
							}
							if (frame.data->channels != 2)
							{
								ConLog.Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels);
								Emu.Pause();
								break;
							}

							//ConLog.Write("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));

							adec.frames.Push(frame);
							frame.data = nullptr; // to prevent destruction

							/*Callback cb;
							cb.SetAddr(adec.cbFunc);
							cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
							cb.Branch(false);*/
							adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
						}
					}
						
					/*Callback cb;
					cb.SetAddr(adec.cbFunc);
					cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
					cb.Branch(false);*/
					adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg);
				}
				break;

			case adecClose:
				{
					adec.is_finished = true;
					ConLog.Write("Audio Decoder exit");
					return;
				}

			default:
				ConLog.Error("Audio Decoder error: unknown task(%d)", task.type);
			}
		}
		adec.is_finished = true;
		ConLog.Warning("Audio Decoder aborted");
	});

	t.detach();

	return adec_id;
}
Beispiel #5
0
int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
{
	const wxString& path = Memory.ReadString(path_addr);
	sys_fs.Log("cellFsOpen(path=\"%s\", flags=0x%x, fd_addr=0x%x, arg_addr=0x%x, size=0x%llx)",
		path.wx_str(), flags, fd.GetAddr(), arg.GetAddr(), size);

	const wxString& ppath = path;
	//ConLog.Warning("path: %s [%s]", ppath.wx_str(), path.wx_str());

	s32 _oflags = flags;
	if(flags & CELL_O_CREAT)
	{
		_oflags &= ~CELL_O_CREAT;
		Emu.GetVFS().CreateFile(ppath);
	}

	vfsOpenMode o_mode;

	switch(flags & CELL_O_ACCMODE)
	{
	case CELL_O_RDONLY:
		_oflags &= ~CELL_O_RDONLY;
		o_mode = vfsRead;
	break;

	case CELL_O_WRONLY:
		_oflags &= ~CELL_O_WRONLY;

		if(flags & CELL_O_APPEND)
		{
			_oflags &= ~CELL_O_APPEND;
			o_mode = vfsWriteAppend;
		}
		else if(flags & CELL_O_EXCL)
		{
			_oflags &= ~CELL_O_EXCL;
			o_mode = vfsWriteExcl;
		}
		else //if (flags & CELL_O_TRUNC)
		{
			_oflags &= ~CELL_O_TRUNC;
			o_mode = vfsWrite;
		}
	break;

	case CELL_O_RDWR:
		_oflags &= ~CELL_O_RDWR;
		if (flags & CELL_O_TRUNC)
		{
			_oflags &= ~CELL_O_TRUNC;
			//truncate file before opening it as read/write
			Emu.GetVFS().OpenFile(ppath, vfsWrite);
		}
		o_mode = vfsReadWrite;
	break;
	}

	if(_oflags != 0)
	{
		sys_fs.Error("\"%s\" has unknown flags! flags: 0x%08x", ppath.wx_str(), flags);
		return CELL_EINVAL;
	}

	vfsFileBase* stream = Emu.GetVFS().OpenFile(ppath, o_mode);

	if(!stream || !stream->IsOpened())
	{
		sys_fs.Error("\"%s\" not found! flags: 0x%08x", ppath.wx_str(), flags);
		return CELL_ENOENT;
	}

	fd = sys_fs.GetNewId(stream, IDFlag_File);
	ConLog.Warning("*** cellFsOpen(path=\"%s\"): fd = %d", path.wx_str(), fd.GetValue());

	return CELL_OK;
}
Beispiel #6
0
u32 vdecOpen(VideoDecoder* data)
{
	VideoDecoder& vdec = *data;

	vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);

	u32 vdec_id = cellVdec.GetNewId(data);

	vdec.id = vdec_id;

	vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");

	thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]()
	{
		ConLog.Write("Video Decoder enter()");

		VdecTask& task = vdec.task;

		while (true)
		{
			if (Emu.IsStopped())
			{
				break;
			}

			if (vdec.job.IsEmpty() && vdec.is_running)
			{
				Sleep(1);
				continue;
			}

			if (vdec.frames.GetSize() >= 50)
			{
				Sleep(1);
				continue;
			}

			if (!vdec.job.Pop(task))
			{
				break;
			}

			switch (task.type)
			{
			case vdecStartSeq:
				{
					// TODO: reset data
					ConLog.Warning("vdecStartSeq:");

					vdec.reader.addr = 0;
					vdec.reader.size = 0;
					vdec.is_running = true;
					vdec.just_started = true;
				}
				break;

			case vdecEndSeq:
				{
					// TODO: finalize
					ConLog.Warning("vdecEndSeq:");

					vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
					/*Callback cb;
					cb.SetAddr(vdec.cbFunc);
					cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
					cb.Branch(true); // ???*/

					avcodec_close(vdec.ctx);
					avformat_close_input(&vdec.fmt);

					vdec.is_running = false;
				}
				break;

			case vdecDecodeAu:
				{
					int err;

					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;
					//ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts);

					if (vdec.just_started)
					{
						vdec.first_pts = task.pts;
						vdec.last_pts = task.pts;
						vdec.first_dts = task.dts;
					}

					struct AVPacketHolder : AVPacket
					{
						AVPacketHolder(u32 size)
						{
							av_init_packet(this);

							if (size)
							{
								data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
								memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
								this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
							}
							else
							{
								data = NULL;
								size = 0;
							}
						}

						~AVPacketHolder()
						{
							av_free(data);
							//av_free_packet(this);
						}

					} au(0);

					if (vdec.just_started) // deferred initialization
					{
						err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL);
						if (err)
						{
							ConLog.Error("vdecDecodeAu: avformat_open_input() failed");
							Emu.Pause();
							break;
						}
						AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ???
						if (!codec)
						{
							ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed");
							Emu.Pause();
							break;
						}
						/*err = avformat_find_stream_info(vdec.fmt, NULL);
						if (err)
						{
							ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed");
							Emu.Pause();
							break;
						}
						if (!vdec.fmt->nb_streams)
						{
							ConLog.Error("vdecDecodeAu: no stream found");
							Emu.Pause();
							break;
						}*/
						if (!avformat_new_stream(vdec.fmt, codec))
						{
							ConLog.Error("vdecDecodeAu: avformat_new_stream() failed");
							Emu.Pause();
							break;
						}
						vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data
						
						AVDictionary* opts = nullptr;
						av_dict_set(&opts, "refcounted_frames", "1", 0);
						{
							SMutexGeneralLocker lock(g_mutex_avcodec_open2);
							// not multithread-safe
							err = avcodec_open2(vdec.ctx, codec, &opts);
						}
						if (err)
						{
							ConLog.Error("vdecDecodeAu: avcodec_open2() failed");
							Emu.Pause();
							break;
						}
						//vdec.ctx->flags |= CODEC_FLAG_TRUNCATED;
						//vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS;
						vdec.just_started = false;
					}

					bool last_frame = false;

					while (true)
					{
						if (Emu.IsStopped())
						{
							ConLog.Warning("vdecDecodeAu aborted");
							return;
						}

						last_frame = av_read_frame(vdec.fmt, &au) < 0;
						if (last_frame)
						{
							//break;
							av_free(au.data);
							au.data = NULL;
							au.size = 0;
						}

						struct VdecFrameHolder : VdecFrame
						{
							VdecFrameHolder()
							{
								data = av_frame_alloc();
							}

							~VdecFrameHolder()
							{
								if (data)
								{
									av_frame_unref(data);
									av_frame_free(&data);
								}
							}

						} frame;

						if (!frame.data)
						{
							ConLog.Error("vdecDecodeAu: av_frame_alloc() failed");
							Emu.Pause();
							break;
						}

						int got_picture = 0;

						int decode = avcodec_decode_video2(vdec.ctx, frame.data, &got_picture, &au);

						if (decode <= 0)
						{
							if (!last_frame && decode < 0)
							{
								ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode);
							}
							if (!got_picture && vdec.reader.size == 0) break; // video end?
						}

						if (got_picture)
						{
							u64 ts = av_frame_get_best_effort_timestamp(frame.data);
							if (ts != AV_NOPTS_VALUE)
							{
								frame.pts = ts/* - vdec.first_pts*/; // ???
								vdec.last_pts = frame.pts;
							}
							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;
							}
							//frame.pts = vdec.last_pts;
							//vdec.last_pts += 3754;
							frame.dts = (frame.pts - vdec.first_pts) + vdec.first_dts;
							frame.userdata = task.userData;

							//ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);	

							vdec.frames.Push(frame); // !!!!!!!!
							frame.data = nullptr; // to prevent destruction

							vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
							/*Callback cb;
							cb.SetAddr(vdec.cbFunc);
							cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
							cb.Branch(false);*/
						}
					}

					vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
					/*Callback cb;
					cb.SetAddr(vdec.cbFunc);
					cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
					cb.Branch(false);*/
				}
				break;

			case vdecClose:
				{
					vdec.is_finished = true;
					ConLog.Write("Video Decoder exit");
					return;
				}

			case vdecSetFrameRate:
				{
					ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc);
				}
				break;

			default:
				ConLog.Error("Video Decoder error: unknown task(%d)", task.type);
			}
		}

		vdec.is_finished = true;
		ConLog.Warning("Video Decoder aborted");
	});

	t.detach();

	return vdec_id;
}