vs2010MFC D3D播放YUV格式视频详细制作全过程

本文介绍如何使用Visual Studio 2010和DirectX SDK创建一个简单的YUV格式视频播放器,包括环境配置、代码编写及视频播放流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.环境配置

1.1 Microsoft Visual Studio 2010安装

先下载Visual Studio 2010,然后双击setup.exe安装,安装时有一步选择vc++安装就可以了,其他步骤直接点击下一步。

1.2DirectX  SDK安装

  先下载DXSDK_Feb10,然后解压,解压完双击DXSDK_Feb10.exe进行安装,安装时请记住自己的安装路径以便后续操作,一直点下一步直到完成安装即可。

2.YUV视频播放器编写

2.1创建项

先运行vs2010,新建项目,模板选择Visual C++ 中MFC中的MFC应用程序,然后输入项目名称“myplayer”,点击确定,弹出一个MFC应用程序向导对话框,点击下一步,应用程序类型选择基于对话框(D),然后点击完成。

2.2设置DirectX  SDK环境

2.2.1右击刚才创建的项目,选择属性,弹出一个项目属性页。

2.2.2点击配置属性里的VC++目录,然后选择包含目录那一行,在那行后边会出现一个倒立黑色小三角形。如下图:


左击倒立三角,弹出一个单行的框,里边写着编辑,左击编辑两个字,弹出包含目录对话框,如下图,左击下图红色正方形标示的图标,在红色长方形处会弹出一行空白框,空白框后边有个按钮,左击那个按钮。


左击按钮后出现一个选择目录对话框,根据自己安装DirectX  SDK时的路径找到如下图红色标示区的文件夹,双击这个文件夹进入里边,找到Include文件夹,双击Include文件夹,然后点击“选择文件夹”按钮,接下来一直点击确定即可。

 

2.2.3包含d3d9.lib文件

  先执行上边的2.2.1操作,如下图找到配置属性下的链接器双击,再双击输入,单击附加依赖项这一行,出现黑色倒立小三角形,单击三角形出现编辑两个字。


单击编辑这两个字,出现如下图的附加依赖项对话框,如下图红色标示处自己写上d3d9.lib,点击确定按钮。至此DirectX  SDK环境设置完成。

 

2.3创建一个用于显示YUV视频的窗口。

2.3.1下图使我们创建项目时自动生成的MFC窗口,把下图中红色标示的控件删除。

2.3.2如下图把vs2010窗口右边的红色标示的工具箱打开。

 

2.3.3展开工具箱后用如下红色标示的两个控件创建窗口。

2.3.4播放窗口如下图:

 

 

上图中间是Picture Control控件,用来显示视频,选中这个控件,在vs2010窗口右侧属性那如下图把ID属性改为“IDC_VIDEO”。

 

 

2.3.5在自己创建的项目的头文件右击选择“添加”—>“新建项”,弹出添加新项窗口。


在添加新项窗口中选择如下图红色标示的项,然后输入名称,点击“添加”按钮。一共要添加四个*.h的文件,名称分别输入为PlayControl、DEFINE、ColourSpaceConvert 和D3DDisplay。


添加完四个*.h的文件,再按这种方法添加三个*.cpp的文件,如下图单击选择红色区域,然后输入名称,点击“添加”按钮。名称分别为PlayControl、ColourSpaceConvert 和D3DDisplay。


2.3.6代码

2.3.6.1  DEFINE.h
#ifndef MESSAGE_H_
#define MESSAGE_H_
#define D3D_ARGB32              1
#define D3D_YUV422              2
#define IMAGE_WIDTH            352 //分辨率
#define IMAGE_HEIGHT            288//分辨率
#define YUVPLANE IMAGE_WIDTH*IMAGE_HEIGHT*3/2
#define RGBPLANE IMAGE_WIDTH*IMAGE_HEIGHT*4
#endif//MESSAGE_H_

2.3.6.2  ColourSpaceConvert.h
//经典的YUV转换到RGB的函数的头文件
#if !defined(AFX_COLOURSPACECONVERT_H__92911B35_FC87_4C19_9007_1D735942D76E__INCLUDED_)
#define AFX_COLOURSPACECONVERT_H__92911B35_FC87_4C19_9007_1D735942D76E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CColourSpaceConvert  
{
public:
	CColourSpaceConvert();
	virtual ~CColourSpaceConvert();
void YUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori, int width,int height);
	
private:
//YUV===>RGB
	 long int crv_tab[256];
     long int cbu_tab[256];
     long int cgu_tab[256];
     long int cgv_tab[256];
     long int tab_76309[256];
     unsigned char clp[1024];
	 void InitConvertTable();
};
#endif

2.3.6.3  PlayControl.h
#if !defined(AFX_PLAYCONTROL_H__C3D14174_0157_4809_B573_DEA1F90DADB6__INCLUDED_)
#define AFX_PLAYCONTROL_H__C3D14174_0157_4809_B573_DEA1F90DADB6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "D3DDisplay.h"
#include "DEFINE.h"
#include <stdio.h>
#define WM_MANAGE WM_USER + 1001
 class CPlayControl :public CWinThread
{
	DECLARE_DYNCREATE(CPlayControl)
public:
	CPlayControl();
	virtual ~CPlayControl();
virtual BOOL InitInstance();
	virtual int ExitInstance();
	int Init(HWND hwnd, char *filename);
	void Play();
	void Stop();
	void Pause();
private:
	CD3DDisplay m_D3D;
	BYTE *yuvbuf;
	BYTE *rgbbuf;
	FILE *f_in;//输入的文件句柄
	int m_State;
protected:
	

	void OnManage(WPARAM wParam, LPARAM lParam);
	DECLARE_MESSAGE_MAP()
		
};
#endif 

2.3.6.4  D3DDisplay.h
#if !defined(AFX_D3DDISPLAY_H__D2B5461A_AF44_411A_8FEA_8439E0FB5628__INCLUDED_)
#define AFX_D3DDISPLAY_H__D2B5461A_AF44_411A_8FEA_8439E0FB5628__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <d3dx9.h>
class CD3DDisplay  
{
public:
	int GetFormt();
	HRESULT RenderSample(BYTE* pSampleBuffer);
	HRESULT RenderTOSrceen();
	HRESULT InitGeometry();
	HRESULT CreateTexture();
	HRESULT InitD3D(HWND hWnd);
	void ClearD3D();
	CD3DDisplay();
	virtual ~CD3DDisplay();
private:
	LPDIRECT3D9             m_pD3D; 
    LPDIRECT3DDEVICE9       m_pd3dDevice; 
    LPDIRECT3DTEXTURE9      m_pTexturesvideo; 
	LPDIRECT3DVERTEXBUFFER9 m_pVBvideo;		//视频矩形的顶点缓存区接口指针
	LPDIRECT3DTEXTURE9      m_pTexturesbmp;
	LPDIRECT3DVERTEXBUFFER9 m_pVBbmp;       //位图矩形的顶点缓存区接口指针

	HWND m_hWnd;
	D3DFORMAT m_Format;
	LPD3DXFONT m_p2Dfont;
};
#endif


2.3.6.5  ColourSpaceConvert.cpp
//经典的YUV转换到RGB的函数的实现
#include "stdafx.h"
#include "ColourSpaceConvert.h"
CColourSpaceConvert::CColourSpaceConvert()
{
	//InitLookupTable();
	InitConvertTable();
}

CColourSpaceConvert::~CColourSpaceConvert()
{

}
//YUV===>RGB
void CColourSpaceConvert::InitConvertTable()
{
   long int crv,cbu,cgu,cgv;
   int i,ind;   
     
   crv = 104597; 
cbu = 132201; 
   cgu = 25675; 
 cgv = 53279;
  
   for (i = 0; i < 256; i++) {
      crv_tab[i] = (i-128) * crv;
      cbu_tab[i] = (i-128) * cbu;
      cgu_tab[i] = (i-128) * cgu;
      cgv_tab[i] = (i-128) * cgv;
      tab_76309[i] = 76309*(i-16);
   }
	 
   for (i=0; i<384; i++)
	  clp[i] =0;
   ind=384;
   for (i=0;i<256; i++)
	   clp[ind++]=i;
   ind=640;
   for (i=0;i<384;i++)
	   clp[ind++]=255;
}

void CColourSpaceConvert::YUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,
								 int width,int height)
{
    int y1,y2,u,v; 
	unsigned char *py1,*py2;
	int i,j, c1, c2, c3, c4;
	unsigned char *d1, *d2;

	py1=src0;
	py2=py1+width;
	d1=dst_ori;
	d2=d1+3*width;
 	for (j = 0; j < height; j += 2) { 
		for (i = 0; i < width; i += 2) {

			u = *src1++;
			v = *src2++;

			c1 = crv_tab[v];
			c2 = cgu_tab[u];
			c3 = cgv_tab[v];
			c4 = cbu_tab[u];

			//up-left
            y1 = tab_76309[*py1++];	
			*d1++ = clp[384+((y1 + c1)>>16)];  
			*d1++ = clp[384+((y1 - c2 - c3)>>16)];
            *d1++ = clp[384+((y1 + c4)>>16)];

			//down-left
			y2 = tab_76309[*py2++];
			*d2++ = clp[384+((y2 + c1)>>16)];  
			*d2++ = clp[384+((y2 - c2 - c3)>>16)];
            *d2++ = clp[384+((y2 + c4)>>16)];

			//up-right
			y1 = tab_76309[*py1++];
			*d1++ = clp[384+((y1 + c1)>>16)];  
			*d1++ = clp[384+((y1 - c2 - c3)>>16)];
			*d1++ = clp[384+((y1 + c4)>>16)];

			//down-right
			y2 = tab_76309[*py2++];
			*d2++ = clp[384+((y2 + c1)>>16)];  
			*d2++ = clp[384+((y2 - c2 - c3)>>16)];
            *d2++ = clp[384+((y2 + c4)>>16)];
		}
		d1 += 3*width;
		d2 += 3*width;
		py1+=   width;
		py2+=   width;
	}       
}

2.3.6.6  PlayControl.cpp
#include "stdafx.h"
#include "PlayControl.h"
#include "ColourSpaceConvert.h"
#include  <afx.h>
/////////////////////////////////////////////////////////////////////////////
// CPlayControl
IMPLEMENT_DYNCREATE(CPlayControl, CWinThread)
CPlayControl::CPlayControl()
{
	m_State = 0;
	f_in = NULL;
	rgbbuf = NULL; 
	yuvbuf = NULL;
	CreateThread();
}
CPlayControl::~CPlayControl()
{
	f_in = NULL;
	rgbbuf = NULL; 
	yuvbuf = NULL;
}
BOOL CPlayControl::InitInstance()
{
	// TODO:  perform and per-thread initialization here
	return TRUE;
}
int CPlayControl::ExitInstance()
{
	// TODO:  perform any per-thread cleanup here
	return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CPlayControl, CWinThread)
	//{{AFX_MSG_MAP(CPlayControl)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		ON_THREAD_MESSAGE(WM_MANAGE,OnManage)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPlayControl message handlers
int CPlayControl::Init(HWND hwnd, char *filename)
{
	m_D3D.InitD3D(hwnd);
	m_D3D.CreateTexture();
	m_D3D.InitGeometry();
	if(m_D3D.GetFormt() == D3D_ARGB32)
	{
		rgbbuf = new BYTE[RGBPLANE]; 
	    yuvbuf = new BYTE[YUVPLANE];
	}
	else
	{
		return -1;
	}	
	if(!rgbbuf || !yuvbuf)
	{
		delete [] rgbbuf;
		delete [] yuvbuf;
		rgbbuf = NULL; 
	    yuvbuf = NULL;
		return -1;
	}
	f_in=fopen(filename,"rb");
	if (f_in == NULL)
	{
		return -1;
	}
	m_State = 1;
	return 0;
}
void CPlayControl::Play()
{
	m_State = 1;
}
void CPlayControl::Stop()
{
	m_State = 0;		
}
void CPlayControl::Pause()
{
	m_State = 2;
}
void CPlayControl::OnManage(WPARAM wParam, LPARAM lParam)
{
	CColourSpaceConvert m_csc;
	if(f_in == NULL)
		return;
	while(1)
	{
		if(m_State == 1)
		{
			if(fread(yuvbuf, YUVPLANE, 1, f_in))
			{
				m_csc.YUV2RGB(yuvbuf, 
					yuvbuf + IMAGE_HEIGHT*IMAGE_WIDTH*5/4, 
					yuvbuf + IMAGE_HEIGHT*IMAGE_WIDTH,
					rgbbuf, IMAGE_WIDTH, IMAGE_HEIGHT);
				m_D3D.RenderSample(rgbbuf);
				m_D3D.RenderTOSrceen();	
				Sleep(33);
			}
			else
				break;
		}
		else if(m_State == 2)
			continue;
		else
			break;
	}
	fclose(f_in);
}

 
2.3.6.7  D3DDisplay.cpp
#include "stdafx.h"
#include "D3DDisplay.h"
#include "DEFINE.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
struct CUSTOMVERTEX//顶点缓存
{     
	float x,y,z,rhw;	//顶点坐标 
    DWORD color;		//顶点颜色
	float tu,tv;		//纹理坐标
}; 
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CD3DDisplay::CD3DDisplay()
{
	m_pd3dDevice = NULL;
	m_pD3D = NULL;
    m_p2Dfont = NULL;
	m_pTexturesvideo = NULL;
	m_pVBvideo = NULL;
	m_pTexturesbmp = NULL;
	m_pVBbmp = NULL;
	m_hWnd = NULL;
	m_Format = (D3DFORMAT)0;
}
CD3DDisplay::~CD3DDisplay()
{
	ClearD3D();	
}
HRESULT CD3DDisplay::InitD3D(HWND hWnd)//初始化d3d
{
    D3DPRESENT_PARAMETERS d3dpp;//显示参数设置
	if(hWnd == NULL)
		return -1;
	m_hWnd = hWnd;
	//D3DFMT_A8R8G8B8表示一个32位像素,从左开始,8位为ALPHA通道,8位分配给红色,8位分配给绿色,8位分配给蓝色
	m_Format = D3DFMT_A8R8G8B8;
    if(NULL == (m_pD3D = Direct3DCreate9( D3D_SDK_VERSION )))//创建d3d对象
        return -1;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );//清空显示参数,重新设置参数
    d3dpp.Windowed = TRUE;//FALSE,表示要渲染全屏,如果为TRUE,表示要渲染窗口
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//交换缓冲支持的效果类型,指定表面在交换链中D是如何被交换的
	//D3DSWAPEFFECT_DISCARD,则后备缓冲区的东西被复制到屏幕上后,后备缓冲区的东西就没有什么用可以丢弃
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//后备缓冲的格式D3DFMT_UNKNOWN,这时候它将使用桌面的格式
    d3dpp.EnableAutoDepthStencil = TRUE;//如果要使用缓冲或模板缓冲则把它设为TRUE
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;//如果启动了深度缓冲那么这个参数将为深度设定缓冲格式
	//D3DFMT_16深度缓冲
	d3dpp.BackBufferWidth = IMAGE_WIDTH;//后备缓冲的宽度和高度
    d3dpp.BackBufferHeight = IMAGE_HEIGHT;//在全屏模式下这两者的值必需符合显卡所支持的分辨率
	
    if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL, 
		m_hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
		&d3dpp, 
		&m_pd3dDevice ) ) )//创建d3d设备
        return -1;
    return 0;
}
void CD3DDisplay::ClearD3D()//释放d3d
{
	if(m_pd3dDevice != NULL)
		m_pd3dDevice->Release();
	if(m_pD3D != NULL)
		m_pD3D->Release(); 
	if(m_p2Dfont != NULL)
		m_p2Dfont->Release(); 
	if(m_pVBvideo != NULL)
		m_pVBvideo->Release();
	if(m_pTexturesvideo != NULL)
		m_pTexturesvideo->Release();
	if(m_pVBbmp != NULL)
		m_pVBbmp->Release(); 
	if(m_pTexturesbmp != NULL)
		m_pTexturesbmp->Release(); 
	m_hWnd = NULL;
	m_Format = (D3DFORMAT)0;
}
HRESULT CD3DDisplay::CreateTexture()//创建纹理
{
    HRESULT hr = 0;
    D3DSURFACE_DESC ddsd;
	hr = m_pd3dDevice->CreateTexture( IMAGE_WIDTH, IMAGE_HEIGHT, 1, 0, m_Format, 
		D3DPOOL_MANAGED, &m_pTexturesvideo, NULL);
	if( FAILED(hr))
	{
		return -1;
	}
hr = m_pTexturesvideo->GetLevelDesc( 0, &ddsd );//获得加载图片的宽和高及些信息
	if(FAILED(hr))
		return -1;
	if ((ddsd.Format != D3DFMT_A8R8G8B8) && (ddsd.Format != D3DFMT_YUY2)) 
		return -1;

    return 0;
}
HRESULT CD3DDisplay::InitGeometry()//创建视频几何建立顶点缓存并初始化纹坐标
{
    HRESULT hr = 0;
    CUSTOMVERTEX* pVertices = NULL;
    RECT rect;
	//创建视频矩形
	rect.top = 0;			
	rect.left = 0;
	rect.right = IMAGE_WIDTH;
	rect.bottom = IMAGE_HEIGHT;
	CUSTOMVERTEX vertices[4] =  //顶点缓存
	{     // x, y, z, rhw, color
		{ (float)rect.left, (float)rect.top, 
			0.0f, 1.0f,	D3DCOLOR_XRGB(255,255,255), 0.0f, 0.0f }, 
		{ (float)rect.right, (float)rect.top, 
		0.0f, 1.0f, D3DCOLOR_XRGB(255,255,255), 1.0f, 0.0f }, 
		{ (float)rect.left, (float)rect.bottom, 
		0.0f, 1.0f, D3DCOLOR_XRGB(255,255,255), 0.0f, 1.0f }, 
		{ (float)rect.right, (float)rect.bottom, 
		0.0f, 1.0f, D3DCOLOR_XRGB(255,255,255), 1.0f, 1.0f }
	};
	m_pd3dDevice->CreateVertexBuffer(sizeof(vertices), //指定缓冲区的大小
		0, //指定顶点缓冲区的属性
		D3DFVF_CUSTOMVERTEX, //开始创建的定点格式
		D3DPOOL_DEFAULT, //指定顶点缓冲区的内存类型
		&m_pVBvideo, //视频矩形的顶点缓存区接口指针
		NULL ); //保留参数
m_pVBvideo->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ); //填充顶点缓冲区
	memcpy( pVertices, vertices, sizeof(vertices)); 
	m_pVBvideo->Unlock(); 	
    return hr;
}
HRESULT CD3DDisplay::RenderSample(BYTE *pSampleBuffer)
{
    HRESULT hr = 0;
    BYTE * pTextureBuffer = NULL;
    D3DLOCKED_RECT d3dlr;
    LONG  lTexturePitch;     
		hr = m_pTexturesvideo->LockRect( 0, &d3dlr, 0, 0 );
	if( FAILED(hr))
	{
		return -1;
	}
	lTexturePitch = d3dlr.Pitch;
	pTextureBuffer = static_cast<byte *>(d3dlr.pBits);
	for(int i = 0; i < IMAGE_HEIGHT; i++ ) 
	{
		BYTE *pBmpBufferOld = pSampleBuffer;
		BYTE *pTxtBufferOld = pTextureBuffer;   
		for (int j = 0; j < IMAGE_WIDTH; j++) 
		{
			pTextureBuffer[0] = pSampleBuffer[0];
			pTextureBuffer[1] = pSampleBuffer[1];
			pTextureBuffer[2] = pSampleBuffer[2];
			pTextureBuffer[3] = 0xFF;
			pTextureBuffer += 4;
			pSampleBuffer  += 3;
		}
		pSampleBuffer  = pBmpBufferOld + IMAGE_WIDTH *3;
		pTextureBuffer = pTxtBufferOld + lTexturePitch;
	}
	hr = m_pTexturesvideo->UnlockRect(0);
	if( FAILED(hr))
	{
		return -1;
	}
    return 0;
}
HRESULT CD3DDisplay::RenderTOSrceen()//传递到屏幕
{
    HRESULT hr = 0;
	hr = m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0 );
	if( FAILED(hr))
	{
		return -1;
	}
	hr = m_pd3dDevice->BeginScene();
	if( FAILED(hr))
	{
		return -1;
	}
	//显示视频
    hr = m_pd3dDevice->SetTexture( 0, m_pTexturesvideo );
	m_pd3dDevice->SetStreamSource( 0, m_pVBvideo, 0, sizeof(CUSTOMVERTEX)); 
	hr = m_pd3dDevice->SetVertexShader( NULL );//设置可编程渲染管道的Shader程序
	m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //设置固定渲染管道Ì的顶点格式
	m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );//渲染一组非索引
	m_pd3dDevice->SetTexture( 0, NULL ); 
	m_pd3dDevice->EndScene();
	m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
	return hr;
}
int CD3DDisplay::GetFormt()
{
    return D3D_ARGB32;	
}

2.3.6.8  按钮点击事件函数

双击你自己创建的用于播放YUV视频的窗体上的那四个按钮,进入单击事件代码区,然后分别写入相应代码。

首先在myplayerDlg.h中加入头文件声明#include "PlayControl.h",在类中加上

private:
	CPlayControl m_PlayControl;

双击“打开文件”按钮后写入代码:

void CmyplayerDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	CString file_name = "";
	CFileDialog fd(TRUE,  NULL, 
				   file_name, 
				   OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, 
				   NULL, NULL);
	
	if (fd.DoModal() == IDOK) 
	{
		m_PlayControl.Init(::GetDlgItem(GetSafeHwnd(),IDC_VIDEO), 
			fd.GetPathName().GetBuffer(fd.GetPathName().GetLength()));
		
		m_PlayControl.PostThreadMessage(WM_MANAGE, 0, 0);
	}
}

双击“播放”按钮后写入代码:

void CmyplayerDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	m_PlayControl.Play();
}

双击“暂停”按钮后写入代码:

void CmyplayerDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	m_PlayControl.Pause();
}
双击“停止”按钮后写入代码:
void CmyplayerDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	m_PlayControl.Stop();
}

3.程序内部运行过程

  运行时,初始化播放界面,操作人员点击“打开文件”按钮,选择自己要播放的YUV格式视频文件,点击一下这个视频文件,程序会先用PlayControl类的对象调用PlayControl.cpp中Init()函数来创建D3D设备(创建D3D设备调用D3DDisplay类),然后PlayControl类的对象传递消息触发消息响应函数PlayControl.cpp中的OnManage()函数,OnManage()函数中使用ColourSpaceConvert类的对象调用ColourSpaceConvert.cpp中的YUV2RGB()函数将YUV视频转换为RGB格式,然后D3D设备调用D3DDisplay.cpp中的RenderSample()函数和RenderToScreen()函数对视频渲染并在屏幕上显示。

4.注意事项

4.1在DEFINE.h文件中

#define IMAGE_WIDTH            352 //分辨率

#define IMAGE_HEIGHT            288//分辨率

这两句是设置分辨率的,可以更改为自己YUV视频的分辨率来正确播放视频。

4.2字符集错误

若出现不能将参数2 从“wchar_t *”转换为“char *”的错误,右击项目名选择“属性”,按下图红色区域把字符集改为“使用多字节字符集”。



5.其他:

本文附带的项目文件“myplayer”需要在安装了DirectX SDK的电脑上运行,请按上文中1.2所述进行安装。

若安装完运行出错,请按2.2所述配置SDK环境。




评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值