?? aviomgr.cpp
字號:
BOOL bRet=FALSE;
if(m_iStatus!=STA_FREE)
goto RET;
SetDst(ip,port);
PACK_CMD pc;
m_session=rand()&0xff;
pc.flag=FLAG_CMD;
pc.cmd=CMD_CALL;
pc.type=0;
pc.data_size_extra=0;
pc.ext=VER_AVIO&0xff;//AVIO 的版本
if(!SendCmd(&pc,sizeof(pc),m_dst,TRUE))
goto RET;
m_iStatus=STA_BUSY;
bRet=TRUE;
m_uDataSend=0;
m_uDataRcv=0;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
//結束通話
BOOL CAVIOMgr::EndTalk()
{
BOOL bRet=FALSE;
if(m_iStatus==STA_FREE)
goto RET;
if(m_iStatus==STA_BUSY)
{
m_iStatus=STA_FREE;
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.cmd=CMD_END;
pc.data_size_extra=0;
pc.type=0;
SendCmd(&pc,sizeof(pc),m_dst,FALSE);
ZeroMemory(&m_dst,sizeof(m_dst));
DestroyVideoCodec();
DestroyAudioCodec();
DestroyAudioPlay();
DestroyAudioRec();
DestroyCap();
}
bRet=TRUE;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
//接受請求
BOOL CAVIOMgr::Accept()
{
BOOL bRet=FALSE;
if(m_iStatus!=STA_BUSY)
goto RET;
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.cmd=CMD_ACCEPT;
pc.data_size_extra=0;
pc.type=0;
SendCmd(&pc,sizeof(pc),m_dst,TRUE);
ZeroMemory(&m_ds,sizeof(m_ds));
m_ds.bVideoOut=true;//always ok
if(InitVideoCodec())//why this must ahead InitAudioCodec??i don't know why
m_ds.bVideoCodec=true;
if(InitAudioCodec())
m_ds.bAudioCodec=true;
if(InitAudioPlay())
m_ds.bAudioOut=true;
if(InitAudioRec())
m_ds.bAudioIn=true;
if(m_ds.bVideoCodec&&InitCap())
m_ds.bVideoIn=true;
if(!m_ds.bAudioCodec&&!m_ds.bVideoCodec)
{
DestroyCap();
DestroyAudioRec();
DestroyAudioPlay();
DestroyAudioCodec();
DestroyVideoCodec();
m_iStatus=STA_FREE;
}
bRet=TRUE;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
//拒絕請求
BOOL CAVIOMgr::Refuse()
{
BOOL bRet=FALSE;
if(m_iStatus!=STA_BUSY)
goto RET;
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.cmd=CMD_REFUSE;
pc.ext=R_USER;
pc.data_size_extra=0;
pc.type=0;
m_iStatus=STA_FREE;
SendCmd(&pc,sizeof(pc),m_dst,TRUE);
bRet=TRUE;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
//解釋發送來的命令
void CAVIOMgr::OnCommand(PACK_CMD *ppc, int len)
{
switch(ppc->cmd)
{
case CMD_CALL:
{
if(ppc->type==0)
{
if(m_bEnable)
{
//如果是空閑的,就保存地址,設置狀態為工作狀態
//并向主窗口發送呼叫通知
if(m_iStatus==STA_FREE)
{
m_dst=m_sockaddr;
m_iStatus=STA_BUSY;
m_session=ppc->session;
PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_CALL,VER_AVIO),(LPARAM)this);
//返回請求確認
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.data_size_extra=0;
pc.cmd=CMD_CALL;
pc.ext=VER_AVIO&0xff;// AVIO的版本
pc.type=1;
pc.id=ppc->id;
pc.session=m_session;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);
}
else
if(m_iStatus==STA_BUSY&&m_session!=ppc->session)
{
/*//有另一臺機請求通話,拒絕!
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.cmd=CMD_REFUSE;
pc.data_size_extra=0;
pc.ext=R_BUSY;
pc.type=0;
pc.id=ppc->id;
pc.session=ppc->session;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);*/
}
}
}
//回應
else
{
if(ppc->session==m_session)
{
KillTimer(m_MsgRcvWnd,ppc->id);
m_CmdQueue.Remove(ppc->id);
PostMessage(m_hwndMainWnd,IOM_NOTIFY,IOMN_CONNECTED,(LPARAM)this);
}
}
}break;
case CMD_END:
{
if(ppc->session==m_session)
{
if(ppc->type==0)
{
if(m_iStatus==STA_BUSY)
{
PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_END,E_USER),(LPARAM)this);
}
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.data_size_extra=0;
pc.cmd=CMD_END;
pc.type=1;
pc.id=ppc->id;
pc.session=m_session;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);
}
else
{
KillTimer(m_MsgRcvWnd,ppc->id);
m_CmdQueue.Remove(ppc->id);
}
}
}
break;
case CMD_REFUSE:
{
if(ppc->session==m_session)
{
if(ppc->type==0)
{
if(m_iStatus==STA_BUSY)
{
m_iStatus=STA_FREE;
PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_REFUSE,ppc->ext),(LPARAM)this);
}
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.data_size_extra=0;
pc.cmd=CMD_REFUSE;
pc.type=1;
pc.id=ppc->id;
pc.session=m_session;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);
}
else
{
KillTimer(m_MsgRcvWnd,ppc->id);
m_CmdQueue.Remove(ppc->id);
}
}
}
break;
case CMD_ACCEPT:
{
if(ppc->session==m_session)
{
if(ppc->type==0)
{
if(m_iStatus==STA_BUSY)
{
PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ACCEPT,VER_AVIO),(LPARAM)this);
}
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.data_size_extra=0;
pc.cmd=CMD_ACCEPT;
pc.type=1;
pc.id=ppc->id;
pc.session=m_session;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);
}
else
{
KillTimer(m_MsgRcvWnd,ppc->id);
m_CmdQueue.Remove(ppc->id);
}
}
}
break;
case CMD_TXT:
{
if(ppc->type==0)
{
//bug exist
SendMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_TXT,0),(LPARAM)(((char*)ppc)+sizeof(PACK_CMD)));
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.data_size_extra=0;
pc.cmd=CMD_TXT;
pc.type=1;
pc.id=ppc->id;
m_Socket.SendTo((char*)&pc,sizeof(pc),(sockaddr*)&m_sockaddr);
}
else
{
KillTimer(m_MsgRcvWnd,ppc->id);
UINT len;char resend;sockaddr_in addr;
char* p=m_CmdQueue.GetBuf(ppc->id,len,resend,addr);
if(p)
{
SendMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_TXT,1),(LPARAM)(p+sizeof(PACK_CMD)));
}
m_CmdQueue.Remove(ppc->id);
}
}
break;
case CMD_DROPRATE:
{
//根據丟包率來調整視頻質量
if(ppc->type==0&&ppc->session&&m_bEnableBandAdjust)
{
SetVideoQuality(100-ppc->ext);
SendMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_VQSET,100-ppc->ext),(LPARAM)this);
}
}break;
}
}
/*------------------------------------------------------------------------------*/
//以下是設置對外消息接口
//設置主窗口
void CAVIOMgr::SetMainWnd(HWND hwnd)
{
m_hwndMainWnd=hwnd;
}
void CAVIOMgr::SetLocalVideoRcvWnd(HWND hwnd)
{
m_hwndLocalVideoRcv=hwnd;
}
void CAVIOMgr::SetLocalAudioRcvWnd(HWND hwnd)
{
m_hwndLocalAudioRcv=hwnd;
}
void CAVIOMgr::SetRemoteVideoRcvWnd(HWND hwnd)
{
m_hwndRemoteVideoRcv=hwnd;
}
void CAVIOMgr::SetRemoteAudioRcvWnd(HWND hwnd)
{
m_hwndRemoteAudioRcv=hwnd;
}
/*------------------------------------------------------------------------------*/
//得到當前狀態
int CAVIOMgr::GetStatus()
{
return m_iStatus;
}
/*------------------------------------------------------------------------------*/
//調用以下函數要謹慎
//只有在收到相應消息時才能調用
/////////////////////////
///
char* CAVIOMgr::GetLocalVideo(UINT &len)
{
len=m_CodecMgr.m_BmpU.bmiHeader.biSizeImage;
return m_VideoLocal;
}
char* CAVIOMgr::GetLocalAudio(UINT &len)
{
len=SIZE_AUDIO_FRAME;
return m_AudioLocal;
}
char* CAVIOMgr::GetRemoteVideo(UINT &len)
{
len=m_CodecMgr.m_BmpU.bmiHeader.biSizeImage;
return m_VideoRemote;
}
char* CAVIOMgr::GetRemoteAudio(UINT &len)
{
len=SIZE_AUDIO_FRAME;
return m_AudioRemote;
}
/*------------------------------------------------------------------------------*/
//得到原始視頻格式
BITMAPINFO* CAVIOMgr::GetBitampInfo()
{
return &m_CodecMgr.m_BmpU;
}
/*------------------------------------------------------------------------------*/
//得到數據發送量
UINT CAVIOMgr::GetDataSend()
{
return m_uDataSend;
}
/*------------------------------------------------------------------------------*/
//得到數據接收量
UINT CAVIOMgr::GetDataRcv()
{
return m_uDataRcv;
}
/*------------------------------------------------------------------------------*/
//設置是否傳輸視頻
void CAVIOMgr::VideoSend(BOOL b)
{
m_bVideoSend=b;
}
/*------------------------------------------------------------------------------*/
//得到對方地址
sockaddr_in CAVIOMgr::GetRemoteAddr()
{
return m_dst;
}
/*------------------------------------------------------------------------------*/
//設置視頻質量
void CAVIOMgr::SetVideoQuality(UINT q)
{
m_CodecMgr.m_cv.lQ=q*100;
}
/*------------------------------------------------------------------------------*/
//預覽
BOOL CAVIOMgr::EnablePreview(BOOL b)
{
if(m_iStatus==STA_FREE&&b)
{
return InitCap();
}
else
if(m_iStatus==STA_FREE&&!b)
{
DestroyCap();
}
return TRUE;
}
/*------------------------------------------------------------------------------*/
//當對方接收請求后,會受到Accept的消息,這時必須調用此函數,來打開各種設備
void CAVIOMgr::OnAccept()
{
if(m_iStatus==STA_FREE) return;
ZeroMemory(&m_ds,sizeof(m_ds));
m_ds.bVideoOut=true;//always ok
if(InitVideoCodec())
m_ds.bVideoCodec=true;
if(InitAudioCodec())
m_ds.bAudioCodec=true;
if(InitAudioPlay())
m_ds.bAudioOut=true;
if(InitAudioRec())
m_ds.bAudioIn=true;
if(m_ds.bVideoCodec&&InitCap())
m_ds.bVideoIn=true;
if(!m_ds.bAudioCodec&&!m_ds.bVideoCodec)
{
DestroyCap();
DestroyAudioRec();
DestroyAudioPlay();
DestroyAudioCodec();
DestroyVideoCodec();
m_iStatus=STA_FREE;
}
}
/*------------------------------------------------------------------------------*/
//得到幀數
UINT CAVIOMgr::GetFrameCount()
{
return m_nFrameCount;
}
/*------------------------------------------------------------------------------*/
//發送命令(比較可靠)
BOOL CAVIOMgr::SendCmd(PACK_CMD *pCmd, UINT nLen,sockaddr_in &addr, BOOL bFlag)
{
if(!pCmd) return FALSE;
pCmd->id=m_idCmd++;
pCmd->session=m_session;
int l=m_Socket.SendTo((char*)pCmd,nLen,(sockaddr*)&addr);
if(l>0)
{
if(bFlag)
{
m_CmdQueue.Add(pCmd->id,(char*)pCmd,nLen,addr);//把命令加入命令表
SetTimer(m_MsgRcvWnd,pCmd->id,800,CmdTimeOutProc);
}
return TRUE;
}
else
return FALSE;
}
/*------------------------------------------------------------------------------*/
//命令超時重發
void CALLBACK CAVIOMgr::CmdTimeOutProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
if(pMgrInst)
{
UINT len;char resend;sockaddr_in addr;
char* p=pMgrInst->m_CmdQueue.GetBuf(idEvent,len,resend,addr);//找出相應ID的命令(已經超時,需要重發)
if(p)
{
if(resend<5)
pMgrInst->m_Socket.SendTo(p,len,(sockaddr*)&addr);
else//當重發次數超過4次時,宣布失敗
{
KillTimer(hwnd,idEvent);//
if(pMgrInst)
{
PACK_CMD* pCmd=(PACK_CMD*)p;
switch(pCmd->cmd)
{
case CMD_CALL:
{
PostMessage(pMgrInst->m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_REFUSE,R_TIMEOUT),(LPARAM)pMgrInst);
pMgrInst->m_iStatus=STA_FREE;
}
break;
case CMD_REFUSE:
break;
case CMD_ACCEPT:
break;
case CMD_END:
break;
case CMD_TXT:
break;
}
}
pMgrInst->m_CmdQueue.Remove(idEvent);//把命令從表中移除
}
}
else
KillTimer(hwnd,idEvent);
}
}
/*------------------------------------------------------------------------------*/
//丟包率計算(包括幀頻率計算)
void CALLBACK CAVIOMgr::DropRateCounter(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
//計算丟包率
if(pMgrInst)
{
UINT delt;
if(pMgrInst->m_nCurVid<pMgrInst->m_nLastVid)
delt=pMgrInst->m_nCurVid+256-pMgrInst->m_nLastVid;
else
delt=pMgrInst->m_nCurVid-pMgrInst->m_nLastVid;
if(delt>0)
pMgrInst->m_nDropRate=100-(pMgrInst->m_nFrameCount-pMgrInst->m_nLastFrameCount)*100/delt;
pMgrInst->m_nLastVid=pMgrInst->m_nCurVid;
//發送丟包率
PACK_CMD pc;
pc.flag=FLAG_CMD;
pc.cmd=CMD_DROPRATE;
pc.session=pMgrInst->m_session;
pc.type=0;
pc.data_size_extra=0;
pc.ext=pMgrInst->m_nDropRate;
pMgrInst->m_Socket.SendTo((char*)&pc,sizeof(PACK_CMD),(SOCKADDR*)&pMgrInst->m_dst);
//計算幀頻率
pMgrInst->m_nFps=(pMgrInst->m_nFrameCount-pMgrInst->m_nLastFrameCount);
pMgrInst->m_nLastFrameCount=pMgrInst->m_nFrameCount;
}
}
/*------------------------------------------------------------------------------*/
UINT CAVIOMgr::GetFps()
{
return m_nFps;
}
/*------------------------------------------------------------------------------*/
//發送文本信息
BOOL CAVIOMgr::SendTxt(char *ip, unsigned short port, char *txt)
{
BOOL bRet=FALSE;
PACK_CMD *ppc=(PACK_CMD*)new char[sizeof(PACK_CMD)+strlen(txt)+1];
strcpy(((char*)ppc)+sizeof(PACK_CMD),txt);
ppc->flag=FLAG_CMD;
ppc->cmd=CMD_TXT;
ppc->type=0;
ppc->data_size_extra=strlen(txt)+1;
//將ip和port轉化
sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=CUDPSocket::Name2Inet(ip);
addr.sin_port=htons(port);
//
if(!SendCmd(ppc,sizeof(PACK_CMD)+ppc->data_size_extra,addr,TRUE))
goto RET;
bRet=TRUE;
RET:
return bRet;
}
/*------------------------------------------------------------------------------*/
//得到前一次發來數據的地址
sockaddr_in& CAVIOMgr::GetCurrentAddr()
{
return m_sockaddr;
}
/*------------------------------------------------------------------------------*/
//
BOOL CAVIOMgr::Enable(BOOL bEnable)
{
BOOL t=m_bEnable;
m_bEnable=bEnable;
return t;
}
/*------------------------------------------------------------------------------*/
//是否自動調整圖象質量
BOOL CAVIOMgr::EnableBandAdjust(BOOL bEnable)
{
BOOL t=m_bEnableBandAdjust;
m_bEnableBandAdjust=bEnable;
return t;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -