vs2010MFC D3D播放YUV格式视频详细制作全过程
1.環(huán)境配置
1.1 Microsoft Visual Studio 2010安裝
先下載Visual Studio 2010,然后雙擊setup.exe安裝,安裝時(shí)有一步選擇vc++安裝就可以了,其他步驟直接點(diǎn)擊下一步。
1.2DirectX? SDK安裝
? 先下載DXSDK_Feb10,然后解壓,解壓完雙擊DXSDK_Feb10.exe進(jìn)行安裝,安裝時(shí)請(qǐng)記住自己的安裝路徑以便后續(xù)操作,一直點(diǎn)下一步直到完成安裝即可。
2.YUV視頻播放器編寫
2.1創(chuàng)建項(xiàng)
先運(yùn)行vs2010,新建項(xiàng)目,模板選擇Visual C++ 中MFC中的MFC應(yīng)用程序,然后輸入項(xiàng)目名稱“myplayer”,點(diǎn)擊確定,彈出一個(gè)MFC應(yīng)用程序向?qū)?duì)話框,點(diǎn)擊下一步,應(yīng)用程序類型選擇基于對(duì)話框(D),然后點(diǎn)擊完成。
2.2設(shè)置DirectX? SDK環(huán)境
2.2.1右擊剛才創(chuàng)建的項(xiàng)目,選擇屬性,彈出一個(gè)項(xiàng)目屬性頁(yè)。
2.2.2點(diǎn)擊配置屬性里的VC++目錄,然后選擇包含目錄那一行,在那行后邊會(huì)出現(xiàn)一個(gè)倒立黑色小三角形。如下圖:
左擊倒立三角,彈出一個(gè)單行的框,里邊寫著編輯,左擊編輯兩個(gè)字,彈出包含目錄對(duì)話框,如下圖,左擊下圖紅色正方形標(biāo)示的圖標(biāo),在紅色長(zhǎng)方形處會(huì)彈出一行空白框,空白框后邊有個(gè)按鈕,左擊那個(gè)按鈕。
左擊按鈕后出現(xiàn)一個(gè)選擇目錄對(duì)話框,根據(jù)自己安裝DirectX? SDK時(shí)的路徑找到如下圖紅色標(biāo)示區(qū)的文件夾,雙擊這個(gè)文件夾進(jìn)入里邊,找到Include文件夾,雙擊Include文件夾,然后點(diǎn)擊“選擇文件夾”按鈕,接下來(lái)一直點(diǎn)擊確定即可。
?
2.2.3包含d3d9.lib文件
? 先執(zhí)行上邊的2.2.1操作,如下圖找到配置屬性下的鏈接器雙擊,再雙擊輸入,單擊附加依賴項(xiàng)這一行,出現(xiàn)黑色倒立小三角形,單擊三角形出現(xiàn)編輯兩個(gè)字。
單擊編輯這兩個(gè)字,出現(xiàn)如下圖的附加依賴項(xiàng)對(duì)話框,如下圖紅色標(biāo)示處自己寫上d3d9.lib,點(diǎn)擊確定按鈕。至此DirectX? SDK環(huán)境設(shè)置完成。
?
2.3創(chuàng)建一個(gè)用于顯示YUV視頻的窗口。
2.3.1下圖使我們創(chuàng)建項(xiàng)目時(shí)自動(dòng)生成的MFC窗口,把下圖中紅色標(biāo)示的控件刪除。
2.3.2如下圖把vs2010窗口右邊的紅色標(biāo)示的工具箱打開。
?
2.3.3展開工具箱后用如下紅色標(biāo)示的兩個(gè)控件創(chuàng)建窗口。
2.3.4播放窗口如下圖:
?
?
上圖中間是Picture Control控件,用來(lái)顯示視頻,選中這個(gè)控件,在vs2010窗口右側(cè)屬性那如下圖把ID屬性改為“IDC_VIDEO”。
?
?
2.3.5在自己創(chuàng)建的項(xiàng)目的頭文件右擊選擇“添加”—>“新建項(xiàng)”,彈出添加新項(xiàng)窗口。
在添加新項(xiàng)窗口中選擇如下圖紅色標(biāo)示的項(xiàng),然后輸入名稱,點(diǎn)擊“添加”按鈕。一共要添加四個(gè)*.h的文件,名稱分別輸入為PlayControl、DEFINE、ColourSpaceConvert 和D3DDisplay。
添加完四個(gè)*.h的文件,再按這種方法添加三個(gè)*.cpp的文件,如下圖單擊選擇紅色區(qū)域,然后輸入名稱,點(diǎn)擊“添加”按鈕。名稱分別為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
//經(jīng)典的YUV轉(zhuǎn)換到RGB的函數(shù)的頭文件 #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===>RGBlong 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(); }; #endif2.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 + 1001class 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()}; #endif2.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; //視頻矩形的頂點(diǎn)緩存區(qū)接口指針LPDIRECT3DTEXTURE9 m_pTexturesbmp;LPDIRECT3DVERTEXBUFFER9 m_pVBbmp; //位圖矩形的頂點(diǎn)緩存區(qū)接口指針HWND m_hWnd;D3DFORMAT m_Format;LPD3DXFONT m_p2Dfont; }; #endif2.3.6.5? ColourSpaceConvert.cpp
//經(jīng)典的YUV轉(zhuǎn)換到RGB的函數(shù)的實(shí)現(xiàn) #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-lefty1 = tab_76309[*py1++]; *d1++ = clp[384+((y1 + c1)>>16)]; *d1++ = clp[384+((y1 - c2 - c3)>>16)];*d1++ = clp[384+((y1 + c4)>>16)];//down-lefty2 = tab_76309[*py2++];*d2++ = clp[384+((y2 + c1)>>16)]; *d2++ = clp[384+((y2 - c2 - c3)>>16)];*d2++ = clp[384+((y2 + c4)>>16)];//up-righty1 = tab_76309[*py1++];*d1++ = clp[384+((y1 + c1)>>16)]; *d1++ = clp[384+((y1 - c2 - c3)>>16)];*d1++ = clp[384+((y1 + c4)>>16)];//down-righty2 = 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 herereturn TRUE; } int CPlayControl::ExitInstance() {// TODO: perform any per-thread cleanup herereturn 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);}elsebreak;}else if(m_State == 2)continue;elsebreak;}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//頂點(diǎn)緩存 { float x,y,z,rhw; //頂點(diǎn)坐標(biāo) DWORD color; //頂點(diǎn)顏色float tu,tv; //紋理坐標(biāo) }; #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;//顯示參數(shù)設(shè)置if(hWnd == NULL)return -1;m_hWnd = hWnd;//D3DFMT_A8R8G8B8表示一個(gè)32位像素,從左開始,8位為ALPHA通道,8位分配給紅色,8位分配給綠色,8位分配給藍(lán)色m_Format = D3DFMT_A8R8G8B8;if(NULL == (m_pD3D = Direct3DCreate9( D3D_SDK_VERSION )))//創(chuàng)建d3d對(duì)象return -1;ZeroMemory( &d3dpp, sizeof(d3dpp) );//清空顯示參數(shù),重新設(shè)置參數(shù)d3dpp.Windowed = TRUE;//FALSE,表示要渲染全屏,如果為TRUE,表示要渲染窗口d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//交換緩沖支持的效果類型,指定表面在交換鏈中D是如何被交換的//D3DSWAPEFFECT_DISCARD,則后備緩沖區(qū)的東西被復(fù)制到屏幕上后,后備緩沖區(qū)的東西就沒有什么用可以丟棄d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//后備緩沖的格式D3DFMT_UNKNOWN,這時(shí)候它將使用桌面的格式d3dpp.EnableAutoDepthStencil = TRUE;//如果要使用緩沖或模板緩沖則把它設(shè)為TRUEd3dpp.AutoDepthStencilFormat = D3DFMT_D16;//如果啟動(dòng)了深度緩沖那么這個(gè)參數(shù)將為深度設(shè)定緩沖格式//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 ) ) )//創(chuàng)建d3d設(shè)備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()//創(chuàng)建紋理 {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()//創(chuàng)建視頻幾何建立頂點(diǎn)緩存并初始化紋坐標(biāo) {HRESULT hr = 0;CUSTOMVERTEX* pVertices = NULL;RECT rect;//創(chuàng)建視頻矩形rect.top = 0; rect.left = 0;rect.right = IMAGE_WIDTH;rect.bottom = IMAGE_HEIGHT;CUSTOMVERTEX vertices[4] = //頂點(diǎn)緩存{ // 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), //指定緩沖區(qū)的大小0, //指定頂點(diǎn)緩沖區(qū)的屬性D3DFVF_CUSTOMVERTEX, //開始創(chuàng)建的定點(diǎn)格式D3DPOOL_DEFAULT, //指定頂點(diǎn)緩沖區(qū)的內(nèi)存類型&m_pVBvideo, //視頻矩形的頂點(diǎn)緩存區(qū)接口指針NULL ); //保留參數(shù) m_pVBvideo->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ); //填充頂點(diǎn)緩沖區(qū)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 );//設(shè)置可編程渲染管道的Shader程序m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //設(shè)置固定渲染管道ì的頂點(diǎn)格式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? 按鈕點(diǎn)擊事件函數(shù)
雙擊你自己創(chuàng)建的用于播放YUV視頻的窗體上的那四個(gè)按鈕,進(jìn)入單擊事件代碼區(qū),然后分別寫入相應(yīng)代碼。
首先在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.程序內(nèi)部運(yùn)行過程
? 運(yùn)行時(shí),初始化播放界面,操作人員點(diǎn)擊“打開文件”按鈕,選擇自己要播放的YUV格式視頻文件,點(diǎn)擊一下這個(gè)視頻文件,程序會(huì)先用PlayControl類的對(duì)象調(diào)用PlayControl.cpp中Init()函數(shù)來(lái)創(chuàng)建D3D設(shè)備(創(chuàng)建D3D設(shè)備調(diào)用D3DDisplay類),然后PlayControl類的對(duì)象傳遞消息觸發(fā)消息響應(yīng)函數(shù)PlayControl.cpp中的OnManage()函數(shù),OnManage()函數(shù)中使用ColourSpaceConvert類的對(duì)象調(diào)用ColourSpaceConvert.cpp中的YUV2RGB()函數(shù)將YUV視頻轉(zhuǎn)換為RGB格式,然后D3D設(shè)備調(diào)用D3DDisplay.cpp中的RenderSample()函數(shù)和RenderToScreen()函數(shù)對(duì)視頻渲染并在屏幕上顯示。
4.注意事項(xiàng)
4.1在DEFINE.h文件中
#define IMAGE_WIDTH???????? ???352 //分辨率
#define IMAGE_HEIGHT??????????? 288//分辨率
這兩句是設(shè)置分辨率的,可以更改為自己YUV視頻的分辨率來(lái)正確播放視頻。
4.2字符集錯(cuò)誤
若出現(xiàn)不能將參數(shù)2 從“wchar_t *”轉(zhuǎn)換為“char *”的錯(cuò)誤,右擊項(xiàng)目名選擇“屬性”,按下圖紅色區(qū)域把字符集改為“使用多字節(jié)字符集”。
5.其他:
本文附帶的項(xiàng)目文件“myplayer”需要在安裝了DirectX SDK的電腦上運(yùn)行,請(qǐng)按上文中1.2所述進(jìn)行安裝。
若安裝完運(yùn)行出錯(cuò),請(qǐng)按2.2所述配置SDK環(huán)境。
總結(jié)
以上是生活随笔為你收集整理的vs2010MFC D3D播放YUV格式视频详细制作全过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用opencv改变视频长宽
- 下一篇: opencv中在图片上显示文本