zoukankan      html  css  js  c++  java
  • H264解码之DDraw显示YUV

    头文件:

    #pragma once
    #include "ddraw.h"
    #include <time.h>
    #pragma  comment (lib, "ddraw.lib")
    #pragma comment(lib, "dxguid.lib")
    class display
    {
    public:
    	display(void);
    public:
    	~display(void);
    public:
    	unsigned __int64 init(HWND hwnd);
    	void uninit();
    	unsigned __int64 inputsource(unsigned char * src, long nwidth, long nheight, long ntype, long nrate, unsigned __int64 npts);
    	static BOOL WINAPI DDEnumCallBack( GUID *pguid, LPTSTR pszdesc, LPTSTR pszdevicename, LPVOID pcontext, HMONITOR hmonior );
    	unsigned __int64 createoffscreen(LPDIRECTDRAWSURFACE7 * offscreen, DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype);
    	unsigned __int64 createddsd(DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype);
    	unsigned __int64 wait_ctrl(unsigned __int64 npts);
    	void refrush();
    	void reinit();
    
    private:
    	struct MONITOR_INFO
    	{
    		LPDIRECTDRAW7 lpDD;				// DirectDraw 对象指针
    		HMONITOR hMon;	
    	};
    	LPDIRECTDRAW7 m_lpddraw;						// DirectDraw 对象指针
    	LPDIRECTDRAWSURFACE7 m_lpddsprimary;			// DirectDraw 主表面指针
    	LPDIRECTDRAWSURFACE7 m_lpddsoffscr;				// DirectDraw 离屏表面指针
    	LPDIRECTDRAWSURFACE7 m_lpddsoffscr2;			// DirectDraw 离屏表面指针
    	LPDIRECTDRAWCLIPPER m_lpclipper;
    	HWND m_hwnd;
    	DDSURFACEDESC2 m_ddsd;
    	bool m_init;
    	long m_lastwidth;
    	long m_lastheight;
    
    	RECT m_rctDest;			// 目标区域
    	RECT m_rctSour;			// 源区域
    	RECT m_rctDestLast;
    	DDBLTFX  m_ddbltfx;
    };
    

    cpp文件:

    #include "StdAfx.h"
    #include "display.h"
    
    display::display(void)
    {
    	m_lpddraw = NULL;
    	m_lpddsprimary = NULL;
    	m_lpddsoffscr = NULL;
    	m_lpddsoffscr2 = NULL;
    	m_lpclipper = NULL;
    	m_init = false;
    	memset(&m_ddsd, 0, sizeof(m_ddsd));
    	m_lastwidth = 0;
    	m_lastheight = 0;
    }
    
    display::~display(void)
    {
    }
    
    BOOL WINAPI display::DDEnumCallBack( GUID *pguid, LPTSTR pszdesc, LPTSTR pszdevicename, LPVOID pcontext, HMONITOR hmonior )
    {
    	LPDIRECTDRAW7            lpDD = NULL;				// DirectDraw 对象指针
    	MONITOR_INFO *pthis = ( MONITOR_INFO *)pcontext;
    	if ( !pthis )
    	{
    		return FALSE;
    	}
    	if ( pthis->hMon == hmonior )
    	{
            OutputDebugStringA("创建DirectDraw begin
    ");
    		if (DirectDrawCreateEx(pguid, (void**)&lpDD, IID_IDirectDraw7, NULL) != DD_OK)
    		{
    			OutputDebugStringA("创建lpDD error!
    ");
    		}
    		pthis->lpDD = lpDD;
    		lpDD = NULL;
    	}
    
        OutputDebugStringA("创建DirectDraw end
    ");
    	// 创建DirectDraw对象
    
    	return TRUE;
    }
    
    void display::reinit()
    {
    	uninit();
    	init(m_hwnd);
    }
    
    unsigned __int64 display::init(HWND hwnd)
    {
    	if (m_init)
    	{
    		return 0;
    	}
    	m_hwnd = hwnd;
    	MONITOR_INFO mi_lpdd;
    	mi_lpdd.hMon = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
    	// 枚举监视器并创建DirectDraw对象
    	DirectDrawEnumerateExA( display::DDEnumCallBack, 
    		&mi_lpdd,
    		DDENUM_ATTACHEDSECONDARYDEVICES | 
    		DDENUM_DETACHEDSECONDARYDEVICES | 
    		DDENUM_NONDISPLAYDEVICES
    		);
    	m_lpddraw = mi_lpdd.lpDD;
    	if(m_lpddraw == NULL)
    	{
    		if (DirectDrawCreateEx(NULL, (VOID**)&m_lpddraw,IID_IDirectDraw7,NULL) != DD_OK) 
    		{
    			OutputDebugStringA("display::init 创建DirectDraw NOK
    ");
    		}
    		if (!m_lpddraw)
    		{
    			OutputDebugStringA("display::init 2创建DirectDraw NOK
    ");
    			return -1;
    		}
    	}
    	if (m_lpddraw->SetCooperativeLevel(/*pcd->hRenderWnd*/NULL,
    		DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES | DDSCL_ALLOWREBOOT ) != DD_OK)
    	{
    		OutputDebugStringA("display::init 创建lpDDxiezuo error!
    ");
    		if (m_lpddraw)
    		{
    			m_lpddraw->Release();
    			m_lpddraw = NULL;
    		}
    		return -1;
    	}
    	// 创建主表面
    	DDSURFACEDESC2			ddsd;				// DirectDraw 表面描述
    	ZeroMemory(&ddsd, sizeof(ddsd));
    	ddsd.dwSize = sizeof(ddsd);
    	ddsd.dwFlags = DDSD_CAPS;// | DDSD_BACKBUFFERCOUNT;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    	//ddsd.dwBackBufferCount = 1;
    	if (m_lpddraw->CreateSurface(&ddsd, &m_lpddsprimary, NULL) != DD_OK)
    	{
    		OutputDebugStringA("display::init 创建m_lpddsprimary error!
    ");
    		if (m_lpddraw)
    		{
    			m_lpddraw->Release();
    			m_lpddraw = NULL;
    		}
    		return -1;
    	}
    	if(m_lpddraw->CreateClipper(0, &m_lpclipper, NULL) != DD_OK)
    	{
    		if (m_lpddraw)
    		{
    			m_lpddraw->Release();
    			m_lpddraw = NULL;
    		}
    		OutputDebugStringA("display::init 创建m_lpclipper error!
    ");
    		return -1;
    	}
    
    	m_lpclipper->SetHWnd(0, hwnd);
    	m_lpddsprimary->SetClipper(m_lpclipper);
    	m_init = true;
    	return 0;
    }
    
    void display::uninit()
    {
    	if (m_lpddsoffscr)
    	{
    		m_lpddsoffscr->Release();
    		m_lpddsoffscr = NULL;
    	}
    	if (m_lpddsoffscr2)
    	{
    		m_lpddsoffscr2->Release();
    		m_lpddsoffscr2 = NULL;
    	}
    	if (m_lpddsprimary)
    	{
    		m_lpddsprimary->Release();
    		m_lpddsprimary = NULL;
    	}
    	if (m_lpclipper)
    	{
    		m_lpclipper->Release();
    		m_lpclipper = NULL;
    	}
    	if (m_lpddraw)
    	{
    		m_lpddraw->Release();
    		m_lpddraw = NULL;
    	}
    	m_init = false;
    }
    
    unsigned __int64 display::createddsd(DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype)
    {
    	ddsd->dwSize = sizeof(*ddsd);
    	ddsd->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY ; //DDSCAPS_OVERLAY DDSCAPS_OFFSCREENPLAIN;
    	ddsd->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;// | DDSD_PITCH | DDSD_LPSURFACE;
    	ddsd->dwWidth = nwidth;
    	ddsd->dwHeight = nheight;
    	ddsd->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    	ddsd->ddpfPixelFormat.dwFlags = DDPF_FOURCC;
    	if ( ntype == 2)
    	{
    		ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('R','G','B',' ');
    		ddsd->ddpfPixelFormat.dwFlags |= DDPF_RGB;
    		ddsd->ddpfPixelFormat.dwRGBBitCount = 32;
    	}
    	else if ( ntype == 3)
    	{
    		ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','1','2');
    		ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
    		ddsd->ddpfPixelFormat.dwYUVBitCount = 12;
    	}
    	else if ( ntype == 4)
    	{
    		ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('U','Y','V','Y');
    		ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
    		ddsd->ddpfPixelFormat.dwYUVBitCount = 16;
    	}
    	else if ( ntype == 5)
    	{
    		ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC(/*'I','4','2','0'*/'Y','V','1','2');
    		ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
    		ddsd->ddpfPixelFormat.dwYUVBitCount = 12;
    	}
    	else if ( ntype == 6)
    	{
    		ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2'); //or YUYV. the same format.
    		ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
    		ddsd->ddpfPixelFormat.dwYUVBitCount = 16;
    	}
    	else
    	{
    		OutputDebugStringA("************LOG_RTM, unsupported pixel format: %d, pcd->m_bdInRender.nType
    ");
    		return -1;
    	}
    	return 0;
    }
    
    void display::refrush()
    {
    	//m_lpddsprimary->Blt(&m_rctDest, m_lpddsoffscr, &m_rctSour, DDBLT_WAIT, &m_ddbltfx); 
    }
    
    unsigned __int64 display::createoffscreen(LPDIRECTDRAWSURFACE7 * offscreen, DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype)
    {
    	unsigned __int64 nerror = 0;
    	//DDERR_UNSUPPORTEDMODE;
    	HRESULT result = m_lpddraw->CreateSurface(ddsd, offscreen, NULL);
    	if(FAILED (result))
    	{
    		if (result == DDERR_NODIRECTDRAWHW)
    		{
    			reinit();
    		}
    		return -1;
    	}
    	return 0;
    }
    
    unsigned __int64 display::wait_ctrl(unsigned __int64 npts)
    {
    	return 0;
    }
    
    unsigned __int64 display::inputsource(unsigned char * src, long nwidth, long nheight, long ntype, long nrate, unsigned __int64 npts)
    {
    	if (!m_init)
    	{
    		return -1;
    	}
    	unsigned __int64 nerror = 0;
    	if (!m_lpddsoffscr || m_lastwidth != nwidth || m_lastheight != nheight)
    	{
    		if (m_lpddsoffscr)
    		{
    			m_lpddsoffscr->Release();
    			m_lpddsoffscr = NULL;
    		}
    		nerror = createddsd(&m_ddsd, nwidth, nheight, ntype);
    		if (nerror)
    		{
    			OutputDebugStringA("display::inputsource createddsd error[m_lpddsoffscr equ null]
    ");
    			return -1;
    		}
    		nerror = createoffscreen(&m_lpddsoffscr, &m_ddsd, nwidth, nheight, ntype);
    		if (nerror)
    		{
    			OutputDebugStringA("display::inputsource createoffscreen error[m_lpddsoffscr equ null]
    ");
    			return -1;
    		}
    	}
    	if (!m_lpddsoffscr)
    	{
    		OutputDebugStringA("display::inputsource error[m_lpddsoffscr equ null]
    ");
    		return -1;
    	}
    	HRESULT hr = m_lpddsoffscr->Lock(NULL,&m_ddsd, DDLOCK_WAIT |DDLOCK_WRITEONLY,NULL);
    	if (hr == DDERR_SURFACELOST) 
    	{
            OutputDebugStringA("DDERR_SURFACELOST DDERR_SURFACELOST DDERR_SURFACELOST...1
    ");
    		hr = m_lpddsoffscr->Restore(); 
    		hr = (hr != DD_OK)? hr : m_lpddsoffscr->Lock(NULL,&m_ddsd,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL); 
    	}
    	if (hr != DD_OK)
    	{
    		OutputDebugStringA("display::inputsource  Lock error
    ");
    		return -1;
    	}
    
    	m_lastwidth = nwidth;
    	m_lastheight = nheight;
    	LPBYTE lpSurf = (LPBYTE)m_ddsd.lpSurface;
    	LPBYTE lpSurfV = lpSurf + m_ddsd.dwHeight*m_ddsd.lPitch;
    	LPBYTE lpSurfU = lpSurfV + (m_ddsd.dwHeight*m_ddsd.lPitch>>2);
    	if (3 == ntype || 5 == ntype)
    	{
    		LPBYTE lpY = src;
    		LPBYTE lpU;
    		LPBYTE lpV;
    		if (3 == ntype)
    		{
    			lpV = lpY + nwidth * nheight;
    			lpU = lpV + (nwidth * nheight>>2);
    		}
    		else
    		{
    			lpU = lpY + nwidth * nheight;
    			lpV = lpU + (nwidth * nheight>>2);
    		}
    		// 填充离屏表面
    		long lddsdHeightHalf = m_ddsd.dwHeight>>1;
    		long lddsdlPitchHalf = m_ddsd.lPitch>>1; 
    		long lWidhtHalf = nwidth>>1;
    		for(unsigned int i = 0; i < m_ddsd.dwHeight; i++)
    		{
    			memcpy(lpSurf, lpY, nwidth);
    			lpY += nwidth;
    			lpSurf += m_ddsd.lPitch;
    
    			if (i < lddsdHeightHalf)
    			{
    				memcpy(lpSurfU, lpU, lWidhtHalf);				
    				lpU += lWidhtHalf;
    				lpSurfU += lddsdlPitchHalf;
    
    				memcpy(lpSurfV, lpV, lWidhtHalf);
    				lpV += lWidhtHalf;
    				lpSurfV += lddsdlPitchHalf;				
    			}
    		}
    	}
    	
    	m_lpddsoffscr->Unlock(NULL);
    
    //  	RECT rctDest;
    //  	GetClientRect(m_hwnd, &rctDest);
    //  	ClientToScreen(m_hwnd,(LPPOINT)&rctDest.left);
    //  	ClientToScreen(m_hwnd,(LPPOINT)&rctDest.right);
    //  	if (rctDest.left != m_rctDestLast.left || rctDest.top != m_rctDestLast.top 
    //  		|| rctDest.right != m_rctDestLast.right || rctDest.bottom != m_rctDestLast.bottom)
    	{
    		//m_rctDestLast = rctDest;
    		m_rctSour.left = 0;
    		m_rctSour.top = 0;
    		m_rctSour.right = m_ddsd.dwWidth;
    		m_rctSour.bottom = m_ddsd.dwHeight;
    
    		GetClientRect(m_hwnd, &m_rctDest);				
    		MONITORINFO mi;
    		memset(&mi, 0, sizeof(MONITORINFO));
    		mi.cbSize = sizeof(MONITORINFO);
    		HMONITOR hmon = ::MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
    		if (!hmon)
    		{
    			OutputDebugStringA("display::inputsource MonitorFromWindow error[hmon equ null]
    ");
    			return -1;
    		}
    		::GetMonitorInfo(hmon, &mi);
    		m_rctDest.left -= mi.rcMonitor.left;
    		m_rctDest.right -= mi.rcMonitor.left;
    		m_rctDest.top -= mi.rcMonitor.top;
    		m_rctDest.bottom -= mi.rcMonitor.top;
    		ClientToScreen(m_hwnd, (LPPOINT)&m_rctDest.left);
    		ClientToScreen(m_hwnd, (LPPOINT)&m_rctDest.right);
    		
    		memset(&m_ddbltfx, 0, sizeof(m_ddbltfx));
    		m_ddbltfx.dwSize = sizeof(m_ddbltfx);
    		m_ddbltfx.dwROP = SRCCOPY;
    	}
    		
    	// Blt到主表面上
    	HRESULT hr2 = m_lpddsprimary->Blt(&m_rctDest, m_lpddsoffscr, &m_rctSour, DDBLT_WAIT, &m_ddbltfx); 
    	if (hr2 == DDERR_SURFACELOST)
    	{
            OutputDebugStringA("DDERR_SURFACELOST DDERR_SURFACELOST DDERR_SURFACELOST...
    ");
    		hr2 = m_lpddsprimary->Restore();
    	}
    	if (hr2 != DD_OK)
    	{
    		OutputDebugStringA("display::inputsource Blt error
    ");
    		return -1;
    	}
    	return 0;
    }
  • 相关阅读:
    Xcode编译报错信息总结
    iOS组件化方案
    xcodebuild命令
    Mac下配置MAMP Pro+PHPStorm
    Sublime Text PHP Mac系统环境配置
    JS生成二维码
    为IE和chrome编写单独的样式
    几个简单的VBS脚本程序以及其JS实现
    vue组件中使用iframe元素
    nginx简易部署
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049144.html
Copyright © 2011-2022 走看看