www.pudn.com > GDIyuvplayer.rar > YUVPlayer.cpp
// YUVPlayer.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "YUVPlayer.h"
#include "DisplayWin.h"
#include "YUVPlayerDlg.h"
#include "CirQueue.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define GET_R(sy,su,sv) ((298*((sy)-16) + 409*((sv)-128) + 128)>>8)
#define GET_G(sy,su,sv) ((298*((sy)-16) - 100*((su)-128) - 208*((sv)-128)+128)>> 8)
#define GET_B(sy,su,sv) ((298*((sy)-16) + 516*((su)-128) + 128)>> 8)
#define CLIP(value) (value)<0 ? 0 : ((value)>255 ? 255 : (value))
UINT SetQueueSize=0, fileLength=0;
extern CEvent eventStart, ReadKill, ConvertKill, freeBuffer;
extern UINT frameSize;
extern BOOL ThreadinUse = FALSE;
extern CFile m_pFile;
extern CCirQueue *FrameQueue;
extern HANDLE m_hTestEvent;
void getSeqName(char *inseqpath, char *seqname)
{
int lastSlashPos, i = 0;
char tmp = '0';
while(tmp != 0)
{
tmp = inseqpath[i];
if(tmp == '\\')
lastSlashPos = i;
i++;
}
strcpy(seqname, inseqpath + lastSlashPos + 1);
}
void YUV420toRGB24(unsigned char *ybuffer, unsigned char *ubuffer, unsigned char *vbuffer, unsigned char *rgbbuffer, int width, int height)
{
int i, j;
int src_y, src_u, src_v;
unsigned char *des1, *des2, *y1, *y2;
des1 = rgbbuffer;
des2 = rgbbuffer + 3*width;
y1 = ybuffer;
y2 = ybuffer + width;
for(i = 0; i < height; i += 2)
{
for (j = 0; j < width; j += 2)
{
src_y = *(y1++);
src_u = *(ubuffer++);
src_v = *(vbuffer++);
*(des1++) = CLIP(GET_B(src_y, src_u, src_v));
*(des1++) = CLIP(GET_G(src_y, src_u, src_v));
*(des1++) = CLIP(GET_R(src_y, src_u, src_v));
src_y = *(y1++);
*(des1++) = CLIP(GET_B(src_y,src_u,src_v));
*(des1++) = CLIP(GET_G(src_y,src_u,src_v));
*(des1++) = CLIP(GET_R(src_y,src_u,src_v));
src_y = *(y2++);
*(des2++) = CLIP(GET_B(src_y,src_u,src_v));
*(des2++) = CLIP(GET_G(src_y,src_u,src_v));
*(des2++) = CLIP(GET_R(src_y,src_u,src_v));
src_y = *(y2++);
*(des2++) = CLIP(GET_B(src_y,src_u,src_v));
*(des2++) = CLIP(GET_G(src_y,src_u,src_v));
*(des2++) = CLIP(GET_R(src_y,src_u,src_v));
}
y1 += width;
y2 += width;
des2 += 3*width;
des1 += 3*width;
}
}
UINT ReadtoBuffer(LPVOID pParam)
{
DisplayWin *pShow = (DisplayWin*) pParam;
FrameQueue = new CCirQueue(SetQueueSize);
if (FrameQueue->CreateinHeap() == FALSE)
{
AfxMessageBox("Queue allocate in Heap is failed");
return FALSE;
}
double FrameLength = frameSize*1.5;
HANDLE HANDLEarray[2] = { ReadKill, m_hTestEvent };
unsigned char* FrameBuf;
while (1)
{
if( WaitForMultipleObjects(2, HANDLEarray, FALSE, INFINITE) == WAIT_OBJECT_0)
{
break;
}
if(FrameQueue->QFull() == FALSE && m_pFile.GetPosition() != fileLength)
{
FrameBuf = (unsigned char*) malloc(FrameLength);//freed in ConvertPicture();
if (FrameLength == m_pFile.Read(FrameBuf,FrameLength))
{
FrameQueue -> QInsert(FrameBuf);
}
}
if (FrameQueue -> QFull() == TRUE)
ResetEvent(m_hTestEvent);
}
WaitForSingleObject(freeBuffer,INFINITE);
while (FrameQueue->QEmpty() == FALSE)
{
free(FrameQueue->QOut());
}
delete FrameQueue;
return TRUE;
}
UINT ConvertPicture(LPVOID pParam)
{
unsigned char *yBuffer, *uBuffer, *vBuffer;
DisplayWin *pShow = (DisplayWin*) pParam;
HANDLE HANDLEarray[2] = {ConvertKill, eventStart};
ThreadinUse = TRUE;
while(1)
{
if( WaitForMultipleObjects(2, HANDLEarray, FALSE, INFINITE) == WAIT_OBJECT_0)
{
freeBuffer.SetEvent();
break;
}
SetEvent(m_hTestEvent);
if (FrameQueue -> QEmpty() == TRUE)
Sleep(20);
if (FrameQueue -> QEmpty() == FALSE)
{
yBuffer = FrameQueue -> QOut();
uBuffer = yBuffer + frameSize;
vBuffer = uBuffer + frameSize / 4;
YUV420toRGB24(yBuffer,uBuffer,vBuffer,pShow->RGBbuf,pShow->dWidth,pShow->dHeight);
free(yBuffer);
pShow -> InvalidateRect (NULL,FALSE);
pShow -> UpdateWindow ();
}
}
KillTimer(AfxGetMainWnd() -> m_hWnd, 1);//播放结束后需要关闭计时器;
ThreadinUse = FALSE;
pShow -> PostMessage(WM_CLOSE);// 寄消息给主线程,关闭播放窗口;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CYUVPlayerApp
BEGIN_MESSAGE_MAP(CYUVPlayerApp, CWinApp)
//{{AFX_MSG_MAP(CYUVPlayerApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CYUVPlayerApp construction
CYUVPlayerApp::CYUVPlayerApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CYUVPlayerApp object
CYUVPlayerApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CYUVPlayerApp initialization
BOOL CYUVPlayerApp::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
CYUVPlayerDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}