revplaymdichildwnd.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:24k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // RevPlayMDIChildWnd.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "RevPlayThread.h"
  5. #include "RevPlayMDIChildWnd.h"
  6. #include "ConnectDlg.h"
  7. #include "resource.h"
  8. #include "asyncio.h"
  9. #include "asyncrdr.h"
  10. #include "mainfrm.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. //#define IDC_REVPLAY_WND 1
  17. #define LISTEN_PORT 1500
  18. #define BUFSIZE 32768
  19. #define WSA_CONNECT WM_USER+200
  20. #define WSA_READ WM_USER+300  //读取视频数据
  21. //{ 36a5f771-fe4c-11ce-a8ed-00aa002feab5 }
  22. const CLSID  CLSID_Stream = {
  23. 0x36a5f771, 0xfe4c, 0x11ce, 0xa8, 0xed, 0x00, 0xaa, 0x00, 0x2f, 0xea, 0xb5
  24. };
  25. const AMOVIESETUP_MEDIATYPE sudPinTypes =
  26. {
  27.     &MEDIATYPE_NULL,            // Major type
  28.     &MEDIASUBTYPE_NULL          // Minor type
  29. };
  30. const AMOVIESETUP_PIN sudPins =
  31. {
  32.     L"Input",                   // Pin string name
  33.     FALSE,                      // Is it rendered
  34.     FALSE,                      // Is it an output
  35.     FALSE,                      // Allowed none
  36.     FALSE,                      // Likewise many
  37.     &CLSID_NULL,                // Connects to filter
  38.     L"Output",                  // Connects to pin
  39.     1,                          // Number of types
  40.     &sudPinTypes                // Pin information
  41. };
  42. const AMOVIESETUP_FILTER sudStream =
  43. {
  44.     &CLSID_Stream,                // Filter CLSID
  45.     L"Stream",                    // String name
  46.     MERIT_DO_NOT_USE,           // Filter merit
  47.     1,                          // Number pins
  48.     &sudPins                    // Pin details
  49. };
  50. //
  51. //  Object creation stuff
  52. //
  53. CFactoryTemplate g_Templates[]= {
  54.     L"Stream", &CLSID_Stream, NULL, NULL, &sudStream
  55. };
  56. int g_cTemplates = 1;
  57. class CMemStream : public CAsyncStream
  58. {
  59. public:
  60.     CRevPlayWnd* pWnd;  //接收播放窗口指针
  61. public:
  62. BOOL PeekAndPump();
  63.     CMemStream( LPBYTE pbData, LONGLONG llLength, DWORD dwKBPerSec = INFINITE) :
  64. m_pbData(pbData),
  65.         m_llLength(llLength),
  66.         m_llPosition(0),
  67.         m_dwKBPerSec(dwKBPerSec)
  68.     {
  69.         m_dwTimeStart = timeGetTime();
  70.     }
  71. //设置当前位置
  72. HRESULT SetPointer(LONGLONG llPos)
  73.     {
  74.         if (llPos < 0 || llPos > m_llLength) {
  75.             return S_FALSE;
  76.         } else {
  77.             m_llPosition = llPos;
  78.             return S_OK;
  79.         }
  80.     }
  81. //当MPEG1 Stream Splitter请求数据时,由Read函数提供
  82.     HRESULT Read(PBYTE pbBuffer,
  83. DWORD dwBytesToRead,
  84. BOOL bAlign,
  85. LPDWORD pdwBytesRead)
  86.     {
  87.         CAutoLock lck(&m_csLock);
  88.         DWORD dwReadLength, cbRet;
  89.         DWORD dwTime = timeGetTime();
  90. //如果要求读取的字节数大于剩余的字节数,则只直接读取剩余的字节
  91.         if (m_llPosition + dwBytesToRead > m_llLength) 
  92. {
  93.             dwReadLength = (DWORD)(m_llLength - m_llPosition);
  94.         } 
  95. else 
  96. {
  97.             dwReadLength = dwBytesToRead;
  98.         }
  99.         DWORD dwTimeToArrive =
  100.             ((DWORD)m_llPosition + dwReadLength) / m_dwKBPerSec;
  101.         if (dwTime - m_dwTimeStart < dwTimeToArrive) {
  102.             Sleep(dwTimeToArrive - dwTime + m_dwTimeStart);
  103.         }
  104. static int rwIndex =0;
  105. static int Block = pWnd->Block;
  106.         int temp=pWnd->rIndex;
  107. // if (pWnd->m_RenderOk) 
  108. // {
  109. /* while (rwIndex>temp) 
  110. PeekAndPump();*/
  111. //将存放接收的数据缓冲区数组中的数据拷贝到pbBuffer中,传给Splitter
  112. CopyMemory((PVOID)pbBuffer, (PVOID)(pWnd->pRevMem[rwIndex]), pWnd->RevLen);
  113. rwIndex = (rwIndex + 1) % 100;
  114. TRACE1("Read Addr = %dn",rwIndex);
  115. cbRet=pWnd->RevLen;
  116. // }
  117. /* else
  118. {
  119. if (Block == 0)
  120. {
  121. CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData),
  122. dwReadLength);
  123. Block ++;
  124. }
  125. else 
  126. {
  127. CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData + dwReadLength),
  128. dwReadLength);
  129. Block = 0;
  130. }
  131. cbRet = dwReadLength;
  132. }*/
  133. //当前位置向后移读出的字节数
  134.         m_llPosition += cbRet;
  135.         *pdwBytesRead = cbRet;
  136. if (cbRet != dwReadLength)
  137. m_llLength = m_llPosition;
  138. return S_OK;
  139. }
  140. //得到当前的数据总长度
  141.     LONGLONG Size(LONGLONG *pSizeAvailable)
  142.     {
  143.         LONGLONG llCurrentAvailable =
  144.             Int32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec);
  145.         *pSizeAvailable = min(m_llLength, llCurrentAvailable);
  146.         return m_llLength;
  147.     }
  148.     DWORD Alignment()
  149.     {
  150. //按1字节对齐
  151.         return 1;
  152.     }
  153.     void Lock()
  154.     {
  155.         m_csLock.Lock();
  156.     }
  157.     void Unlock()
  158.     {
  159.         m_csLock.Unlock();
  160.     }
  161. private:
  162.     CCritSec       m_csLock;     //数据操作的同步对象
  163.     const PBYTE    m_pbData;     //读写的内存数据指针
  164.     LONGLONG       m_llLength;   //数据总长度 
  165.     LONGLONG       m_llPosition; //实际读写的内存数据位置指针
  166.     DWORD          m_dwKBPerSec; //播放的的速率
  167.     DWORD          m_dwTimeStart;//开始时间
  168. };
  169. class CMemReader : public CAsyncReader
  170. {
  171. public:
  172.     STDMETHODIMP Register()
  173.     {
  174.         return S_OK;
  175.     }
  176.     STDMETHODIMP Unregister()
  177.     {
  178.         return S_OK;
  179.     }
  180.     CMemReader(CMemStream *pStream, CMediaType *pmt, HRESULT *phr) :
  181. CAsyncReader(NAME("Mem Reader"), NULL, pStream, phr)
  182.     {
  183.         m_mt = *pmt;
  184.     }
  185. };
  186. /////////////////////////////////////////////////////////////////////////////
  187. // CRevPlayMDIChildWnd
  188. CMenu CRevPlayMDIChildWnd::menu;   
  189. IMPLEMENT_DYNCREATE(CRevPlayMDIChildWnd, CMDIChildWnd)
  190. CRevPlayMDIChildWnd::CRevPlayMDIChildWnd()
  191. {
  192. }
  193. CRevPlayMDIChildWnd::~CRevPlayMDIChildWnd()
  194. {
  195. }
  196. BEGIN_MESSAGE_MAP(CRevPlayMDIChildWnd, CMDIChildWnd)
  197. //{{AFX_MSG_MAP(CRevPlayMDIChildWnd)
  198. ON_WM_SIZE()
  199. //}}AFX_MSG_MAP
  200. ON_MESSAGE(WM_USER_PREPARE_TO_CLOSE, OnPrepareToClose)
  201.    
  202. END_MESSAGE_MAP()
  203. /////////////////////////////////////////////////////////////////////////////
  204. // CRevPlayMDIChildWnd message handlers
  205. BOOL CRevPlayMDIChildWnd::Create(LPCTSTR szTitle, const RECT &rect, CMDIFrameWnd *parent)
  206. {
  207.     if (menu.m_hMenu == NULL)
  208. menu.LoadMenu(IDR_REVPLAY);
  209. m_hMenuShared = menu.m_hMenu;
  210. //创建子窗口
  211. if (!CMDIChildWnd::Create(NULL, szTitle, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, rect, parent))
  212. return FALSE;
  213. //生成UI线程对象
  214. CRevPlayThread* pRevPlayThread = new CRevPlayThread(m_hWnd);
  215. //创建线程
  216. pRevPlayThread->CreateThread();
  217. return TRUE;
  218. }
  219. BOOL CRevPlayMDIChildWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
  220. {
  221. // TODO: Add your specialized code here and/or call the base class
  222. CWnd* pRevPlayWnd = (CRevPlayWnd*)GetDlgItem(IDC_REVPLAY_WND);
  223. if (pRevPlayWnd == NULL)
  224. return FALSE; 
  225. COnCmdMsg oncmdmsg;
  226. oncmdmsg.m_nID =    nID;
  227. oncmdmsg.m_nCode = nCode;
  228. oncmdmsg.m_pExtra = pExtra;
  229. oncmdmsg.m_pHandlerInfo = pHandlerInfo;
  230. return pRevPlayWnd->SendMessage(WM_USER_ONCMDMSG,
  231. 0, (LPARAM)&oncmdmsg);
  232. }
  233. void CRevPlayMDIChildWnd::OnSize(UINT nType, int cx, int cy) 
  234. {
  235. CMDIChildWnd::OnSize(nType, cx, cy);
  236. // TODO: Add your message handler code here
  237. CWnd* pRevPlayWnd = GetDlgItem(IDC_REVPLAY_WND);
  238. if (pRevPlayWnd == NULL)
  239. return; // child CBounceWnd not created yet
  240. CRect rect;
  241. GetClientRect(&rect);
  242. pRevPlayWnd->SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
  243. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  244. }
  245. BOOL CRevPlayMDIChildWnd::DestroyWindow() 
  246. {
  247. // TODO: Add your specialized code here and/or call the base class
  248. OnPrepareToClose();
  249. return CMDIChildWnd::DestroyWindow();
  250. }
  251. LRESULT CRevPlayMDIChildWnd::OnPrepareToClose(WPARAM wParam, LPARAM lParam)
  252. {
  253.   CWnd* pRevPlayWnd = (CRevPlayWnd*)GetDlgItem(IDC_REVPLAY_WND);
  254. pRevPlayWnd->SendMessage(WM_USER_PREPARE_TO_CLOSE);
  255. WaitForSingleObject(CRevPlayThread::m_hEventRevPlayThreadKilled, INFINITE);
  256. return 0;
  257. }
  258. /////////////////////////////////////////////////////////////////////////////
  259. // CRevPlayWnd
  260. CRevPlayWnd::CRevPlayWnd()
  261. {
  262. m_LostBlock=0;
  263. m_Receive=FALSE;
  264. m_Save=FALSE;
  265. m_FirstRead=TRUE;
  266. m_RenderOk=FALSE;
  267. m_Stop=FALSE;
  268. rIndex=0;   //pRevMem数组的标记
  269. g_rwIndex=0;
  270. m_pStream=NULL;
  271. m_rdr=NULL;
  272. m_pifg = NULL;
  273. m_pigb = NULL;
  274. m_pimc = NULL;
  275. m_pivw = NULL;
  276. m_ppos = NULL;
  277. hmmioSave = NULL;
  278. }
  279. CRevPlayWnd::~CRevPlayWnd()
  280. {
  281.  
  282. }
  283. BEGIN_MESSAGE_MAP(CRevPlayWnd, CWnd)
  284. //{{AFX_MSG_MAP(CRevPlayWnd)
  285. ON_WM_CREATE()
  286. ON_COMMAND(IDR_SAVE, OnSave)
  287. ON_WM_CONTEXTMENU()
  288. ON_COMMAND(ID_STOP_RECEIVE, OnStopReceive)
  289. ON_COMMAND(IDR_REV_PLAY, OnRevPlay)
  290. ON_UPDATE_COMMAND_UI(IDR_SAVE, OnUpdateSave)
  291. ON_UPDATE_COMMAND_UI(ID_STOP_RECEIVE, OnUpdateStopReceive)
  292. ON_WM_SIZE()
  293. //}}AFX_MSG_MAP
  294. ON_MESSAGE(WM_USER_ONCMDMSG, OnDelegatedCmdMsg)
  295. ON_MESSAGE(WM_USER_PREPARE_TO_CLOSE, OnPrepareToClose)
  296. ON_MESSAGE(WSA_CONNECT,OnConnect)
  297. ON_MESSAGE(WSA_READ,OnRead)
  298. END_MESSAGE_MAP()
  299. /////////////////////////////////////////////////////////////////////////////
  300. // CRevPlayWnd message handlers
  301. LRESULT CRevPlayWnd::OnConnect(WPARAM wParam,LPARAM lParam) 
  302. {
  303. int status;
  304. int SendLen;
  305. int socket;
  306. char szRev[80];
  307. char szBuff[80];
  308. char Msg[]="请发送数据";
  309. u_long block=0;
  310. socket=(SOCKET)wParam; 
  311. if (WSAGETSELECTERROR(lParam))
  312. {//建立连接失败
  313. MessageBox("不能连接服务器", "连接失败", MB_OK);
  314. if(WaitDlg)
  315. WaitDlg.EndDialog(IDCANCEL);
  316. //关闭socket
  317. closesocket(socket); 
  318. return -1;
  319. }
  320. if (WSAGETSELECTEVENT(lParam) == FD_CONNECT)
  321. {//成功建立连接
  322. if(WaitDlg)
  323. WaitDlg.EndDialog(IDCANCEL);
  324. //发送请求发送数据命令给发送端
  325. SendLen=send(socket,Msg,sizeof(Msg),0);
  326. if(SendLen!=sizeof(Msg))
  327. {//请求数据发送失败
  328. MessageBox("请求错误" "Send");
  329. closesocket(socket); 
  330. return -1;
  331. }
  332. if(SendLen==sizeof(Msg))
  333. {
  334. WSAAsyncSelect(socket,m_hWnd, 0, 0 ); 
  335. status=ioctlsocket(socket,FIONBIO,&block);
  336. if(status==SOCKET_ERROR)
  337. {
  338. sprintf(szBuff,"Err: %d",WSAGetLastError());
  339. MessageBox(szBuff);
  340. return -1;
  341. }
  342. //接收数据
  343. status =recv(socket, szRev,sizeof(szRev),0);
  344. if (status) 
  345. {
  346. //得到组播IP地址和端口
  347. sscanf(szRev,"%s%d",strDestAddr,&DestPort);    
  348. sprintf(szBuff,"请加入组:%s,端口:%d",strDestAddr,DestPort);
  349. MessageBox(szBuff,"接收请求");            
  350. sprintf(szBuff,"接收播放:组:%s,端口:%d",strDestAddr,DestPort);
  351. ::SetWindowText(GetParent()->m_hWnd,szBuff);
  352. //关闭socket
  353. closesocket(socket);
  354. }
  355. if(status==0)
  356. {
  357. MessageBox("对方关闭连接");
  358. closesocket(socket);
  359. return -1;
  360. }  
  361. }
  362. }
  363. return 0;
  364. }
  365. LRESULT CRevPlayWnd::OnRead(WPARAM wParam,LPARAM lParam) 
  366. {
  367. DWORD dwRet;
  368. REFTIME fTime;
  369. REFERENCE_TIME llClock; 
  370. HRESULT hr;
  371. RECT rect;
  372. //接收组播数据,存放到缓冲区stWSABuf中
  373. RevLen=ReceiveData();
  374. //将缓冲区stWSABuf中的数据拷贝到存放接收的数据的数组pRevMem中,
  375. //以供DirectShow读取
  376. CopyMemory((PVOID)pRevMem[rIndex],(PVOID)stWSABuf.buf,RevLen);
  377. rIndex=(rIndex+1)%100;
  378. //将接收到的数据保存到文件中
  379. if(hmmioSave)
  380. mmioWrite(hmmioSave,stWSABuf.buf,RevLen);
  381. if(m_FirstRead)   
  382. {//如果是第一次接收到数据,启动DirectShow
  383. fTime = 0.0;
  384. dwRet = Parse ((PBYTE)stWSABuf.buf, stWSABuf.len, &llClock);
  385. fTime = llClock / 90000.0;
  386. if(dwRet == 0)
  387. return -1;
  388. if(InitGraph()==-1)
  389. return -1;
  390. if (abs (dwRet - 2048000) <= 16000) {
  391. RenderFrom ((PBYTE)achInBuf, "2mpal.dat");
  392. if (abs (dwRet - 1152000) <= 16000) {
  393. RenderFrom ((PBYTE)achInBuf, "1mpal.dat");
  394. if (abs (dwRet - 512000)  <= 16000) {
  395. RenderFrom ((PBYTE)achInBuf, "512pal.dat");
  396. }
  397. if (abs (dwRet - 256000)  <= 16000) {
  398. RenderFrom ((PBYTE)achInBuf, "256pal.dat");
  399. }
  400. Block = 0;
  401. //使用智能连接,将Source Filter的输出Pin连出去
  402. if (FAILED(hr = m_pigb -> Render(m_rdr -> GetPin(0)))) 
  403. {
  404. if (hr != VFW_S_AUDIO_NOT_RENDERED && hr != VFW_E_NO_AUDIO_HARDWARE )
  405. {
  406. MessageBox ("Render Error");
  407. WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,0); 
  408. HELPER_RELEASE(m_pifg);
  409. HELPER_RELEASE(m_pigb);
  410. HELPER_RELEASE(m_pimc);
  411. HELPER_RELEASE(m_pivw);
  412. HELPER_RELEASE(m_ppos);
  413. return -1;
  414. }
  415. }
  416. m_RenderOk = true;
  417. //设置视频窗口属性
  418. m_pivw -> put_Owner((OAHWND)m_hWnd);
  419. m_pivw -> put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  420. GetClientRect(&rect);
  421. m_pivw -> SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom);
  422. //开始播放
  423. m_pimc -> Run();
  424. m_ppos->put_CurrentPosition(fTime + 0.4);
  425. m_Stop = TRUE;
  426. }
  427. m_FirstRead=FALSE;
  428. return 0;
  429. }
  430. LRESULT CRevPlayWnd::OnDelegatedCmdMsg(WPARAM, LPARAM lParam)
  431. {
  432. COnCmdMsg* pOnCmdMsg = (COnCmdMsg*)lParam;
  433. return CWnd::OnCmdMsg(pOnCmdMsg->m_nID, pOnCmdMsg->m_nCode, pOnCmdMsg->m_pExtra,
  434. pOnCmdMsg->m_pHandlerInfo);
  435. }
  436. LRESULT CRevPlayWnd::OnPrepareToClose(WPARAM, LPARAM)
  437. {
  438.     StopReceive();
  439. if( stWSABuf.buf)
  440. {
  441. delete  stWSABuf.buf;
  442. stWSABuf.buf=NULL;
  443. }
  444. if(achInBuf)
  445. {
  446. delete achInBuf;
  447. achInBuf=NULL;
  448. }
  449. DestroyWindow();
  450. return 0;
  451. }
  452. BOOL CRevPlayWnd::Create(LPCTSTR szTitle, LONG style, const RECT& rect, CWnd* parent)
  453. {
  454. // Register a custom WndClass and create a window.
  455. // This must be done because CBounceWnd has a custom cursor, and
  456. //  no icon.
  457. LPCTSTR lpszRevPlayClass =
  458. AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
  459. LoadCursor(NULL, IDC_UPARROW),
  460. (HBRUSH)(COLOR_WINDOW+1),
  461. NULL);
  462. return CWnd::Create(lpszRevPlayClass, szTitle, style, rect, parent,
  463. IDC_REVPLAY_WND);
  464. }
  465. int CRevPlayWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  466. {
  467. if (CWnd::OnCreate(lpCreateStruct) == -1)
  468. return -1;
  469. // TODO: Add your specialized creation code here
  470. int status;
  471. int sock;
  472. CConnectDlg ConnectDlg;
  473. stWSABuf.buf = new char[BUFSIZE];
  474. stWSABuf.len = BUFSIZE;
  475. achInBuf = new BYTE [BUFSIZE*2];
  476. if(ConnectDlg.DoModal()==IDOK)
  477. {
  478. status=Connect(m_hWnd,AddressIp,LISTEN_PORT,sock);
  479. if(status<0)
  480. return -1;
  481. }
  482. return 0;
  483. }
  484. int CRevPlayWnd::Connect(HWND hwnd, const char *Addr, short Port, int &sock)
  485. {
  486. SOCKADDR_IN send_sin;
  487. int status;
  488. //创建一个socket
  489. sock = socket(AF_INET,SOCK_STREAM,0);
  490. if (sock == INVALID_SOCKET)
  491. {
  492.         MessageBox("Socket Error");
  493.         closesocket(sock);   
  494. return -1;
  495. else
  496. {
  497. send_sin.sin_family=AF_INET;
  498. send_sin.sin_addr.s_addr=inet_addr(Addr);
  499. send_sin.sin_port=htons(Port);
  500. //设置响应的网络事件为FD_CONNECT,即建立连接
  501. //发送WSA_CONNECT消息给窗口
  502. status=WSAAsyncSelect(sock,hwnd,WSA_CONNECT,FD_CONNECT); 
  503. if(status<0)
  504. {//连接建立失败,关闭socket
  505. MessageBox("Error on WSAAsyncSelect()");
  506. WSAAsyncSelect(sock, hwnd, 0, 0);
  507. closesocket(sock);
  508. return -1;
  509. }
  510. //连接发送端
  511. connect(sock,(struct sockaddr FAR *)&send_sin, sizeof(send_sin));
  512. int error=WSAGetLastError();
  513. //有阻塞,弹出等待对话框
  514. if (error==WSAEWOULDBLOCK)
  515. WaitDlg.DoModal(); 
  516. return 0;
  517. }
  518. void CRevPlayWnd::InitMultiSock()
  519. {
  520.     int RevBuf;
  521.     int status;
  522.     BOOL  bFlag;
  523. CString ErrMsg;
  524. SOCKADDR_IN stLocalAddr;
  525. SOCKADDR_IN stDestAddr;
  526. SOCKET hNewSock;
  527.     int RevLen=sizeof(RevBuf);
  528. //创建一个IP组播套接字
  529.     MultiSock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
  530.   (LPWSAPROTOCOL_INFO)NULL, 0, 
  531.   WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF);
  532. if (MultiSock == INVALID_SOCKET) 
  533. {
  534. MessageBox("WSASocket() failed");
  535. return;
  536.     } 
  537.     //允许对同一地址bind多次
  538. bFlag = TRUE;
  539. status = setsockopt(
  540. MultiSock, /* socket */
  541.      SOL_SOCKET, /* socket level */
  542. SO_REUSEADDR, /* socket option */
  543.     (char *)&bFlag, /* option value */
  544.   sizeof (bFlag)); /* size of value */
  545. if (status == SOCKET_ERROR) 
  546. {
  547.   ErrMsg.Format ("set SO_REUSEADDR failed, Err: %d",WSAGetLastError());
  548.       MessageBox(ErrMsg);
  549.   return;
  550. }
  551. // 将套接字绑定到用户指定端口
  552. stLocalAddr.sin_family = AF_INET;
  553.   //  stLocalAddr.sin_port = htons (DestPort);
  554.     stLocalAddr.sin_port = htons (201);
  555. stLocalAddr.sin_addr.s_addr = INADDR_ANY;
  556.     status = bind (
  557.         MultiSock, 
  558.         (struct sockaddr FAR *)&stLocalAddr, 
  559.         sizeof(struct sockaddr));
  560.     if (status == SOCKET_ERROR) 
  561. {
  562. ErrMsg.Format ("Bind(socket: %d, port: %d) failed, Err: %d",
  563. MultiSock, DestPort, WSAGetLastError());
  564. MessageBox(ErrMsg);
  565.     }
  566. //设定接收缓冲区为64k
  567.   RevBuf=65536;
  568. status = setsockopt(
  569. MultiSock, /* socket */
  570.      SOL_SOCKET, /* socket level */
  571.     SO_RCVBUF, /* socket option */
  572.     (char *)&RevBuf, /* option value */
  573.     sizeof(RevBuf)); /* size of value */
  574. if (status == SOCKET_ERROR) 
  575. {
  576. MessageBox("set SO_REVBUF error");
  577. return;
  578. }
  579.     
  580. //加入组播组
  581. stDestAddr.sin_family = PF_INET;
  582. stDestAddr.sin_port = htons (201);
  583.     stDestAddr.sin_addr.s_addr = inet_addr("234.5.6.7");
  584.     hNewSock = WSAJoinLeaf (MultiSock, /* socket */
  585.         (PSOCKADDR)&stDestAddr, /* multicast address */
  586.         sizeof (stDestAddr),    /* length of addr struct */
  587.         NULL,                   /* caller data buffer */
  588.         NULL,                   /* callee data buffer */
  589.         NULL,                   /* socket QOS setting */
  590.         NULL,                   /* socket group QOS */
  591.         JL_RECEIVER_ONLY);               /* do both: send *and* receive */
  592.     if (hNewSock == INVALID_SOCKET) 
  593. {
  594.   ErrMsg.Format ("WSAJoinLeaf() failed, Err: %d",WSAGetLastError());
  595.       MessageBox(ErrMsg);
  596. }
  597. int CRevPlayWnd::ReceiveData()
  598. {//接收组播数据
  599.     CString msg;
  600.     int status;
  601.     DWORD cbRet;
  602.     DWORD dFlag;
  603. int iLen;
  604. SOCKADDR_IN stSrcAddr;
  605. cbRet = 0;
  606. iLen = sizeof (stSrcAddr);
  607. dFlag = 0;
  608. //接收组播数据,存放到缓冲区stWSABuf中
  609. status = WSARecvFrom (MultiSock, /* socket */
  610. &stWSABuf,               /* input buffer structure */
  611. 1,                       /* buffer count */
  612. &cbRet,                  /* number of bytes recv'd */
  613. &dFlag,                 /* flags */
  614. (struct sockaddr *)&stSrcAddr,/* source address */
  615. &iLen,                   /* size of addr structure */
  616. NULL,                    /* overlapped structure */
  617. NULL);                   /* overlapped callback function */
  618. if (status == SOCKET_ERROR) 
  619. {
  620. //数据丢失,丢失的块数计数加1
  621. m_LostBlock++;
  622. msg.Format ("WSARecvFrom() failed, Err:%d", WSAGetLastError());
  623. MessageBox (msg);
  624. return -1;
  625. return cbRet;
  626. }
  627. void CRevPlayWnd::OnSave() 
  628. {
  629. // TODO: Add your command handler code here
  630. m_Save=!m_Save;
  631. DWORD dwFlags;
  632. CString SaveFileName;
  633. CString strSave;
  634. TCHAR Driver;
  635.     CFileDialog dlg(TRUE,NULL,"temp.mpg",NULL,"mpeg文件(*.mpg)|*.mpg|AVI文件(*.avi)|*.avi");
  636.     dlg.m_ofn.lpstrTitle="保存到...";
  637.     if(dlg.DoModal()==IDOK)
  638. {
  639. SaveFileName=dlg.GetPathName();
  640.         Driver=SaveFileName.GetAt(0);
  641.         CWnd* pParent = GetOwner();
  642. strSave.Format("保存到:%s",SaveFileName);
  643. CMainFrame* pFrame=(CMainFrame*)pParent->GetOwner();
  644. //   pFrame->m_wndStatusBar.SetPaneText(1,strSave);
  645. }
  646.     dwFlags = MMIO_CREATE | MMIO_WRITE;
  647.     hmmioSave = mmioOpen(SaveFileName.GetBuffer(_MAX_PATH), (LPMMIOINFO)NULL, dwFlags);
  648.     SaveFileName.ReleaseBuffer();
  649. }
  650. void CRevPlayWnd::OnContextMenu(CWnd* pWnd, CPoint point) 
  651. {
  652. // TODO: Add your message handler code here
  653. CMenu menu;
  654. menu.LoadMenu(IDR_POP_MENU);
  655. menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
  656. }
  657. void CRevPlayWnd::OnStopReceive() 
  658. {
  659. // TODO: Add your command handler code here
  660. StopReceive();
  661. m_Save=FALSE;
  662.     m_FirstRead=TRUE;
  663.     m_RenderOk=FALSE;
  664.     m_Stop=FALSE;
  665.     rIndex=0;
  666. }
  667. int  CRevPlayWnd::InitGraph()
  668. {//构建Filter Graph
  669.     HRESULT hr;
  670. hr = S_OK;
  671. //设置媒体类型,为MPEG1数据流
  672.     mt.majortype = MEDIATYPE_Stream;
  673.     mt.subtype = MEDIASUBTYPE_MPEG1System;
  674. //创建Source Filter
  675. m_pStream = new CMemStream(achInBuf, 0x80000000, INFINITE);
  676.     m_pStream->pWnd=this;
  677.     m_rdr = new CMemReader(m_pStream, &mt, &hr);
  678.     if(FAILED(hr) || m_rdr == NULL)
  679. {
  680. MessageBox("CMemReader Error");
  681. return -1;
  682. }
  683.     
  684. m_rdr -> AddRef();
  685. //创建Filter Graph
  686. CHECK_ERROR(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IFilterGraph, (void**)&m_pifg),"CoCreateInstance Error") ;
  687. //将Source Filter加入到Filter Graph中    
  688. CHECK_ERROR(m_pifg -> AddFilter(m_rdr, NULL), "AddFilter Error");
  689. //查询IGraphBuilder接口
  690. CHECK_ERROR(m_pifg -> QueryInterface(IID_IGraphBuilder, (void **)&m_pigb),"QueryInterface(IGraphBuilder) Error");
  691.     m_pigb->AddRef ();
  692. //查询IMediaControl接口
  693. CHECK_ERROR(m_pigb -> QueryInterface(IID_IMediaControl, (void **)&m_pimc),"QueryInterface(IMediaControl) Error");
  694.     m_pimc->AddRef ();
  695. //查询IVideoWindow接口
  696.     CHECK_ERROR(m_pigb -> QueryInterface(IID_IVideoWindow, (void **)&m_pivw),"QueryInterface(IVideoWindow) Error");
  697.     m_pivw->AddRef ();
  698.     //查询IMediaPosition接口
  699.     CHECK_ERROR(m_pigb -> QueryInterface(IID_IMediaPosition, (void **)&m_ppos),"QueryInterface(IMediaPosition) Error");
  700.     m_ppos->AddRef ();
  701. return 0;
  702. }
  703. void CRevPlayWnd::OnRevPlay() 
  704. {
  705. // TODO: Add your command handler code here
  706. int status;
  707. //建立组播socket,加入组播组
  708.    InitMultiSock();
  709. //设置响应的网络事件为FD_READ,即读数据
  710. //发送WSA_READ消息给窗口
  711. status=WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,FD_READ);
  712. if(status<0)
  713. {
  714.        MessageBox("Error on WSAAsyncSelect()");
  715.        closesocket(MultiSock);
  716.    return;
  717. }
  718. //初始化存放接收数据的缓冲区
  719. for (int i = 0; i< 100; i++ )
  720. pRevMem[i] =new BYTE[BUFSIZE]; //32k
  721. m_Receive=TRUE;
  722. }
  723. BOOL CMemStream::PeekAndPump()
  724. {
  725. static MSG msg;
  726. while (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
  727. if (!AfxGetApp()->PumpMessage()) {
  728. ::PostQuitMessage(0);
  729. return FALSE;
  730. }
  731. }
  732. return TRUE;
  733. }
  734. void CRevPlayWnd::RenderFrom(PBYTE Buf, LPCTSTR File)
  735. {
  736.     CFile f;
  737. CString MyPath;
  738. char path[MAX_PATH];
  739. GetModuleFileName (AfxGetInstanceHandle(), path, _MAX_PATH);
  740. MyPath = path;
  741. int index = MyPath.ReverseFind ('\');
  742. MyPath = MyPath.Left (index+1);
  743. MyPath += File;
  744. int r = f.Open (MyPath, CFile::modeRead);
  745.     if(r>0)    
  746. r = f.Read (Buf, BUFSIZE*2);
  747.     else
  748. return;
  749. f.Close ();
  750. }
  751. DWORD CRevPlayWnd::Parse(PBYTE Ptr, DWORD dwSize, LONGLONG *llTime)
  752. {
  753. DWORD RetV;
  754. DWORD LeftBytes = dwSize;
  755. while ((LONGLONG)LeftBytes >= 4 ) {
  756. if (!NextStartCode ((const BYTE **)&Ptr, &LeftBytes))
  757. break;
  758. DWORD Code = DWORD_SWAP(*(UNALIGNED DWORD *)Ptr);
  759. if (VALID_PACKET(Code)) {
  760. PBYTE PcktPtr;
  761. DWORD  Remain;
  762. DWORD PtsPos;
  763. RetV = ParseMPEG1Packet(Ptr, LeftBytes, &PacketData, &PtsPos);
  764. PcktPtr = Ptr+4;
  765. Remain = RetV;
  766. while ((LONG)Remain > 4) {
  767. if (!NextStartCode ((const BYTE **)&PcktPtr, &Remain))
  768. break;
  769. DWORD PcktCode = DWORD_SWAP(*(UNALIGNED DWORD *)PcktPtr);
  770. switch (PcktCode) {
  771. case SEQUENCE_HEADER_CODE:
  772. ParseSequenceHeader(PcktPtr, 0, &SeqInfo);
  773. return (SeqInfo.dwBitRate);
  774. }
  775. PcktPtr += 4;
  776. Remain -=4 ;
  777. }
  778. } else {
  779. switch (Code) {
  780. case PACK_START_CODE:
  781. GetClock (Ptr+4, llTime);
  782. RetV = PACK_HEADER_LENGTH;
  783. break;
  784. case SYSTEM_HEADER_START_CODE:
  785. RetV = ParseSystemHeader(Ptr, LeftBytes);
  786. break;
  787. default:
  788. RetV = 4;
  789. break;
  790. }
  791. }
  792. Ptr += RetV;
  793. LeftBytes -= RetV;
  794. if (RetV <=0)
  795. break;
  796. return 0;
  797. }
  798. void CRevPlayWnd::OnUpdateSave(CCmdUI* pCmdUI) 
  799. {
  800. // TODO: Add your command update UI handler code here
  801. pCmdUI->Enable (!m_Stop);
  802. pCmdUI->SetCheck (m_Save);
  803. }
  804. void CRevPlayWnd::OnUpdateStopReceive(CCmdUI* pCmdUI) 
  805. {
  806. // TODO: Add your command update UI handler code here
  807. pCmdUI->Enable (m_Stop);
  808. }
  809. void CRevPlayWnd::StopReceive()
  810. {
  811.     WSAAsyncSelect(MultiSock,m_hWnd,WSA_READ,0);
  812. closesocket(MultiSock);
  813. if (hmmioSave)
  814. {
  815. mmioClose(hmmioSave, NULL);
  816. hmmioSave = NULL;
  817. }
  818. if(m_pimc)
  819. {
  820. m_pimc -> Pause ();
  821. m_pimc ->StopWhenReady();
  822. m_pimc -> Stop();
  823. }
  824. if(m_pivw)
  825. {
  826. m_pivw -> put_Visible(OAFALSE);
  827. m_pivw -> put_Owner(NULL);
  828. }
  829. HELPER_RELEASE(m_pifg);
  830. HELPER_RELEASE(m_pigb);
  831. HELPER_RELEASE(m_pimc);
  832. HELPER_RELEASE(m_pivw);
  833. HELPER_RELEASE(m_ppos);
  834. if(m_pStream)
  835. {
  836. delete m_pStream;
  837. m_pStream = NULL;
  838. }
  839. if(m_rdr)
  840. {
  841. delete m_rdr;
  842. m_rdr = NULL;
  843. }
  844. for (int i = 0; i< 100; i++) 
  845. {
  846. if (m_Receive) //表示按了Receive菜单
  847. if(pRevMem[i])
  848. delete pRevMem[i];
  849. pRevMem[i] = NULL;
  850. }
  851. }
  852. void CRevPlayWnd::OnSize(UINT nType, int cx, int cy) 
  853. {
  854. CWnd::OnSize(nType, cx, cy);
  855. // TODO: Add your message handler code here
  856. CRect rect;
  857. GetClientRect(&rect);
  858. if(m_pivw)
  859. m_pivw -> SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom);
  860. }