Beispiel #1
0
void vdecOpen(u32 vdec_id) // TODO: call from the constructor
{
	const auto sptr = idm::get<VideoDecoder>(vdec_id);

	VideoDecoder& vdec = *sptr;

	vdec.id = vdec_id;

	vdec.vdecCb = idm::make_ptr<PPUThread>(fmt::format("VideoDecoder[0x%x] Thread", vdec_id));
	vdec.vdecCb->prio = 1001;
	vdec.vdecCb->stack_size = 0x10000;
	vdec.vdecCb->custom_task = [sptr](PPUThread& ppu)
	{
		VideoDecoder& vdec = *sptr;
		VdecTask& task = vdec.task;

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

			if (!vdec.job.pop(task, &vdec.is_closed))
			{
				break;
			}

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

				vdec.reader = {};
				vdec.frc_set = 0;
				vdec.just_started = true;
				break;
			}

			case vdecEndSeq:
			{
				// TODO: finalize
				cellVdec.warning("vdecEndSeq:");

				vdec.cbFunc(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);

				vdec.just_finished = true;
				break;
			}

			case vdecDecodeAu:
			{
				int err;

				vdec.reader.addr = task.addr;
				vdec.reader.size = task.size;
				//LOG_NOTICE(HLE, "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 = -1;
					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 && vdec.just_finished)
				{
					avcodec_flush_buffers(vdec.ctx);
					vdec.just_started = false;
					vdec.just_finished = false;
				}
				else if (vdec.just_started) // deferred initialization
				{
					AVDictionary* opts = nullptr;
					av_dict_set(&opts, "probesize", "4096", 0);
					err = avformat_open_input(&vdec.fmt, NULL, NULL, &opts);
					if (err || opts)
					{
						throw EXCEPTION("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)
						{
							throw EXCEPTION("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))
						{
							throw EXCEPTION("avformat_new_stream() failed");
						}
					}
					vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data
						
					opts = nullptr;
					av_dict_set(&opts, "refcounted_frames", "1", 0);
					{
						std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
						// not multithread-safe (???)
						err = avcodec_open2(vdec.ctx, vdec.codec, &opts);
					}
					if (err || opts)
					{
						throw EXCEPTION("avcodec_open2() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0);
					}

					vdec.just_started = false;
				}

				bool last_frame = false;

				while (true)
				{
					if (Emu.IsStopped() || vdec.is_closed)
					{
						if (Emu.IsStopped()) cellVdec.warning("vdecDecodeAu: aborted");
						break;
					}

					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)
					{
						throw EXCEPTION("av_frame_alloc() failed");
					}

					int got_picture = 0;

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

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

					if (got_picture)
					{
						if (frame.data->interlaced_frame)
						{
							throw EXCEPTION("Interlaced frames not supported (0x%x)", frame.data->interlaced_frame);
						}

						if (frame.data->repeat_pict)
						{
							throw EXCEPTION("Repeated frames not supported (0x%x)", frame.data->repeat_pict);
						}

						if (vdec.frc_set)
						{
							if (vdec.last_pts == -1)
							{
								u64 ts = av_frame_get_best_effort_timestamp(frame.data);
								if (ts != AV_NOPTS_VALUE)
								{
									vdec.last_pts = ts;
								}
								else
								{
									vdec.last_pts = 0;
								}
							}
							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:
							{
								throw EXCEPTION("Invalid frame rate code set (0x%x)", vdec.frc_set);
							}
							}

							frame.frc = vdec.frc_set;
						}
						else
						{
							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 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:
								{
									throw EXCEPTION("Unsupported time_base.den (%d/1, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame);
								}
								}
							}
							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 if (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame == 60000)
								{
									frame.frc = CELL_VDEC_FRC_60000DIV1001;
								}
								else
								{
									throw EXCEPTION("Unsupported time_base.den (%d/1001, tpf=%d)", vdec.ctx->time_base.den, vdec.ctx->ticks_per_frame);
								}
							}
							else
							{
								throw EXCEPTION("Unsupported time_base.num (%d)", vdec.ctx->time_base.num);
							}
						}

						frame.pts = vdec.last_pts;
						frame.dts = (frame.pts - vdec.first_pts) + vdec.first_dts;
						frame.userdata = task.userData;

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

						if (vdec.frames.push(frame, &vdec.is_closed))
						{
							frame.data = nullptr; // to prevent destruction
							vdec.cbFunc(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
						}
					}
				}

				vdec.cbFunc(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
				break;
			}

			case vdecSetFrameRate:
			{
				cellVdec.warning("vdecSetFrameRate(0x%x)", task.frc);
				vdec.frc_set = task.frc;
				break;
			}

			case vdecClose:
			{
				break;
			}

			default:
			{
				throw EXCEPTION("Unknown task(%d)", task.type);
			}
			}
		}

		vdec.is_finished = true;
	};

	vdec.vdecCb->cpu_init();
	vdec.vdecCb->state -= cpu_state::stop;
	vdec.vdecCb->safe_notify();
}
Beispiel #2
0
DECLARE(ppu_module_manager::sysPrxForUser)("sysPrxForUser", []()
{
	sysPrxForUser_sys_lwmutex_init();
	sysPrxForUser_sys_lwcond_init();
	sysPrxForUser_sys_ppu_thread_init();
	sysPrxForUser_sys_prx_init();
	sysPrxForUser_sys_heap_init();
	sysPrxForUser_sys_spinlock_init();
	sysPrxForUser_sys_mmapper_init();
	sysPrxForUser_sys_mempool_init();
	sysPrxForUser_sys_spu_init();
	sysPrxForUser_sys_game_init();
	sysPrxForUser_sys_libc_init();

	REG_VAR(sysPrxForUser, sys_prx_version); // 0x7df066cf

	REG_FUNC(sysPrxForUser, sys_initialize_tls);

	REG_FUNC(sysPrxForUser, sys_time_get_system_time);

	// TODO: split syscalls and liblv2 functions
	REG_FUNC(sysPrxForUser, sys_process_exit);
	REG_FUNC(sysPrxForUser, _sys_process_atexitspawn);
	REG_FUNC(sysPrxForUser, _sys_process_at_Exitspawn);
	REG_FUNC(sysPrxForUser, sys_process_is_stack);
	REG_FUNC(sysPrxForUser, sys_process_get_paramsfo); // 0xe75c40f2

	REG_FUNC(sysPrxForUser, sys_interrupt_thread_disestablish);

	REG_FUNC(sysPrxForUser, sys_get_random_number);
Beispiel #3
0
	});

	sysPrxForUser_sys_lwmutex_init();
	sysPrxForUser_sys_lwcond_init();
	sysPrxForUser_sys_ppu_thread_init();
	sysPrxForUser_sys_prx_init();
	sysPrxForUser_sys_heap_init();
	sysPrxForUser_sys_spinlock_init();
	sysPrxForUser_sys_mmapper_init();
	sysPrxForUser_sys_mempool_init();
	sysPrxForUser_sys_spu_init();
	sysPrxForUser_sys_game_init();
	sysPrxForUser_sys_libc_init();
	sysPrxForUser_sys_rsxaudio_init();

	REG_VAR(sysPrxForUser, sys_prx_version); // 0x7df066cf
	REG_VAR(sysPrxForUser, g_ppu_atexitspawn).flag(MFF_HIDDEN);
	REG_VAR(sysPrxForUser, g_ppu_at_Exitspawn).flag(MFF_HIDDEN);

	REG_FUNC(sysPrxForUser, sys_time_get_system_time);

	REG_FUNC(sysPrxForUser, sys_process_exit);
	REG_FUNC(sysPrxForUser, _sys_process_atexitspawn);
	REG_FUNC(sysPrxForUser, _sys_process_at_Exitspawn);
	REG_FUNC(sysPrxForUser, sys_process_is_stack);
	REG_FUNC(sysPrxForUser, sys_process_get_paramsfo); // 0xe75c40f2

	REG_FUNC(sysPrxForUser, sys_get_random_number);

	REG_FUNC(sysPrxForUser, console_getc);
	REG_FUNC(sysPrxForUser, console_putc);
Beispiel #4
0
	// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393f);
#endif

	return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET;
}

s32 cellVideoOutSetCopyControl(u32 videoOut, u32 control)
{
	cellAvconfExt.todo("cellVideoOutSetCopyControl(videoOut=%d, control=0x%x)", videoOut, control);
	return CELL_OK;
}


DECLARE(ppu_module_manager::cellAvconfExt)("cellSysutilAvconfExt", []()
{
	REG_VAR(cellSysutilAvconfExt, g_gamma).flag(MFF_HIDDEN).init = []
	{
		// Test
		*g_gamma = 1.0f;
	};

	REG_FUNC(cellSysutilAvconfExt, cellAudioOutUnregisterDevice);
	REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetDeviceInfo2);
	REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetXVColor);
	REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetupDisplay);
	REG_FUNC(cellSysutilAvconfExt, cellAudioInGetDeviceInfo);
	REG_FUNC(cellSysutilAvconfExt, cellVideoOutConvertCursorColor);
	REG_FUNC(cellSysutilAvconfExt, cellVideoOutGetGamma);
	REG_FUNC(cellSysutilAvconfExt, cellAudioInGetAvailableDeviceInfo);
	REG_FUNC(cellSysutilAvconfExt, cellAudioOutGetAvailableDeviceInfo);
	REG_FUNC(cellSysutilAvconfExt, cellVideoOutSetGamma);
Beispiel #5
0
s32 cellSync2QueueGetSize()
{
	UNIMPLEMENTED_FUNC(cellSync2);
	return CELL_OK;
}

s32 cellSync2QueueGetDepth()
{
	UNIMPLEMENTED_FUNC(cellSync2);
	return CELL_OK;
}

DECLARE(ppu_module_manager::cellSync2)("cellSync2", []()
{
	REG_VAR(cellSync2, gCellSync2CallerThreadTypePpuThread);
	REG_VAR(cellSync2, gCellSync2NotifierPpuThread);
	REG_VAR(cellSync2, gCellSync2CallerThreadTypePpuFiber);
	REG_VAR(cellSync2, gCellSync2NotifierPpuFiber);
	REG_VAR(cellSync2, gCellSync2NotifierSpursTask);
	REG_VAR(cellSync2, gCellSync2NotifierSpursJobQueueJob);

	REG_FUNC(cellSync2, _cellSync2MutexAttributeInitialize);
	REG_FUNC(cellSync2, cellSync2MutexEstimateBufferSize);
	REG_FUNC(cellSync2, cellSync2MutexInitialize);
	REG_FUNC(cellSync2, cellSync2MutexFinalize);
	REG_FUNC(cellSync2, cellSync2MutexLock);
	REG_FUNC(cellSync2, cellSync2MutexTryLock);
	REG_FUNC(cellSync2, cellSync2MutexUnlock);

	REG_FUNC(cellSync2, _cellSync2CondAttributeInitialize);