www.gusucode.com > VC++远程视频监控系统源代码-源码程序 > VC++远程视频监控系统源代码-源码程序/code/AV8SDK/AV8SDK/Demo/PlayWnd.cpp

    // PlayWnd.cpp : implementation file
//

#include "stdafx.h"
#include "MAV8.h"
#include "PlayWnd.h"

#include ".\av8inc\av8api.h"
#include ".\av8inc\define.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WM_DATABLOCK_UPDATE		WM_USER+20

#define CHECK_ERROR(x, idFailMsg) if (FAILED(hr = (x))) { if (idFailMsg) MessageBox(idFailMsg); return;}
#define HELPER_RELEASE(x) {if(x) x -> Release(); x = NULL;} // 控件释放

BOOL	Rendered;
PBYTE	pbMem[100];
int		rIndex = 0;
extern BOOL Ready;
extern PBYTE Ptr[];

BOOL PeekAndPump()
{
	static MSG msg;

	while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
		if (!AfxGetApp()->PumpMessage()) {
			::PostQuitMessage(0);
			return FALSE;
		}	
	}

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
class CMemStream : public CAsyncStream
{
public:
    CMemStream( LPBYTE pbData, LONGLONG llLength, DWORD dwKBPerSec = INFINITE) :
		m_pbData(pbData),
        m_llLength(llLength),
        m_llPosition(0),
        m_dwKBPerSec(dwKBPerSec)
    {
        m_dwTimeStart = timeGetTime();
    }

    HRESULT SetPointer(LONGLONG llPos)
    {
        if (llPos < 0 || llPos > m_llLength) {
            return S_FALSE;
        } else {
            m_llPosition = llPos;
            return S_OK;
        }
    }
    HRESULT Read(PBYTE pbBuffer,
                 DWORD dwBytesToRead,
                 BOOL bAlign,
                 LPDWORD pdwBytesRead)
    {
        CAutoLock lck(&m_csLock);
        DWORD dwReadLength;
        ///*  Wait until the bytes are here! 
        DWORD dwTime = timeGetTime();
        if (m_llPosition + dwBytesToRead > m_llLength) {
            dwReadLength = (DWORD)(m_llLength - m_llPosition);
        } else {
            dwReadLength = dwBytesToRead;
        }
        DWORD dwTimeToArrive =
            ((DWORD)m_llPosition + dwReadLength) / m_dwKBPerSec;
        if (dwTime - m_dwTimeStart < dwTimeToArrive) {
            Sleep(dwTimeToArrive - dwTime + m_dwTimeStart);
        }

		while (!Ready) {
			PeekAndPump();
		}
        CopyMemory((PVOID)pbBuffer, (PVOID)(Ptr[rIndex]), dwReadLength);
		TRACE1 ("Read Addr = %lX\n",(DWORD)(Ptr[rIndex]));

		rIndex = (rIndex + 1) % 100;
		Ready = false;
        m_llPosition += dwReadLength;
        *pdwBytesRead = dwReadLength;
        return S_OK;
    }
    LONGLONG Size(LONGLONG *pSizeAvailable)
    {
        LONGLONG llCurrentAvailable =
            Int32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec);
        *pSizeAvailable = min(m_llLength, llCurrentAvailable);
        return m_llLength;
    }
    DWORD Alignment()
    {
        return 1;
    }
    void Lock()
    {
        m_csLock.Lock();
    }
    void Unlock()
    {
        m_csLock.Unlock();
    }

private:
    CCritSec       m_csLock;
    const PBYTE    m_pbData;
    const LONGLONG m_llLength;
    LONGLONG       m_llPosition;
    DWORD          m_dwKBPerSec;
    DWORD          m_dwTimeStart;
};

class CMemReader : public CAsyncReader
{
public:

    //  We're not going to be CoCreate'd so we don't need registration
    //  stuff etc
    STDMETHODIMP Register()
    {
        return S_OK;
    }
    STDMETHODIMP Unregister()
    {
        return S_OK;
    }
    CMemReader(CMemStream *pStream, CMediaType *pmt, HRESULT *phr) :
        CAsyncReader(NAME("Mem Reader"), NULL, pStream, phr)
    {
        m_mt = *pmt;
    }
};

/////////////////////////////////////////////////////////////////////////////
// CPlayWnd 

IMPLEMENT_DYNCREATE(CPlayWnd, CFrameWnd)

CPlayWnd::CPlayWnd()
{
	m_pStream = NULL;
	m_rdr = NULL;
	m_pivw = NULL; 
	m_pifg = NULL;
	m_pigb = NULL;
	m_pimc = NULL;
	
	CRect rect;

	rect.left = 0;
	rect.top = 0;
	rect.right = 352+GetSystemMetrics(SM_CXFRAME) + 5;
	rect.bottom = 288+GetSystemMetrics(SM_CYFRAME)+ 
		//GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYMENU);
		GetSystemMetrics(SM_CYCAPTION) + 10;

	CFrameWnd::Create(NULL, "Playback Window",WS_OVERLAPPEDWINDOW, rect);
}

CPlayWnd::~CPlayWnd()
{
}


BEGIN_MESSAGE_MAP(CPlayWnd, CFrameWnd)
	//{{AFX_MSG_MAP(CPlayWnd)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPlayWnd message handlers

int CPlayWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
    CoInitialize(NULL);
	
	for (int i = 0; i< 100; i++ )
		pbMem[i] = new BYTE [0x8000];

	m_pStream = new CMemStream(NULL, 0x80000000, INFINITE);

	mt.majortype = MEDIATYPE_Stream;
    mt.subtype = MEDIASUBTYPE_MPEG1System;

	hr = S_OK;
    m_rdr = new CMemReader(m_pStream, &mt, &hr);
	
    if(FAILED(hr) || m_rdr == NULL)
	{
		MessageBox("CMemReader Error");
		return 0;
	}

	InitFilter ();
	Ready = false;
	Rendered = false;

	return 0;
}

void CPlayWnd::InitFilter ()
{
	CHECK_ERROR(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IFilterGraph, (void**)&m_pifg),"CoCreateInstance Error") ;
	    
	CHECK_ERROR(m_pifg -> AddFilter(m_rdr, NULL), "AddFilter Error");
    
	CHECK_ERROR(m_pifg -> QueryInterface(IID_IGraphBuilder, (void **)&m_pigb),"QueryInterface(IGraphBuilder) Error");
    
	CHECK_ERROR(m_pigb -> QueryInterface(IID_IMediaControl, (void **)&m_pimc),"QueryInterface(IMediaControl) Error");

    CHECK_ERROR(m_pigb -> QueryInterface(IID_IVideoWindow, (void **)&m_pivw),"QueryInterface(IVideoWindow) Error");

}

void CPlayWnd::OnDestroy() 
{
	CFrameWnd::OnDestroy();
	
	if(m_pivw) {
		m_pivw -> put_Visible(OAFALSE);
		m_pivw -> put_Owner(NULL);
		HELPER_RELEASE(m_pivw);
	}

	HELPER_RELEASE(m_pifg);
	HELPER_RELEASE(m_pigb);
	HELPER_RELEASE(m_pimc);

	for (int i = 0; i< 100; i++) {
		if (pbMem[i]) {
			delete pbMem[i];
			pbMem[i] = NULL;
		}
	}

	if(m_pStream) {
		delete m_pStream;
		m_pStream = NULL;
	}

	if(m_rdr) {
		delete m_rdr;
		m_rdr = NULL;
	}

    CoUninitialize();
	
}

BOOL CPlayWnd::PreCreateWindow(CREATESTRUCT& cs) 
{
	HBRUSH hBrushMagenta=::CreateSolidBrush(RGB(255, 0, 255));
	HCURSOR hCursor=::LoadCursor(NULL, IDC_ARROW);

	HICON hIcon = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_TSTLOGO));
	cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
				hCursor, hBrushMagenta, hIcon);

	DeleteObject(hBrushMagenta);
	nScreenX=GetSystemMetrics(SM_CXSCREEN);
	nScreenY=GetSystemMetrics(SM_CYSCREEN);
	return CFrameWnd::PreCreateWindow(cs);
}

void CPlayWnd::OnSize(UINT nType, int cx, int cy) 
{
#define DIVIDEVALUE		40
	// TODO: Add your message handler code here
	if(cx+(cx/DIVIDEVALUE) > nScreenX || 
	   cy+(cy/DIVIDEVALUE) > nScreenY){
 		// make the window size smaller to avoid the 352 and 360 problem
		CRect rect;
		rect.left=0;
		rect.top=0;
		rect.right= nScreenX - (nScreenX/DIVIDEVALUE) ;
		rect.bottom= nScreenY- (nScreenY/DIVIDEVALUE) ;
		SetWindowPos(&wndTop, rect.left, rect.top, 
			rect.right, rect.bottom+12, SWP_SHOWWINDOW);
	} else {
		// make the destination lager than window size, because 360 and 352 problem
		CFrameWnd::OnSize(nType, cx, cy);
	}
}

void CPlayWnd::Render ()
{
	if (m_pigb) {
			rIndex = 0;
			CHECK_ERROR(m_pigb -> Render(m_rdr -> GetPin(0)), "render Error");
			Rendered = true;
			m_pivw -> put_Owner((OAHWND)m_hWnd);    
			m_pivw -> put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

			RECT m_rc;
			GetClientRect(&m_rc);
			m_pivw -> SetWindowPosition(m_rc.left, m_rc.top, m_rc.right, m_rc.bottom);
			m_pimc -> Run();
	}

}