教育、会議、情報発信は、同じ画面をライブストリーミングメディアの記録と放送を満たし、ライブ途中のD3Dによって達成スクリーンキャプチャソフトウェアlibEasyScreenLive

情報化時代の到来、より多くの広く教育、会議、イベントで同じスクリーン技術のアプリケーションと。エンド画面殻は、携帯電話、タブレットなどのモバイル機器の表示装置に無線または有線ネットワークの同期上上記オーディオ及びビデオデータの一部です。換言すれば、上記表示周波数画面にモバイルデバイスのオーディオおよびビデオデータにおけるシーン。表示画面上に表示されているものを探しガラス、何のモバイルデバイスの表示、などがあります。

EasyScreenlive.png

D3Dモード画面キャプチャによって達成libEasyScreenLive

libEasyScreenLiveでは、取得GDIモード画面を通じて達成している、しかし、実際の遅延よりもデスクトップビデオフレームリフレッシュデスクトップ画面の買収につながったGDI収集方法の低効率は、この遅延はテストされていると、ほぼ50ミリ秒に達することができます私たちは、画面で非常に低遅延を必要とすることは、コレクションが極めて低いレイテンシーとなっている、需要と一致していないので、私たちは、買収によってD3D、このアプローチは、ハードウェアドライバをスケジュールすることができ、より優れたパフォーマンス、およびキャプチャ60fpsのフレームレートはより多くを達することができます。

主にCD3DCaptureScreemクラスによる方法によってlibEasyScreenLive取得画面のD3Dでは、次の文:

#include <d3d9.h>
#include <WinError.h>

typedef struct IDirect3D9* LPDIRECT3D9, *PDIRECT3D9;
typedef struct IDirect3DDevice9* LPDIRECT3DDevice9, *PDIRECT3DDevice9;
typedef struct IDirect3DSurface9* LPDIRECT3DSurface9, *PDIRECT3DSurface9;

typedef int (WINAPI *CaptureScreenCallback)(int nDevId, unsigned char *pBuffer, int nBufSize, int nRealDatatYPE, void* realDataInfo, void* pMaster);

	class CD3DCaptureScreem
	{
	public:
		CD3DCaptureScreem(void);
		~CD3DCaptureScreem(void);

		//接口函数
		// 初始化
		HRESULT    InitD3DCapture(HWND hShowWnd);
		//direct实现的截图
		void DirectScreenCapture(LPVOID screenCaptureData);

		//创建线程进行屏幕捕获
		int CreateCaptureScreenThread();
		static UINT WINAPI CaptureScreenThread(LPVOID pParam);
		void CaptureVideoProcess();
		//设置捕获数据回调函数
		void SetCaptureScreenCallback(CaptureScreenCallback callBack, void * pMaster);

		BOOL IsInCapturing()
		{
			return m_bCaptureScreen;
		}
		void GetCaptureScreenSize(int& nWidth, int& nHeight );
		bool Convert24Image(BYTE *p32Img, BYTE *p24Img,DWORD dwSize32);
		void StopD3DScreenCapture();

	private:
		HWND m_hMainWnd;
		/*IDirect3D9**/  LPDIRECT3D9            m_pD3DScreenCapture;
		/*IDirect3DDevice9* */LPDIRECT3DDevice9   m_pd3dDevice;
		/*IDirect3DSurface9**/ LPDIRECT3DSurface9  m_pSurface;
		CaptureScreenCallback m_pCallback;
		void* m_pMaster;

		int m_nCapWidth;
		int m_nCapHeight;
		LPVOID					m_pScreenCaptureData;
		RECT							m_ScreenRect;
		HANDLE m_hScreenCaptureThread;
		BOOL m_bCaptureScreen;
	};

私たちはただD3D9は、以下の機能を実現するために(一時的にマウスをキャプチャしていない)、再びそれを取るレンダリング処理設備をキャプチャする必要がある、GDIの方法よりも簡単に実現する取得D3Dを経由してインターフェースから見ることができます:

HRESULT   CD3DCaptureScreem:: InitD3DCapture(HWND hShowWnd)
{
	m_hMainWnd  = hShowWnd;

	BITMAPINFO    bmpInfo;
	ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
	bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biBitCount=32;
	bmpInfo.bmiHeader.biCompression = BI_RGB;
	bmpInfo.bmiHeader.biWidth=GetSystemMetrics(SM_CXSCREEN);
	bmpInfo.bmiHeader.biHeight=GetSystemMetrics(SM_CYSCREEN);
	bmpInfo.bmiHeader.biPlanes=1;
	bmpInfo.bmiHeader.biSizeImage=abs(bmpInfo.bmiHeader.biHeight)*bmpInfo.bmiHeader.biWidth*bmpInfo.bmiHeader.biBitCount/8;

	HDC    hdc=GetDC(GetDesktopWindow());
	HDC        hBackDC=NULL;
	HBITMAP    hBackBitmap=NULL;
	hBackDC=CreateCompatibleDC(hdc);
	hBackBitmap=CreateDIBSection(hdc,&bmpInfo,DIB_RGB_COLORS,&m_pScreenCaptureData,NULL,0);
	if(hBackBitmap==NULL)
	{
		return 0 ;
	}
	ReleaseDC(GetDesktopWindow(),hdc);

	HWND hWnd = hShowWnd;
	D3DDISPLAYMODE    ddm;
	D3DPRESENT_PARAMETERS    d3dpp;

	if((m_pD3DScreenCapture=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
	{
		return E_FAIL;
	}

	if(FAILED(m_pD3DScreenCapture->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
	{
		return E_FAIL;
	}

	ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));

	d3dpp.Windowed=true;
	d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
	d3dpp.BackBufferFormat=ddm.Format;
	d3dpp.BackBufferHeight=m_ScreenRect.bottom =ddm.Height;
	d3dpp.BackBufferWidth=m_ScreenRect.right =ddm.Width;
	d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow=hWnd;
	d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
	d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;

	if(FAILED(m_pD3DScreenCapture->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING ,&d3dpp,&m_pd3dDevice)))
	{
		return E_FAIL;
	}
	m_nCapWidth = ddm.Width;
	m_nCapHeight = ddm.Height;
	if(FAILED(m_pd3dDevice->CreateOffscreenPlainSurface(m_nCapWidth, m_nCapHeight, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &m_pSurface, NULL)))
	{
		return E_FAIL;
	}
	CreateCaptureScreenThread();
	return S_OK;
}

void CD3DCaptureScreem::StopD3DScreenCapture()
{
	m_bCaptureScreen = 0;
	//等待线程结束
	//Sleep(300);
	//获取线程结束代码 ,如果线程还在运行就等她结束
	while (1)
	{
		DWORD dwExitCode ;
		::GetExitCodeThread(m_hScreenCaptureThread,&dwExitCode);
		if(dwExitCode == STILL_ACTIVE)
		{
			WaitForSingleObject(m_hScreenCaptureThread, 100); 
		}
		else
		{
			break;
		}
	}
	CloseHandle(m_hScreenCaptureThread);
	m_hScreenCaptureThread = INVALID_HANDLE_VALUE;

	m_pSurface->Release();
	m_pd3dDevice->Release();
	m_pD3DScreenCapture->Release();

}

//direct实现的截图
void CD3DCaptureScreem::DirectScreenCapture(LPVOID screenCaptureData)
{
	m_pd3dDevice->GetFrontBufferData(0, m_pSurface);
	D3DLOCKED_RECT    lockedRect;
	if(FAILED(m_pSurface->LockRect(&lockedRect,&m_ScreenRect,D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY)))
	{
		return;
	}
// 	for(int i=0;i<m_ScreenRect.bottom;i++)
// 	{
// 	}
	memcpy((BYTE*)screenCaptureData/*+(i)*m_ScreenRect.right*32/8*/,    (BYTE*)lockedRect.pBits/*+i*lockedRect.Pitch*/,    m_ScreenRect.bottom*m_ScreenRect.right<<2);
	m_pSurface->UnlockRect();
	//printf("%d\n" , l3);
}

//创建线程进行屏幕捕获
int CD3DCaptureScreem::CreateCaptureScreenThread()
{
	//创建线程
	m_bCaptureScreen = TRUE;
	m_hScreenCaptureThread=(HANDLE)_beginthreadex(NULL,0,(&CD3DCaptureScreem::CaptureScreenThread),
		this,THREAD_PRIORITY_NORMAL,NULL);
	return 1;
}
UINT WINAPI CD3DCaptureScreem::CaptureScreenThread(LPVOID pParam)
{
	if (pParam)
	{
		CD3DCaptureScreem* pMaster = (CD3DCaptureScreem*)pParam;
		if (pMaster)
		{
			pMaster->CaptureVideoProcess();
		}
	}
	return 0;
}

void CD3DCaptureScreem::CaptureVideoProcess()
{
	unsigned char * screenData = new unsigned char[1920*1080*4];
	unsigned char * screenData24 = new unsigned char[1920*1080*3];

	while (m_bCaptureScreen)
	{
		DirectScreenCapture(screenData);
		Convert24Image(screenData, screenData24, 1920*1080*4);
#if 0
		//显示图像
		HWND hWnd=m_hMainWnd;
		HDC hDC=::GetDC(hWnd);

		::SetTextColor( hDC, RGB( 255, 255, 255 ) );
		::SetBkMode( hDC, TRANSPARENT );
		::SetStretchBltMode( hDC, COLORONCOLOR );

		CRect rect;
		::GetClientRect(m_hMainWnd, &rect);

		BITMAPINFO bmi;
		memset(&bmi, 0, sizeof(bmi));
		bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
		bmi.bmiHeader.biWidth       = 1920;
		bmi.bmiHeader.biHeight      = -1080; // top-down image 
		bmi.bmiHeader.biPlanes      = 1;
		bmi.bmiHeader.biBitCount    = 32;//m_nColorBits;
		bmi.bmiHeader.biCompression = BI_RGB;
		bmi.bmiHeader.biSizeImage   = 0;

		unsigned char * pData = (unsigned char *)screenData ;
		::SetDIBitsToDevice( hDC, 0, 0, /*rect.Width()*/640, /*rect.Height()*/480, 0, 0, 0, 1080, (LPBYTE)pData , &bmi, DIB_RGB_COLORS );

#endif
		if (m_pCallback&&m_pMaster)
		{
			ScreenCapDataInfo sCapScreenInfo;
			sCapScreenInfo.nWidth = m_nCapWidth;
			sCapScreenInfo.nHeight = m_nCapHeight;
			sCapScreenInfo.nDataType = 24;
			strcpy(sCapScreenInfo.strDataType, "RGB24");
			m_pCallback(0, (unsigned char*)(screenData24), /*alpbi->biSizeImage*/m_nCapWidth*m_nCapHeight*3, 1, &sCapScreenInfo, m_pMaster);

		} 
		//Sleep(30);
	}

	if (screenData)
	{
		delete screenData;
		screenData = NULL;
	}
	if(screenData24)
	{
		delete screenData24;
		screenData24 = NULL;
	}
}

bool CD3DCaptureScreem::Convert24Image(BYTE *p32Img, BYTE *p24Img,DWORD dwSize32)  
{  
    if(p32Img != NULL && p24Img != NULL && dwSize32>0)  
    {  
  
        DWORD dwSize24;  
  
        dwSize24=(dwSize32 * 3)/4;  
  
        BYTE *pTemp,*ptr;  
  
        pTemp=p32Img;  
        ptr = p24Img;  
  
        int ival=0;  
        for (DWORD index = 0; index < dwSize32/4 ; index++)  
        {                                     
            unsigned char r = *(pTemp++);  
            unsigned char g = *(pTemp++);  
            unsigned char b = *(pTemp++);  
            (pTemp++);//skip alpha  
  
            *(ptr++) = r;  
            *(ptr++) = g;  
            *(ptr++) = b;  
        }     
    }  
    else  
    {  
        return false;  
    }  
  
    return true;  
}  

//设置捕获数据回调函数
void CD3DCaptureScreem::SetCaptureScreenCallback(CaptureScreenCallback callBack, void * pMaster)
{
	m_pCallback = callBack;
	m_pMaster = pMaster;
}

void CD3DCaptureScreem::GetCaptureScreenSize(int& nWidth, int& nHeight )
{
	nWidth = m_nCapWidth;
	nHeight = m_nCapHeight;
}

EasyScreenliveシナリオ

広く大画面表示画面で使用EasyScreenlive投票など同じ画面ペーパーレス会議、プレゼンテーション、教室と同じ画面には、フルスクリーンで使用することができ、アナログタッチリモコン機能(AndroidのコントロールのWindows、WindowsのコントロールのAndroid、Windowsや他のWindowsのコントロールを逆転)

.jpgシナリオとビデオの画面

おすすめ

転載: www.cnblogs.com/TSINGSEE/p/11684564.html