📄 decoder.c
字号:
#include "pmfplayer.h"
#include <psppower.h>
#include <stdio.h>
#define printf pspDebugScreenPrintf
SceInt32 IsRingbufferFull(ReaderThreadData* D)
{
if(D->m_Status == READER_EOF)
return 1;
if(sceMpegRingbufferAvailableSize(D->m_Ringbuffer) > 0)
return 0;
return 1;
}
int T_Decoder(SceSize _args, void *_argp)
{
int retVal;
int iInitAudio = 1;
SceInt32 iVideoStatus = 0;
SceInt32 unknown = 0;
int iThreadsRunning = 0;
SceInt32 m_iAudioCurrentTimeStamp = 0;
SceInt32 m_iVideoCurrentTimeStamp = 0;
SceInt32 m_iVideoLastTimeStamp = 0;
DecoderThreadData* D = *((DecoderThreadData**)_argp);
for(;;)
{
printf("in T_Decoder thread\n");
sceKernelDelayThread(1);
scePowerTick(0);
if( iThreadsRunning == 0 &&
IsRingbufferFull(D->Reader) &&
D->Video->m_iNumBuffers == D->Video->m_iFullBuffers &&
D->Audio->m_iNumBuffers == D->Audio->m_iFullBuffers )
{
iThreadsRunning = 1;
sceKernelSignalSema(D->Video->m_SemaphoreStart, 1);
sceKernelSignalSema(D->Audio->m_SemaphoreStart, 1);
}
if(D->Reader->m_Status == READER_ABORT)
{
break;
}
else if(D->Reader->m_Status == READER_EOF)
{
retVal = sceMpegRingbufferAvailableSize(D->Reader->m_Ringbuffer);
if(retVal == D->Reader->m_RingbufferPackets)
break;
}
if(!IsRingbufferFull(D->Reader))
{
sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0);
if(D->Reader->m_Status == READER_ABORT)
break;
}
if(D->Audio->m_iFullBuffers < D->Audio->m_iNumBuffers)
{
retVal = sceMpegGetAtracAu(&D->m_Mpeg, D->m_MpegStreamAtrac, D->m_MpegAuAtrac, &unknown);
if(retVal != 0)
{
if(!IsRingbufferFull(D->Reader))
{
sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0);
if(D->Reader->m_Status == READER_ABORT)
break;
}
}
else
{
if(m_iAudioCurrentTimeStamp >= D->m_iLastTimeStamp - D->m_iVideoFrameDuration)
break;
retVal = sceMpegAtracDecode(&D->m_Mpeg, D->m_MpegAuAtrac, D->Audio->m_pAudioBuffer[D->Audio->m_iDecodeBuffer], iInitAudio);
if(retVal != 0)
{
sprintf(D->m_LastError, "sceMpegAtracDecode() failed: 0x%08X", retVal);
break;
}
if(D->m_MpegAuAtrac->iTimestamp < 0)
m_iAudioCurrentTimeStamp += D->m_iAudioFrameDuration;
else
m_iAudioCurrentTimeStamp = D->m_MpegAuAtrac->iTimestamp;
if(m_iAudioCurrentTimeStamp <= 0x15F90 /* video start ts */ - D->m_iAudioFrameDuration)
iInitAudio = 1;
D->Audio->m_iBufferTimeStamp[D->Audio->m_iDecodeBuffer] = m_iAudioCurrentTimeStamp;
if(iInitAudio == 0)
{
sceKernelWaitSema(D->Audio->m_SemaphoreLock, 1, 0);
D->Audio->m_iFullBuffers++;
sceKernelSignalSema(D->Audio->m_SemaphoreLock, 1);
D->Audio->m_iDecodeBuffer = (D->Audio->m_iDecodeBuffer + 1) % D->Audio->m_iNumBuffers;
}
iInitAudio = 0;
}
}
if(!IsRingbufferFull(D->Reader))
{
sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0);
if(D->Reader->m_Status == READER_ABORT)
break;
}
if(D->Video->m_iFullBuffers < D->Video->m_iNumBuffers)
{
retVal = sceMpegGetAvcAu(&D->m_Mpeg, D->m_MpegStreamAVC, D->m_MpegAuAVC, &unknown);
if((SceUInt32)retVal == 0x80618001)
{
if(!IsRingbufferFull(D->Reader))
{
sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0);
if(D->Reader->m_Status == READER_ABORT)
break;
}
}
else if(retVal != 0)
{
sprintf(D->m_LastError, "sceMpegGetAvcAu() failed: 0x%08X", retVal);
break;
}
else
{
if(m_iVideoCurrentTimeStamp >= D->m_iLastTimeStamp - D->m_iVideoFrameDuration)
break;
retVal = sceMpegAvcDecode(&D->m_Mpeg, D->m_MpegAuAVC, BUFFER_WIDTH, &D->Video->m_pVideoBuffer[D->Video->m_iPlayBuffer], &iVideoStatus);
if(retVal != 0)
{
sprintf(D->m_LastError, "sceMpegAvcDecode() failed: 0x%08X", retVal);
break;
}
if(D->m_MpegAuAVC->iTimestamp < 0)
m_iVideoCurrentTimeStamp += 0x0BBC;
else
m_iVideoCurrentTimeStamp = D->m_MpegAuAVC->iTimestamp;
if(iVideoStatus == 1)
{
D->Video->m_iBufferTimeStamp[D->Video->m_iPlayBuffer] = m_iVideoLastTimeStamp;
sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0);
D->Video->m_iFullBuffers++;
sceKernelSignalSema(D->Video->m_SemaphoreLock, 1);
}
m_iVideoLastTimeStamp = m_iVideoCurrentTimeStamp;
}
}
if(!IsRingbufferFull(D->Reader))
{
sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0);
if(D->Reader->m_Status == READER_ABORT)
break;
}
}
sceKernelSignalSema(D->Audio->m_SemaphoreStart, 1);
sceKernelSignalSema(D->Video->m_SemaphoreStart, 1);
D->Reader->m_Status = READER_ABORT;
D->Audio->m_iAbort = 1;
while(D->Video->m_iFullBuffers > 0)
{
sceKernelWaitSema(D->Video->m_SemaphoreWait, 1, 0);
sceKernelSignalSema(D->Video->m_SemaphoreLock, 1);
}
sceMpegAvcDecodeStop(&D->m_Mpeg, BUFFER_WIDTH, D->Video->m_pVideoBuffer, &iVideoStatus);
if(iVideoStatus > 0)
{
sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0);
D->Video->m_iFullBuffers++;
sceKernelSignalSema(D->Video->m_SemaphoreLock, 1);
}
D->Video->m_iAbort = 1;
sceMpegFlushAllStream(&D->m_Mpeg);
sceKernelExitThread(0);
return 0;
}
SceInt32 InitDecoder(PMFPLAYER_STRUCT *p)
{
p->Decoder.m_ThreadID = sceKernelCreateThread("decoder_thread", T_Decoder, 0x10, 0x10000, PSP_THREAD_ATTR_USER, NULL);
printf("p->Decoder.m_ThreadID:%d\n", p->Decoder.m_ThreadID);
if(p->Decoder.m_ThreadID < 0)
{
sprintf(p->m_LastError, "sceKernelCreateThread() failed: 0x%08X", (int)p->Decoder.m_ThreadID);
return -1;
}
p->Decoder.Reader = &p->Reader;
p->Decoder.Video = &p->Video;
p->Decoder.Audio = &p->Audio;
printf("&p->Decoder:0x%x\n", &p->Decoder);
printf("&p->Reader:0x%x\n", &p->Reader);
printf("&p->Video:0x%x\n", &p->Video);
printf("&p->Audio:0x%x\n", &p->Audio);
p->Decoder.m_Mpeg = p->m_Mpeg;
p->Decoder.m_MpegStreamAVC = p->m_MpegStreamAVC;
p->Decoder.m_MpegAuAVC = &p->m_MpegAuAVC;
p->Decoder.m_MpegStreamAtrac = p->m_MpegStreamAtrac;
p->Decoder.m_MpegAuAtrac = &p->m_MpegAuAtrac;
p->Decoder.m_LastError = p->m_LastError;
p->Decoder.m_iAudioFrameDuration = 4180; // ??
p->Decoder.m_iVideoFrameDuration = (int)(90000 / 29.97);
p->Decoder.m_iLastTimeStamp = p->m_iLastTimeStamp;
printf("InitDecoder ok\n");
return 0;
}
SceInt32 ShutdownDecoder(PMFPLAYER_STRUCT *p)
{
sceKernelDeleteThread(p->Decoder.m_ThreadID);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -