www.gusucode.com > VC++远程视频监控系统源代码-源码程序 > VC++远程视频监控系统源代码-源码程序/code/接收端/接收端/revplaymdichildwnd.cpp
// 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 //读取视频数据 //{ 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(); } //设置当前位置 HRESULT SetPointer(LONGLONG llPos) { if (llPos < 0 || llPos > m_llLength) { return S_FALSE; } else { m_llPosition = llPos; return S_OK; } } //当MPEG1 Stream Splitter请求数据时,由Read函数提供 HRESULT Read(PBYTE pbBuffer, DWORD dwBytesToRead, BOOL bAlign, LPDWORD pdwBytesRead) { CAutoLock lck(&m_csLock); DWORD dwReadLength, cbRet; 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); } static int rwIndex =0; static int Block = pWnd->Block; int temp=pWnd->rIndex; // if (pWnd->m_RenderOk) // { /* while (rwIndex>temp) PeekAndPump();*/ //将存放接收的数据缓冲区数组中的数据拷贝到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; }*/ //当前位置向后移读出的字节数 m_llPosition += cbRet; *pdwBytesRead = cbRet; if (cbRet != dwReadLength) m_llLength = m_llPosition; 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() { //按1字节对齐 return 1; } void Lock() { m_csLock.Lock(); } void Unlock() { m_csLock.Unlock(); } private: CCritSec m_csLock; //数据操作的同步对象 const PBYTE m_pbData; //读写的内存数据指针 LONGLONG m_llLength; //数据总长度 LONGLONG m_llPosition; //实际读写的内存数据位置指针 DWORD m_dwKBPerSec; //播放的的速率 DWORD m_dwTimeStart;//开始时间 }; 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; //创建子窗口 if (!CMDIChildWnd::Create(NULL, szTitle, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, rect, parent)) return FALSE; //生成UI线程对象 CRevPlayThread* pRevPlayThread = new CRevPlayThread(m_hWnd); //创建线程 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数组的标记 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[]="请发送数据"; u_long block=0; socket=(SOCKET)wParam; if (WSAGETSELECTERROR(lParam)) {//建立连接失败 MessageBox("不能连接服务器", "连接失败", MB_OK); if(WaitDlg) WaitDlg.EndDialog(IDCANCEL); //关闭socket closesocket(socket); return -1; } if (WSAGETSELECTEVENT(lParam) == FD_CONNECT) {//成功建立连接 if(WaitDlg) WaitDlg.EndDialog(IDCANCEL); //发送请求发送数据命令给发送端 SendLen=send(socket,Msg,sizeof(Msg),0); if(SendLen!=sizeof(Msg)) {//请求数据发送失败 MessageBox("请求错误" "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; } //接收数据 status =recv(socket, szRev,sizeof(szRev),0); if (status) { //得到组播IP地址和端口 sscanf(szRev,"%s%d",strDestAddr,&DestPort); sprintf(szBuff,"请加入组:%s,端口:%d",strDestAddr,DestPort); MessageBox(szBuff,"接收请求"); sprintf(szBuff,"接收播放:组:%s,端口:%d",strDestAddr,DestPort); ::SetWindowText(GetParent()->m_hWnd,szBuff); //关闭socket closesocket(socket); } if(status==0) { MessageBox("对方关闭连接"); closesocket(socket); return -1; } } } return 0; } LRESULT CRevPlayWnd::OnRead(WPARAM wParam,LPARAM lParam) { DWORD dwRet; REFTIME fTime; REFERENCE_TIME llClock; HRESULT hr; RECT rect; //接收组播数据,存放到缓冲区stWSABuf中 RevLen=ReceiveData(); //将缓冲区stWSABuf中的数据拷贝到存放接收的数据的数组pRevMem中, //以供DirectShow读取 CopyMemory((PVOID)pRevMem[rIndex],(PVOID)stWSABuf.buf,RevLen); rIndex=(rIndex+1)%100; //将接收到的数据保存到文件中 if(hmmioSave) mmioWrite(hmmioSave,stWSABuf.buf,RevLen); if(m_FirstRead) {//如果是第一次接收到数据,启动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; //设置视频窗口属性 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); //开始播放 m_pimc -> Run(); m_ppos->put_CurrentPosition(fTime + 0.4); m_Stop = TRUE; } m_FirstRead=FALSE; return 0; } LRESULT CRevPlayWnd::OnDelegatedCmdMsg(WPARAM, LPARAM lParam) { COnCmdMsg* pOnCmdMsg = (COnCmdMsg*)lParam; return CWnd::OnCmdMsg(pOnCmdMsg->m_nID, pOnCmdMsg->m_nCode, pOnCmdMsg->m_pExtra, pOnCmdMsg->m_pHandlerInfo); } LRESULT CRevPlayWnd::OnPrepareToClose(WPARAM, LPARAM) { StopReceive(); if( stWSABuf.buf) { delete stWSABuf.buf; stWSABuf.buf=NULL; } if(achInBuf) { delete achInBuf; achInBuf=NULL; } DestroyWindow(); return 0; } BOOL CRevPlayWnd::Create(LPCTSTR szTitle, LONG style, const RECT& rect, CWnd* parent) { // Register a custom WndClass and create a window. // This must be done because CBounceWnd has a custom cursor, and // no icon. LPCTSTR lpszRevPlayClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, LoadCursor(NULL, IDC_UPARROW), (HBRUSH)(COLOR_WINDOW+1), NULL); return CWnd::Create(lpszRevPlayClass, szTitle, style, rect, parent, IDC_REVPLAY_WND); } int CRevPlayWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here int status; int sock; CConnectDlg ConnectDlg; stWSABuf.buf = new char[BUFSIZE]; stWSABuf.len = BUFSIZE; achInBuf = new BYTE [BUFSIZE*2]; if(ConnectDlg.DoModal()==IDOK) { status=Connect(m_hWnd,AddressIp,LISTEN_PORT,sock); if(status<0) return -1; } return 0; } int CRevPlayWnd::Connect(HWND hwnd, const char *Addr, short Port, int &sock) { SOCKADDR_IN send_sin; int status; //创建一个socket sock = socket(AF_INET,SOCK_STREAM,0); if (sock == INVALID_SOCKET) { MessageBox("Socket Error"); closesocket(sock); return -1; } else { send_sin.sin_family=AF_INET; send_sin.sin_addr.s_addr=inet_addr(Addr); send_sin.sin_port=htons(Port); //设置响应的网络事件为FD_CONNECT,即建立连接 //发送WSA_CONNECT消息给窗口 status=WSAAsyncSelect(sock,hwnd,WSA_CONNECT,FD_CONNECT); if(status<0) {//连接建立失败,关闭socket MessageBox("Error on WSAAsyncSelect()"); WSAAsyncSelect(sock, hwnd, 0, 0); closesocket(sock); return -1; } } //连接发送端 connect(sock,(struct sockaddr FAR *)&send_sin, sizeof(send_sin)); int error=WSAGetLastError(); //有阻塞,弹出等待对话框 if (error==WSAEWOULDBLOCK) WaitDlg.DoModal(); return 0; } void CRevPlayWnd::InitMultiSock() { int RevBuf; int status; BOOL bFlag; CString ErrMsg; SOCKADDR_IN stLocalAddr; SOCKADDR_IN stDestAddr; SOCKET hNewSock; int RevLen=sizeof(RevBuf); //创建一个IP组播套接字 MultiSock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, (LPWSAPROTOCOL_INFO)NULL, 0, WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF); if (MultiSock == INVALID_SOCKET) { MessageBox("WSASocket() failed"); return; } //允许对同一地址bind多次 bFlag = TRUE; status = setsockopt( MultiSock, /* socket */ SOL_SOCKET, /* socket level */ SO_REUSEADDR, /* socket option */ (char *)&bFlag, /* option value */ sizeof (bFlag)); /* size of value */ if (status == SOCKET_ERROR) { ErrMsg.Format ("set SO_REUSEADDR failed, Err: %d",WSAGetLastError()); MessageBox(ErrMsg); return; } // 将套接字绑定到用户指定端口 stLocalAddr.sin_family = AF_INET; // stLocalAddr.sin_port = htons (DestPort); stLocalAddr.sin_port = htons (201); stLocalAddr.sin_addr.s_addr = INADDR_ANY; status = bind ( MultiSock, (struct sockaddr FAR *)&stLocalAddr, sizeof(struct sockaddr)); if (status == SOCKET_ERROR) { ErrMsg.Format ("Bind(socket: %d, port: %d) failed, Err: %d", MultiSock, DestPort, WSAGetLastError()); MessageBox(ErrMsg); } //设定接收缓冲区为64k RevBuf=65536; status = setsockopt( MultiSock, /* socket */ SOL_SOCKET, /* socket level */ SO_RCVBUF, /* socket option */ (char *)&RevBuf, /* option value */ sizeof(RevBuf)); /* size of value */ if (status == SOCKET_ERROR) { MessageBox("set SO_REVBUF error"); return; } //加入组播组 stDestAddr.sin_family = PF_INET; stDestAddr.sin_port = htons (201); stDestAddr.sin_addr.s_addr = inet_addr("234.5.6.7"); hNewSock = WSAJoinLeaf (MultiSock, /* socket */ (PSOCKADDR)&stDestAddr, /* multicast address */ sizeof (stDestAddr), /* length of addr struct */ NULL, /* caller data buffer */ NULL, /* callee data buffer */ NULL, /* socket QOS setting */ NULL, /* socket group QOS */ JL_RECEIVER_ONLY); /* do both: send *and* receive */ if (hNewSock == INVALID_SOCKET) { ErrMsg.Format ("WSAJoinLeaf() failed, Err: %d",WSAGetLastError()); MessageBox(ErrMsg); } } int CRevPlayWnd::ReceiveData() {//接收组播数据 CString msg; int status; DWORD cbRet; DWORD dFlag; int iLen; SOCKADDR_IN stSrcAddr; cbRet = 0; iLen = sizeof (stSrcAddr); dFlag = 0; //接收组播数据,存放到缓冲区stWSABuf中 status = WSARecvFrom (MultiSock, /* socket */ &stWSABuf, /* input buffer structure */ 1, /* buffer count */ &cbRet, /* number of bytes recv'd */ &dFlag, /* flags */ (struct sockaddr *)&stSrcAddr,/* source address */ &iLen, /* size of addr structure */ NULL, /* overlapped structure */ NULL); /* overlapped callback function */ if (status == SOCKET_ERROR) { //数据丢失,丢失的块数计数加1 m_LostBlock++; msg.Format ("WSARecvFrom() failed, Err:%d", WSAGetLastError()); MessageBox (msg); return -1; } return cbRet; } void CRevPlayWnd::OnSave() { // TODO: Add your command handler code here m_Save=!m_Save; DWORD dwFlags; CString SaveFileName; CString strSave; TCHAR Driver; CFileDialog dlg(TRUE,NULL,"temp.mpg",NULL,"mpeg文件(*.mpg)|*.mpg|AVI文件(*.avi)|*.avi"); dlg.m_ofn.lpstrTitle="保存到..."; if(dlg.DoModal()==IDOK) { SaveFileName=dlg.GetPathName(); Driver=SaveFileName.GetAt(0); CWnd* pParent = GetOwner(); strSave.Format("保存到:%s",SaveFileName); CMainFrame* pFrame=(CMainFrame*)pParent->GetOwner(); // pFrame->m_wndStatusBar.SetPaneText(1,strSave); } dwFlags = MMIO_CREATE | MMIO_WRITE; hmmioSave = mmioOpen(SaveFileName.GetBuffer(_MAX_PATH), (LPMMIOINFO)NULL, dwFlags); SaveFileName.ReleaseBuffer(); } void CRevPlayWnd::OnContextMenu(CWnd* pWnd, CPoint point) { // TODO: Add your message handler code here CMenu menu; menu.LoadMenu(IDR_POP_MENU); menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this); } void CRevPlayWnd::OnStopReceive() { // TODO: Add your command handler code here StopReceive(); m_Save=FALSE; m_FirstRead=TRUE; m_RenderOk=FALSE; m_Stop=FALSE; rIndex=0; } int CRevPlayWnd::InitGraph() {//构建Filter Graph HRESULT hr; hr = S_OK; //设置媒体类型,为MPEG1数据流 mt.majortype = MEDIATYPE_Stream; mt.subtype = MEDIASUBTYPE_MPEG1System; //创建Source Filter m_pStream = new CMemStream(achInBuf, 0x80000000, INFINITE); m_pStream->pWnd=this; m_rdr = new CMemReader(m_pStream, &mt, &hr); if(FAILED(hr) || m_rdr == NULL) { MessageBox("CMemReader Error"); return -1; } m_rdr -> AddRef(); //创建Filter Graph CHECK_ERROR(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IFilterGraph, (void**)&m_pifg),"CoCreateInstance Error") ; //将Source Filter加入到Filter Graph中 CHECK_ERROR(m_pifg -> AddFilter(m_rdr, NULL), "AddFilter Error"); //查询IGraphBuilder接口 CHECK_ERROR(m_pifg -> QueryInterface(IID_IGraphBuilder, (void **)&m_pigb),"QueryInterface(IGraphBuilder) Error"); m_pigb->AddRef (); //查询IMediaControl接口 CHECK_ERROR(m_pigb -> QueryInterface(IID_IMediaControl, (void **)&m_pimc),"QueryInterface(IMediaControl) Error"); m_pimc->AddRef (); //查询IVideoWindow接口 CHECK_ERROR(m_pigb -> QueryInterface(IID_IVideoWindow, (void **)&m_pivw),"QueryInterface(IVideoWindow) Error"); m_pivw->AddRef (); //查询IMediaPosition接口 CHECK_ERROR(m_pigb -> QueryInterface(IID_IMediaPosition, (void **)&m_ppos),"QueryInterface(IMediaPosition) Error"); m_ppos->AddRef (); return 0; } void CRevPlayWnd::OnRevPlay() { // TODO: Add your command handler code here int status; //建立组播socket,加入组播组 InitMultiSock(); //设置响应的网络事件为FD_READ,即读数据 //发送WSA_READ消息给窗口 status=WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,FD_READ); if(status<0) { MessageBox("Error on WSAAsyncSelect()"); closesocket(MultiSock); return; } //初始化存放接收数据的缓冲区 for (int i = 0; i< 100; i++ ) pRevMem[i] =new BYTE[BUFSIZE]; //32k m_Receive=TRUE; } BOOL CMemStream::PeekAndPump() { static MSG msg; while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { if (!AfxGetApp()->PumpMessage()) { ::PostQuitMessage(0); return FALSE; } } return TRUE; } void CRevPlayWnd::RenderFrom(PBYTE Buf, LPCTSTR File) { CFile f; CString MyPath; char path[MAX_PATH]; GetModuleFileName (AfxGetInstanceHandle(), path, _MAX_PATH); MyPath = path; int index = MyPath.ReverseFind ('\\'); MyPath = MyPath.Left (index+1); MyPath += File; int r = f.Open (MyPath, CFile::modeRead); if(r>0) r = f.Read (Buf, BUFSIZE*2); else return; f.Close (); } DWORD CRevPlayWnd::Parse(PBYTE Ptr, DWORD dwSize, LONGLONG *llTime) { DWORD RetV; DWORD LeftBytes = dwSize; while ((LONGLONG)LeftBytes >= 4 ) { if (!NextStartCode ((const BYTE **)&Ptr, &LeftBytes)) break; DWORD Code = DWORD_SWAP(*(UNALIGNED DWORD *)Ptr); if (VALID_PACKET(Code)) { PBYTE PcktPtr; DWORD Remain; DWORD PtsPos; RetV = ParseMPEG1Packet(Ptr, LeftBytes, &PacketData, &PtsPos); PcktPtr = Ptr+4; Remain = RetV; while ((LONG)Remain > 4) { if (!NextStartCode ((const BYTE **)&PcktPtr, &Remain)) break; DWORD PcktCode = DWORD_SWAP(*(UNALIGNED DWORD *)PcktPtr); switch (PcktCode) { case SEQUENCE_HEADER_CODE: ParseSequenceHeader(PcktPtr, 0, &SeqInfo); return (SeqInfo.dwBitRate); } PcktPtr += 4; Remain -=4 ; } } else { switch (Code) { case PACK_START_CODE: GetClock (Ptr+4, llTime); RetV = PACK_HEADER_LENGTH; break; case SYSTEM_HEADER_START_CODE: RetV = ParseSystemHeader(Ptr, LeftBytes); break; default: RetV = 4; break; } } Ptr += RetV; LeftBytes -= RetV; if (RetV <=0) break; } return 0; } void CRevPlayWnd::OnUpdateSave(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable (!m_Stop); pCmdUI->SetCheck (m_Save); } void CRevPlayWnd::OnUpdateStopReceive(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->Enable (m_Stop); } void CRevPlayWnd::StopReceive() { WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,0); closesocket(MultiSock); if (hmmioSave) { mmioClose(hmmioSave, NULL); hmmioSave = NULL; } if(m_pimc) { m_pimc -> Pause (); m_pimc ->StopWhenReady(); m_pimc -> Stop(); } if(m_pivw) { m_pivw -> put_Visible(OAFALSE); m_pivw -> put_Owner(NULL); } HELPER_RELEASE(m_pifg); HELPER_RELEASE(m_pigb); HELPER_RELEASE(m_pimc); HELPER_RELEASE(m_pivw); HELPER_RELEASE(m_ppos); if(m_pStream) { delete m_pStream; m_pStream = NULL; } if(m_rdr) { delete m_rdr; m_rdr = NULL; } for (int i = 0; i< 100; i++) { if (m_Receive) //表示按了Receive菜单 if(pRevMem[i]) delete pRevMem[i]; pRevMem[i] = NULL; } } void CRevPlayWnd::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // TODO: Add your message handler code here CRect rect; GetClientRect(&rect); if(m_pivw) m_pivw -> SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom); }