?? revplaymdichildwnd.cpp
字號(hào):
// RevPlayMDIChildWnd.cpp : implementation file
//
#include "stdafx.h"
#include "RevPlayThread.h"
#include "RevPlayMDIChildWnd.h"
#include "ConnectDlg.h"
#include "resource.h"
#include "asyncio.h"
#include "asyncrdr.h"
#include "mainfrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//#define IDC_REVPLAY_WND 1
#define LISTEN_PORT 1500
#define BUFSIZE 32768
#define WSA_CONNECT WM_USER+200
#define WSA_READ WM_USER+300 //讀取視頻數(shù)據(jù)
//{ 36a5f771-fe4c-11ce-a8ed-00aa002feab5 }
const CLSID CLSID_Stream = {
0x36a5f771, 0xfe4c, 0x11ce, 0xa8, 0xed, 0x00, 0xaa, 0x00, 0x2f, 0xea, 0xb5
};
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_NULL, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN sudPins =
{
L"Input", // Pin string name
FALSE, // Is it rendered
FALSE, // Is it an output
FALSE, // Allowed none
FALSE, // Likewise many
&CLSID_NULL, // Connects to filter
L"Output", // Connects to pin
1, // Number of types
&sudPinTypes // Pin information
};
const AMOVIESETUP_FILTER sudStream =
{
&CLSID_Stream, // Filter CLSID
L"Stream", // String name
MERIT_DO_NOT_USE, // Filter merit
1, // Number pins
&sudPins // Pin details
};
//
// Object creation stuff
//
CFactoryTemplate g_Templates[]= {
L"Stream", &CLSID_Stream, NULL, NULL, &sudStream
};
int g_cTemplates = 1;
class CMemStream : public CAsyncStream
{
public:
CRevPlayWnd* pWnd; //接收播放窗口指針
public:
BOOL PeekAndPump();
CMemStream( LPBYTE pbData, LONGLONG llLength, DWORD dwKBPerSec = INFINITE) :
m_pbData(pbData),
m_llLength(llLength),
m_llPosition(0),
m_dwKBPerSec(dwKBPerSec)
{
m_dwTimeStart = timeGetTime();
}
//設(shè)置當(dāng)前位置
HRESULT SetPointer(LONGLONG llPos)
{
if (llPos < 0 || llPos > m_llLength) {
return S_FALSE;
} else {
m_llPosition = llPos;
return S_OK;
}
}
//當(dāng)MPEG1 Stream Splitter請(qǐng)求數(shù)據(jù)時(shí),由Read函數(shù)提供
HRESULT Read(PBYTE pbBuffer,
DWORD dwBytesToRead,
BOOL bAlign,
LPDWORD pdwBytesRead)
{
CAutoLock lck(&m_csLock);
DWORD dwReadLength, cbRet;
DWORD dwTime = timeGetTime();
//如果要求讀取的字節(jié)數(shù)大于剩余的字節(jié)數(shù),則只直接讀取剩余的字節(jié)
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);
}
static int rwIndex =0;
static int Block = pWnd->Block;
int temp=pWnd->rIndex;
// if (pWnd->m_RenderOk)
// {
/* while (rwIndex>temp)
PeekAndPump();*/
//將存放接收的數(shù)據(jù)緩沖區(qū)數(shù)組中的數(shù)據(jù)拷貝到pbBuffer中,傳給Splitter
CopyMemory((PVOID)pbBuffer, (PVOID)(pWnd->pRevMem[rwIndex]), pWnd->RevLen);
rwIndex = (rwIndex + 1) % 100;
TRACE1("Read Addr = %d\n",rwIndex);
cbRet=pWnd->RevLen;
// }
/* else
{
if (Block == 0)
{
CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData),
dwReadLength);
Block ++;
}
else
{
CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData + dwReadLength),
dwReadLength);
Block = 0;
}
cbRet = dwReadLength;
}*/
//當(dāng)前位置向后移讀出的字節(jié)數(shù)
m_llPosition += cbRet;
*pdwBytesRead = cbRet;
if (cbRet != dwReadLength)
m_llLength = m_llPosition;
return S_OK;
}
//得到當(dāng)前的數(shù)據(jù)總長(zhǎng)度
LONGLONG Size(LONGLONG *pSizeAvailable)
{
LONGLONG llCurrentAvailable =
Int32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec);
*pSizeAvailable = min(m_llLength, llCurrentAvailable);
return m_llLength;
}
DWORD Alignment()
{
//按1字節(jié)對(duì)齊
return 1;
}
void Lock()
{
m_csLock.Lock();
}
void Unlock()
{
m_csLock.Unlock();
}
private:
CCritSec m_csLock; //數(shù)據(jù)操作的同步對(duì)象
const PBYTE m_pbData; //讀寫(xiě)的內(nèi)存數(shù)據(jù)指針
LONGLONG m_llLength; //數(shù)據(jù)總長(zhǎng)度
LONGLONG m_llPosition; //實(shí)際讀寫(xiě)的內(nèi)存數(shù)據(jù)位置指針
DWORD m_dwKBPerSec; //播放的的速率
DWORD m_dwTimeStart;//開(kāi)始時(shí)間
};
class CMemReader : public CAsyncReader
{
public:
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;
}
};
/////////////////////////////////////////////////////////////////////////////
// CRevPlayMDIChildWnd
CMenu CRevPlayMDIChildWnd::menu;
IMPLEMENT_DYNCREATE(CRevPlayMDIChildWnd, CMDIChildWnd)
CRevPlayMDIChildWnd::CRevPlayMDIChildWnd()
{
}
CRevPlayMDIChildWnd::~CRevPlayMDIChildWnd()
{
}
BEGIN_MESSAGE_MAP(CRevPlayMDIChildWnd, CMDIChildWnd)
//{{AFX_MSG_MAP(CRevPlayMDIChildWnd)
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_USER_PREPARE_TO_CLOSE, OnPrepareToClose)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRevPlayMDIChildWnd message handlers
BOOL CRevPlayMDIChildWnd::Create(LPCTSTR szTitle, const RECT &rect, CMDIFrameWnd *parent)
{
if (menu.m_hMenu == NULL)
menu.LoadMenu(IDR_REVPLAY);
m_hMenuShared = menu.m_hMenu;
//創(chuàng)建子窗口
if (!CMDIChildWnd::Create(NULL, szTitle, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, rect, parent))
return FALSE;
//生成UI線(xiàn)程對(duì)象
CRevPlayThread* pRevPlayThread = new CRevPlayThread(m_hWnd);
//創(chuàng)建線(xiàn)程
pRevPlayThread->CreateThread();
return TRUE;
}
BOOL CRevPlayMDIChildWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
CWnd* pRevPlayWnd = (CRevPlayWnd*)GetDlgItem(IDC_REVPLAY_WND);
if (pRevPlayWnd == NULL)
return FALSE;
COnCmdMsg oncmdmsg;
oncmdmsg.m_nID = nID;
oncmdmsg.m_nCode = nCode;
oncmdmsg.m_pExtra = pExtra;
oncmdmsg.m_pHandlerInfo = pHandlerInfo;
return pRevPlayWnd->SendMessage(WM_USER_ONCMDMSG,
0, (LPARAM)&oncmdmsg);
}
void CRevPlayMDIChildWnd::OnSize(UINT nType, int cx, int cy)
{
CMDIChildWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
CWnd* pRevPlayWnd = GetDlgItem(IDC_REVPLAY_WND);
if (pRevPlayWnd == NULL)
return; // child CBounceWnd not created yet
CRect rect;
GetClientRect(&rect);
pRevPlayWnd->SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
}
BOOL CRevPlayMDIChildWnd::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
OnPrepareToClose();
return CMDIChildWnd::DestroyWindow();
}
LRESULT CRevPlayMDIChildWnd::OnPrepareToClose(WPARAM wParam, LPARAM lParam)
{
CWnd* pRevPlayWnd = (CRevPlayWnd*)GetDlgItem(IDC_REVPLAY_WND);
pRevPlayWnd->SendMessage(WM_USER_PREPARE_TO_CLOSE);
WaitForSingleObject(CRevPlayThread::m_hEventRevPlayThreadKilled, INFINITE);
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// CRevPlayWnd
CRevPlayWnd::CRevPlayWnd()
{
m_LostBlock=0;
m_Receive=FALSE;
m_Save=FALSE;
m_FirstRead=TRUE;
m_RenderOk=FALSE;
m_Stop=FALSE;
rIndex=0; //pRevMem數(shù)組的標(biāo)記
g_rwIndex=0;
m_pStream=NULL;
m_rdr=NULL;
m_pifg = NULL;
m_pigb = NULL;
m_pimc = NULL;
m_pivw = NULL;
m_ppos = NULL;
hmmioSave = NULL;
}
CRevPlayWnd::~CRevPlayWnd()
{
}
BEGIN_MESSAGE_MAP(CRevPlayWnd, CWnd)
//{{AFX_MSG_MAP(CRevPlayWnd)
ON_WM_CREATE()
ON_COMMAND(IDR_SAVE, OnSave)
ON_WM_CONTEXTMENU()
ON_COMMAND(ID_STOP_RECEIVE, OnStopReceive)
ON_COMMAND(IDR_REV_PLAY, OnRevPlay)
ON_UPDATE_COMMAND_UI(IDR_SAVE, OnUpdateSave)
ON_UPDATE_COMMAND_UI(ID_STOP_RECEIVE, OnUpdateStopReceive)
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_USER_ONCMDMSG, OnDelegatedCmdMsg)
ON_MESSAGE(WM_USER_PREPARE_TO_CLOSE, OnPrepareToClose)
ON_MESSAGE(WSA_CONNECT,OnConnect)
ON_MESSAGE(WSA_READ,OnRead)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRevPlayWnd message handlers
LRESULT CRevPlayWnd::OnConnect(WPARAM wParam,LPARAM lParam)
{
int status;
int SendLen;
int socket;
char szRev[80];
char szBuff[80];
char Msg[]="請(qǐng)發(fā)送數(shù)據(jù)";
u_long block=0;
socket=(SOCKET)wParam;
if (WSAGETSELECTERROR(lParam))
{//建立連接失敗
MessageBox("不能連接服務(wù)器", "連接失敗", MB_OK);
if(WaitDlg)
WaitDlg.EndDialog(IDCANCEL);
//關(guān)閉socket
closesocket(socket);
return -1;
}
if (WSAGETSELECTEVENT(lParam) == FD_CONNECT)
{//成功建立連接
if(WaitDlg)
WaitDlg.EndDialog(IDCANCEL);
//發(fā)送請(qǐng)求發(fā)送數(shù)據(jù)命令給發(fā)送端
SendLen=send(socket,Msg,sizeof(Msg),0);
if(SendLen!=sizeof(Msg))
{//請(qǐng)求數(shù)據(jù)發(fā)送失敗
MessageBox("請(qǐng)求錯(cuò)誤" "Send");
closesocket(socket);
return -1;
}
if(SendLen==sizeof(Msg))
{
WSAAsyncSelect(socket,m_hWnd, 0, 0 );
status=ioctlsocket(socket,FIONBIO,&block);
if(status==SOCKET_ERROR)
{
sprintf(szBuff,"Err: %d",WSAGetLastError());
MessageBox(szBuff);
return -1;
}
//接收數(shù)據(jù)
status =recv(socket, szRev,sizeof(szRev),0);
if (status)
{
//得到組播IP地址和端口
sscanf(szRev,"%s%d",strDestAddr,&DestPort);
sprintf(szBuff,"請(qǐng)加入組:%s,端口:%d",strDestAddr,DestPort);
MessageBox(szBuff,"接收請(qǐng)求");
sprintf(szBuff,"接收播放:組:%s,端口:%d",strDestAddr,DestPort);
::SetWindowText(GetParent()->m_hWnd,szBuff);
//關(guān)閉socket
closesocket(socket);
}
if(status==0)
{
MessageBox("對(duì)方關(guān)閉連接");
closesocket(socket);
return -1;
}
}
}
return 0;
}
LRESULT CRevPlayWnd::OnRead(WPARAM wParam,LPARAM lParam)
{
DWORD dwRet;
REFTIME fTime;
REFERENCE_TIME llClock;
HRESULT hr;
RECT rect;
//接收組播數(shù)據(jù),存放到緩沖區(qū)stWSABuf中
RevLen=ReceiveData();
//將緩沖區(qū)stWSABuf中的數(shù)據(jù)拷貝到存放接收的數(shù)據(jù)的數(shù)組pRevMem中,
//以供DirectShow讀取
CopyMemory((PVOID)pRevMem[rIndex],(PVOID)stWSABuf.buf,RevLen);
rIndex=(rIndex+1)%100;
//將接收到的數(shù)據(jù)保存到文件中
if(hmmioSave)
mmioWrite(hmmioSave,stWSABuf.buf,RevLen);
if(m_FirstRead)
{//如果是第一次接收到數(shù)據(jù),啟動(dòng)DirectShow
fTime = 0.0;
dwRet = Parse ((PBYTE)stWSABuf.buf, stWSABuf.len, &llClock);
fTime = llClock / 90000.0;
if(dwRet == 0)
return -1;
if(InitGraph()==-1)
return -1;
if (abs (dwRet - 2048000) <= 16000) {
RenderFrom ((PBYTE)achInBuf, "2mpal.dat");
}
if (abs (dwRet - 1152000) <= 16000) {
RenderFrom ((PBYTE)achInBuf, "1mpal.dat");
}
if (abs (dwRet - 512000) <= 16000) {
RenderFrom ((PBYTE)achInBuf, "512pal.dat");
}
if (abs (dwRet - 256000) <= 16000) {
RenderFrom ((PBYTE)achInBuf, "256pal.dat");
}
Block = 0;
//使用智能連接,將Source Filter的輸出Pin連出去
if (FAILED(hr = m_pigb -> Render(m_rdr -> GetPin(0))))
{
if (hr != VFW_S_AUDIO_NOT_RENDERED && hr != VFW_E_NO_AUDIO_HARDWARE )
{
MessageBox ("Render Error");
WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,0);
HELPER_RELEASE(m_pifg);
HELPER_RELEASE(m_pigb);
HELPER_RELEASE(m_pimc);
HELPER_RELEASE(m_pivw);
HELPER_RELEASE(m_ppos);
return -1;
}
}
m_RenderOk = true;
//設(shè)置視頻窗口屬性
m_pivw -> put_Owner((OAHWND)m_hWnd);
m_pivw -> put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
GetClientRect(&rect);
m_pivw -> SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom);
//開(kāi)始播放
m_pimc -> Run();
m_ppos->put_CurrentPosition(fTime + 0.4);
m_Stop = TRUE;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -