⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.c

📁 psp下pmf文件播放器源码
💻 C
字号:
#include "pmfplayer.h"
#include <psputilsforkernel.h>
#include <pspdisplay.h>
#include <pspge.h>
#include <pspgu.h>

#include <stdio.h>

#define printf pspDebugScreenPrintf

static unsigned int __attribute__((aligned(64)))  DisplayList[128 * 1024 * 4];

SceInt32 AVSyncStatus(DecoderThreadData* D)
{
	if(D->Audio->m_iFullBuffers == 0 || D->Video->m_iFullBuffers == 0)
		return 1;

	int iAudioTS = D->Audio->m_iBufferTimeStamp[D->Audio->m_iPlayBuffer];
	int iVideoTS = D->Video->m_iBufferTimeStamp[D->Video->m_iPlayBuffer];

	// if video ahead of audio, do nothing
	if(iVideoTS - iAudioTS > 2 * D->m_iVideoFrameDuration)
		return 0;

	// if audio ahead of video, skip frame
	if(iAudioTS - iVideoTS > 2 * D->m_iVideoFrameDuration)
		return 2;

	return 1;
}

int RenderFrame(int width, int height, void* Buffer)
{
	sceGuStart(GU_DIRECT, DisplayList);

	struct Vertex* Vertices = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex));

	Vertices[0].u = 0;        Vertices[0].v = 0;
	Vertices[0].x = 0;        Vertices[0].y = 0;        Vertices[0].z = 0;
	Vertices[1].u = width;	  Vertices[1].v = height;
	Vertices[1].x = SCREEN_W; Vertices[1].y = SCREEN_H; Vertices[1].z = 0;

	sceGuTexImage(0, TEXTURE_W, TEXTURE_H, BUFFER_WIDTH, Buffer);

	sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D, 2, 0, Vertices);

	sceGuFinish();

	sceGuSync(0, 0);

	sceDisplayWaitVblankStart();

	sceGuSwapBuffers();

	return 0;
}

int T_Video(SceSize _args, void *_argp)
{
	int iSyncStatus = 1;

	DecoderThreadData* D = *((DecoderThreadData**)_argp);

	sceKernelWaitSema(D->Video->m_SemaphoreStart, 1, 0);
	
	for(;;)
	{
		printf("in T_Video thread\n");
		if(D->Video->m_iAbort != 0)
			break;

		if(D->Video->m_iFullBuffers > 0)
		{
			iSyncStatus = AVSyncStatus(D);

			if(iSyncStatus > 0)
			{
				if(iSyncStatus == 1)
					RenderFrame(D->Video->m_iWidth, D->Video->m_iHeight, D->Video->m_pVideoBuffer[D->Video->m_iPlayBuffer]);

				sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0);

				D->Video->m_iFullBuffers--;

				sceKernelSignalSema(D->Video->m_SemaphoreLock, 1);
			}
		}
		else
		{
			sceDisplayWaitVblankStart();
		}

		sceKernelSignalSema(D->Video->m_SemaphoreWait, 1);

		sceDisplayWaitVblankStart();
	}

	while(D->Video->m_iFullBuffers > 0)
	{
		RenderFrame(D->Video->m_iWidth, D->Video->m_iHeight, D->Video->m_pVideoBuffer[D->Video->m_iPlayBuffer]);

		sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0);

		D->Video->m_iFullBuffers--;

		sceKernelSignalSema(D->Video->m_SemaphoreLock, 1);

		sceDisplayWaitVblankStart();
	}

	sceGuTerm();

	sceKernelExitThread(0);

	return 0;
}

SceInt32 InitVideo(PMFPLAYER_STRUCT *p)
{
	p->Video.m_ThreadID = sceKernelCreateThread("video_thread", T_Video, 0x3F, 0x10000, PSP_THREAD_ATTR_USER, NULL);
	printf("p->Video.m_ThreadID:%d\n", p->Video.m_ThreadID);
	if(p->Video.m_ThreadID < 0)
	{
		sprintf(p->m_LastError, "sceKernelCreateThread() failed: 0x%08X", (int)p->Video.m_ThreadID);
		return -1;
	}

	p->Video.m_SemaphoreStart = sceKernelCreateSema("video_start_sema", 0, 0, 1, NULL);
	if(p->Video.m_SemaphoreStart < 0)
	{
		sprintf(p->m_LastError, "sceKernelCreateSema() failed: 0x%08X", (int)p->Video.m_SemaphoreStart);
		goto exit0;
	}

	p->Video.m_SemaphoreWait = sceKernelCreateSema("video_wait_sema", 0, 1, 1, NULL);
	if(p->Video.m_SemaphoreWait < 0)
	{
		sprintf(p->m_LastError, "sceKernelCreateSema() failed: 0x%08X", (int)p->Video.m_SemaphoreWait);
		goto exit1;
	}

	p->Video.m_SemaphoreLock = sceKernelCreateSema("video_lock_sema", 0, 1, 1, NULL);
	if(p->Video.m_SemaphoreLock < 0)
	{
		sprintf(p->m_LastError, "sceKernelCreateSema() failed: 0x%08X", (int)p->Video.m_SemaphoreLock);
		goto exit2;
	}

	p->Video.m_iBufferTimeStamp[0]	= 0;
	p->Video.m_iNumBuffers			= 1;
	p->Video.m_iFullBuffers		= 0;
	p->Video.m_iPlayBuffer			= 0;
	p->Video.m_iAbort				= 0;
	p->Video.m_LastError			= p->m_LastError;

	// not sure how to get these
	if (p->m_PmfScaling) {
		p->Video.m_iWidth				= p->m_MovieWidth;
		p->Video.m_iHeight			= p->m_MovieHeight;
	} else {
		p->Video.m_iWidth				= 480;
		p->Video.m_iHeight				= 272;
	}

	p->Video.m_pVideoBuffer[0]		= ((char *)sceGeEdramGetAddr()) + DRAW_BUFFER_SIZE + DISP_BUFFER_SIZE;

	sceGuInit();

	sceGuStart(GU_DIRECT, DisplayList);

	sceGuDrawBuffer(GU_PSM_8888, (void*)0, BUFFER_WIDTH);
	sceGuDispBuffer(SCREEN_W, SCREEN_H, (void*)(DRAW_BUFFER_SIZE), BUFFER_WIDTH);

	sceGuDisable  (GU_SCISSOR_TEST);

	sceGuTexFilter(GU_NEAREST,GU_LINEAR);

	sceGuTexMode  (GU_PSM_8888, 0, 0, GU_FALSE);  

	sceGuEnable   (GU_TEXTURE_2D);

	sceGuColor    (0xFFFFFFFF);

	sceGuFinish   ();
	
	sceGuSync     (0, 0);

	sceDisplayWaitVblankStart();

	sceGuDisplay  (GU_TRUE);

	sceGuClear    (GU_COLOR_BUFFER_BIT);

	printf("InitVideo ok\n");
	return 0;

exit2:
	sceKernelDeleteSema(p->Video.m_SemaphoreWait);
exit1:
	sceKernelDeleteSema(p->Video.m_SemaphoreStart);
exit0:
	sceKernelDeleteThread(p->Video.m_ThreadID);

	return -1;
}

SceInt32 ShutdownVideo(PMFPLAYER_STRUCT *p)
{
	sceKernelDeleteThread(p->Video.m_ThreadID);

	sceKernelDeleteSema(p->Video.m_SemaphoreStart);
	sceKernelDeleteSema(p->Video.m_SemaphoreWait);
	sceKernelDeleteSema(p->Video.m_SemaphoreLock);

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -