📄 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -