AVIOMgr.cpp
资源名称:网络视频电话系统.rar [点击查看]
上传用户:oldpeter23
上传日期:2013-01-09
资源大小:1111k
文件大小:28k
源码类别:
IP电话/视频会议
开发平台:
Visual C++
- //NetTalk
- /*------------------------------------------------------------------------------*
- =============================
- 模块名称: AVIOMgr.cpp
- =============================
- [版权]
- 2000-2002 115软件工厂 版权所有
- *------------------------------------------------------------------------------*/
- #include "WndX.h"
- #include <vfw.h>
- #include "AVIOMgr.h"
- #include "UDPSocket.h"
- #include "g729a.h"
- #include "AudioPlay.h"
- #include <stdio.h>
- /*------------------------------------------------------------------------------*/
- CAVIOMgr* pMgrInst=0;
- /*------------------------------------------------------------------------------*/
- //声音输入线程,包括声音的压缩
- DWORD WINAPI CAVIOMgr::AudioInThreadProc(LPVOID lpParameter)
- {
- CAVIOMgr* pMgr=(CAVIOMgr*)lpParameter;
- MSG msg;
- while(GetMessage(&msg,0,0,0))
- {
- switch(msg.message)
- {
- case WIM_DATA:
- {
- WAVEHDR* pWH=(WAVEHDR*)msg.lParam;
- waveInUnprepareHeader((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
- if(pWH->dwBytesRecorded!=SIZE_AUDIO_FRAME)
- break;//it's not full recorded,i think the wave recorder has ben
- //stopped,discard it,and don't do anything!
- //
- CopyMemory(pMgr->m_AudioLocal,pWH->lpData,SIZE_AUDIO_FRAME);
- pMgr->OnEncodeAudioData(pMgr->m_AudioLocal,SIZE_AUDIO_FRAME);
- waveInPrepareHeader((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
- waveInAddBuffer((HWAVEIN)msg.wParam,pWH,sizeof(WAVEHDR));
- }
- break;
- }
- }
- return msg.wParam;
- }
- /*------------------------------------------------------------------------------*/
- //音频输出线程,包括音频解码
- DWORD WINAPI CAVIOMgr::AudioOutThreadProc(LPVOID lpParameter)
- {
- CAVIOMgr* pMgr=(CAVIOMgr*)lpParameter;
- MSG msg;
- while(GetMessage(&msg,0,0,0))
- {
- switch(msg.message)
- {
- case IOM_AUDIO:
- pMgr->OnDecodeAudioData((PACK_AUDIO*)msg.lParam,(int)msg.wParam);
- break;
- case WOM_DONE:
- {
- WAVEHDR* pwh=(WAVEHDR*)msg.lParam;
- waveOutUnprepareHeader((HWAVEOUT)msg.wParam,pwh,sizeof(WAVEHDR));
- pMgr->m_iAudioBuf--;
- delete []pwh->lpData;//删除Play调用时分配的内存
- delete pwh;
- }
- break;
- }
- }
- return msg.wParam;
- }
- /*------------------------------------------------------------------------------*/
- //视频流回调函数
- LRESULT CALLBACK CAVIOMgr::VideoStreamCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
- {
- CAVIOMgr* pMgr=(CAVIOMgr*)capGetUserData(hWnd);
- if(pMgr)
- {
- //压缩视频数据
- pMgr->OnEncodeVideoData((char*)lpVHdr->lpData,lpVHdr->dwBytesUsed);
- }
- return TRUE;
- }
- /*------------------------------------------------------------------------------*/
- //Socket线程,负责接收数据
- DWORD WINAPI CAVIOMgr::SockThreadProc(LPVOID lpParameter)
- {
- CAVIOMgr* pMgr=(CAVIOMgr*)lpParameter;
- char buf[4096];
- int iLen=0;
- while(1)
- {
- iLen=pMgr->m_Socket.RecvFrom(buf,4096,(sockaddr*)&pMgr->m_sockaddr);
- if(iLen>0)
- {
- switch(*((short*)buf))//check the flag
- {
- case FLAG_CMD:
- {
- //命令
- pMgr->OnCommand((PACK_CMD*)buf,iLen);
- }
- break;
- case FLAG_AUDIO:
- {
- //音频数据
- if(pMgr->m_ds.bAudioOut&&
- pMgr->m_ds.bAudioCodec&&
- pMgr->m_hAudioOut&&
- ((PACK_AUDIO*)buf)->session==pMgr->m_session)
- {
- char* p=new char[iLen];
- if(p)
- {
- CopyMemory(p,buf,iLen);
- if(!PostThreadMessage(pMgr->m_dwAudioOutId,IOM_AUDIO,iLen,(LPARAM)p))
- delete []p;
- }
- }
- }
- break;
- case FLAG_VIDEO:
- {
- //视频数据
- if(pMgr->m_ds.bVideoOut&&
- pMgr->m_ds.bVideoCodec&&
- ((PACK_VIDEO*)buf)->session==pMgr->m_session)
- {
- pMgr->OnDecodeVideoData((PACK_VIDEO*)buf,iLen);
- }
- }
- break;
- }
- }
- else
- {
- if(!pMgr->m_Socket.IsSocket())
- break;
- }//the socket should be closed,that is m_Socket have been
- //destroyed,so break the loop and end the thread
- }
- return 0;
- }
- /*------------------------------------------------------------------------------*/
- CAVIOMgr::CAVIOMgr()
- {
- pMgrInst=this;
- m_hSockThread=NULL;
- m_hAudioOut=0;
- m_hAudioIn=0;
- m_idCmd=0;
- m_bEnable=TRUE;
- m_bEnableBandAdjust=TRUE;
- }
- /*------------------------------------------------------------------------------*/
- CAVIOMgr::~CAVIOMgr()
- {
- Destroy();
- pMgrInst=0;
- }
- /*------------------------------------------------------------------------------*/
- //初始化SOCKET,指定PORT
- BOOL CAVIOMgr::InitSocket(UINT nPort)
- {
- DestroySocket();
- BOOL bRet=FALSE;
- if(!m_Socket.Create(nPort))
- goto RET;
- //创建socket线程(socket为block方式)
- m_hSockThread=CreateThread(0,0,SockThreadProc,(LPVOID)this,0,&m_dwSockThreadId);
- if(!m_hSockThread)
- goto RET;
- bRet=TRUE;
- RET:
- if(!bRet)
- DestroySocket();
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- BOOL CAVIOMgr::DestroySocket()
- {
- m_Socket.Destroy();
- //
- if(m_hSockThread)
- {
- BOOL b=FALSE;
- DWORD ExitCode;
- int Timeout = 50;
- while(Timeout)//等待线程结束,如果到一定时间还没结束,就强制结束
- { //因为Socket已经destroy了,所以socket线程会返回
- GetExitCodeThread(m_hSockThread, &ExitCode);
- if (ExitCode != STILL_ACTIVE)
- {
- b=TRUE;
- // Thread has ended.
- break;
- }
- else
- {
- Sleep(10);
- }
- --Timeout;
- }
- if(!b)//time out ,terminate it
- TerminateThread(m_hSockThread,0);
- }
- m_hSockThread=NULL;
- return TRUE;
- }
- /*------------------------------------------------------------------------------*/
- //设定目标
- void CAVIOMgr::SetDst(char *ip, unsigned short port)
- {
- m_dst.sin_family=AF_INET;
- //将计算机名或IP转化为网络地址
- m_dst.sin_addr.s_addr=CUDPSocket::Name2Inet(ip);
- m_dst.sin_port=htons(port);
- }
- /*------------------------------------------------------------------------------*/
- //初始化音频输入,当初始化完成,录音就开始了
- BOOL CAVIOMgr::InitAudioRec()
- {
- DestroyAudioRec();
- BOOL bRet=FALSE;
- //创建录音线程
- m_hAudioIn=CreateThread(0,0,AudioInThreadProc,this,0,&m_dwAudioInId);
- if(!m_hAudioIn)
- goto RET;
- if(!m_AudioRec.Create(0,m_dwAudioInId,(DWORD)this,CALLBACK_THREAD,SIZE_AUDIO_FRAME))
- goto RET;
- //开始录音
- if(!m_AudioRec.Start())
- goto RET;
- bRet=TRUE;
- RET:
- if(!bRet)
- {
- //如果失败,就向主窗口发送出错消息
- PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ERR,IOME_AUDIO_IN),(LPARAM)this);
- DestroyAudioRec();
- }
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- //该死的waveIn函数,结束录音时老是出现死锁(XP下还是会出现这个问题,也不知道怎么解决,苦啊)
- BOOL CAVIOMgr::DestroyAudioRec()
- {
- m_AudioRec.Stop();
- m_AudioRec.Destroy();
- if(m_hAudioIn)
- {
- int t=50;
- DWORD ExitCode;
- BOOL bEnd=FALSE;
- //向录音线程发送退出消息,并等待线程结束
- PostThreadMessage(m_dwAudioInId,WM_QUIT,0,0);
- while(t)
- {
- GetExitCodeThread(m_hAudioIn,&ExitCode);
- if(ExitCode!= STILL_ACTIVE)
- {
- bEnd=TRUE;
- break;
- }
- else
- Sleep(10);
- t--;
- }
- if(!bEnd)
- TerminateThread(m_hAudioIn,0);
- m_hAudioIn=0;
- }
- return TRUE;
- }
- /*------------------------------------------------------------------------------*/
- //初始化播放设备
- BOOL CAVIOMgr::InitAudioPlay()
- {
- BOOL bRet=FALSE;
- DestroyAudioPlay();
- m_iAudioBuf=0;
- m_hAudioOut=CreateThread(0,0,AudioOutThreadProc,this,0,&m_dwAudioOutId);
- if(!m_hAudioOut)
- goto RET;
- if(!m_AudioPlay.Create(0,m_dwAudioOutId,(DWORD)this,CALLBACK_THREAD))
- goto RET;
- bRet=TRUE;
- RET:
- if(!bRet)
- {
- //向主窗口发送出错消息
- PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ERR,IOME_AUDIO_OUT),(LPARAM)this);
- DestroyAudioPlay();
- }
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- //
- BOOL CAVIOMgr::DestroyAudioPlay()
- {
- m_AudioPlay.Destroy();
- if(m_hAudioOut)
- {
- int t=50;
- DWORD ExitCode;
- BOOL bEnd=FALSE;
- PostThreadMessage(m_dwAudioOutId,WM_QUIT,0,0);
- while(t)
- {
- GetExitCodeThread(m_hAudioOut,&ExitCode);
- if(ExitCode!= STILL_ACTIVE)
- {
- bEnd=TRUE;
- break;
- }
- else
- Sleep(10);
- t--;
- }
- if(!bEnd)
- TerminateThread(m_hAudioOut,0);
- m_hAudioOut=0;
- }
- return TRUE;
- }
- /*------------------------------------------------------------------------------*/
- //音频解码,并将音频数据发送到想要数据的窗口
- void CAVIOMgr::OnDecodeAudioData(PACK_AUDIO *ppa, int len)
- {
- if(m_CodecMgr.DecodeAudioData((char*)ppa->data,SIZE_AUDIO_PACKED,m_AudioRemote,0))
- {
- //为了避免延迟过长,当累积的缓冲超过六块时抛弃即将加入的缓冲
- if(m_iAudioBuf<6)
- {
- m_iAudioBuf++;
- m_AudioPlay.Play(m_AudioRemote,SIZE_AUDIO_FRAME);
- }
- if(m_hwndRemoteAudioRcv)
- SendMessage(m_hwndRemoteAudioRcv,IOM_AUDIO,1,(LPARAM)this);
- }
- m_uDataRcv+=sizeof(PACK_AUDIO);
- delete []ppa;
- }
- /*------------------------------------------------------------------------------*/
- //压缩音频原始数据并发送出去
- void CAVIOMgr::OnEncodeAudioData(char *pa, int len)
- {
- m_AudioPack.flag=FLAG_AUDIO;
- m_AudioPack.session=m_session;
- if(m_CodecMgr.EncodeAudioData(pa,len,(char*)m_AudioPack.data,0))
- {
- m_Socket.SendTo((char*)&m_AudioPack,sizeof(PACK_AUDIO),(sockaddr*)&m_dst);
- m_uDataSend+=sizeof(PACK_AUDIO);
- }
- if(m_hwndLocalAudioRcv)
- SendMessage(m_hwndLocalAudioRcv,IOM_AUDIO,0,(LPARAM)this);
- }
- /*------------------------------------------------------------------------------*/
- //视频解码
- void CAVIOMgr::OnDecodeVideoData(PACK_VIDEO *ppv, int len)
- {
- if(m_CodecMgr.DecodeVideoData(((char*)ppv)+sizeof(PACK_VIDEO),ppv->data_size,m_VideoRemote,0,0))
- {
- m_nFrameCount++;
- m_nCurVid=ppv->id;
- //将视频数据发送到视频显示窗口
- if(m_hwndRemoteVideoRcv)
- SendMessage(m_hwndRemoteVideoRcv,IOM_VIDEO,1,(LPARAM)this);
- }
- //统计收到的数据
- m_uDataRcv+=sizeof(PACK_VIDEO)+ppv->data_size;
- }
- /*------------------------------------------------------------------------------*/
- //视频压缩并发送
- void CAVIOMgr::OnEncodeVideoData(char *pv, int len)
- {
- int rlen;
- if(m_bVideoSend)
- {
- if(m_CodecMgr.EncodeVideoData(pv,len,m_VideoPack+sizeof(PACK_VIDEO),&rlen,0))
- {
- ((PACK_VIDEO*)m_VideoPack)->data_size=(unsigned short)rlen;
- ((PACK_VIDEO*)m_VideoPack)->id=m_idVideo++;
- ((PACK_VIDEO*)m_VideoPack)->session=m_session;
- m_Socket.SendTo(m_VideoPack,rlen+sizeof(PACK_VIDEO),(sockaddr*)&m_dst);
- //统计发送的数据
- m_uDataSend+=rlen+sizeof(PACK_VIDEO);
- }
- }
- m_VideoLocal=pv;
- if(m_hwndLocalVideoRcv)
- {
- //将视频数据发送到视频显示窗口
- SendMessage(m_hwndLocalVideoRcv,IOM_VIDEO,0,(LPARAM)this);
- }
- }
- /*------------------------------------------------------------------------------*/
- //初始化,创建SOCKET,并监听
- BOOL CAVIOMgr::Init(UINT nPort)
- {
- Destroy();
- m_hwndLocalVideoRcv=0;
- m_hwndLocalAudioRcv=0;
- m_hwndRemoteVideoRcv=0;
- m_hwndRemoteAudioRcv=0;
- m_hwndMainWnd=0;
- m_bVideoSend=TRUE;
- m_iStatus=STA_FREE;
- BOOL bRet=FALSE;
- m_uDataRcv=0;
- m_uDataSend=0;
- if(!InitSocket(nPort))
- goto RET;
- //创建消息接收窗口,主要用于超时重发机制,因为要设定很多不同ID的定时器
- m_MsgRcvWnd.Create(0,0,0,0,CRectX(0,0,0,0),0,0);
- bRet=TRUE;
- RET:
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- //初始化视频捕捉设备
- BOOL CAVIOMgr::InitCap()//
- {
- HWND hCap;
- m_ViCap.Destroy();
- BOOL bRet=FALSE;
- if(!m_ViCap.Init())
- goto RET;
- //得到驱动数
- if(!m_ViCap.GetDriverNum())
- goto RET;
- //连接到驱动
- if(!m_ViCap.ConnectToDriver(0))
- goto RET;
- hCap=m_ViCap.GetCapWindow();
- //设置视频格式
- if(!capSetVideoFormat(hCap,&m_CodecMgr.m_BmpU,sizeof(BITMAPINFO)))
- goto RET;
- //设置视频流回调函数
- if(!capSetCallbackOnVideoStream(hCap,VideoStreamCallbackProc))
- goto RET;
- //将user数据设为AVIOMgr对象指针
- if(!capSetUserData(hCap,(DWORD)this))
- goto RET;
- //开始视频流
- if(!capCaptureSequenceNoFile(hCap))
- goto RET;
- bRet=TRUE;
- RET:
- if(!bRet)
- {
- PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ERR,IOME_VIDEO_IN),(LPARAM)this);
- m_ViCap.Destroy();
- }
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- BOOL CAVIOMgr::DestroyCap()
- {
- m_ViCap.Destroy();
- return TRUE;
- }
- /*------------------------------------------------------------------------------*/
- void CAVIOMgr::Destroy()
- {
- EndTalk();
- DestroySocket();
- DestroyAudioRec();
- DestroyCap();
- DestroyAudioPlay();
- DestroyAudioCodec();
- DestroyVideoCodec();
- }
- /*------------------------------------------------------------------------------*/
- //
- BOOL CAVIOMgr::InitAudioCodec()
- {
- BOOL bRet=FALSE;
- if(!m_CodecMgr.InitCodecA())
- goto RET;
- //启动丢包率定时器
- SetTimer(m_hwndMainWnd,100,1000,DropRateCounter);
- bRet=TRUE;
- RET:
- if(!bRet)
- {
- PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ERR,IOME_AUDIO_CODEC),(LPARAM)this);
- DestroyAudioCodec();
- }
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- //
- void CAVIOMgr::DestroyAudioCodec()
- {
- //关闭丢包率定时器
- KillTimer(m_hwndMainWnd,100);
- m_CodecMgr.DestroyCodecA();
- }
- /*------------------------------------------------------------------------------*/
- //初始化视频编码解码器
- BOOL CAVIOMgr::InitVideoCodec()
- {
- m_idVideo=0;
- m_nFps=0;
- m_nFrameCount=0;
- m_nLastFrameCount=0;
- m_nDropRate=0;
- m_nCurVid=0;
- m_nLastVid=0;
- BOOL bRet=FALSE;
- //
- if(!m_CodecMgr.InitCodecV())
- goto RET;
- ((PACK_VIDEO*)m_VideoPack)->flag=FLAG_VIDEO;
- bRet=TRUE;
- RET:
- if(!bRet)
- {
- PostMessage(m_hwndMainWnd,IOM_NOTIFY,MAKEWPARAM(IOMN_ERR,IOME_VIDEO_CODEC),(LPARAM)this);
- DestroyVideoCodec();
- }
- return bRet;
- }
- /*------------------------------------------------------------------------------*/
- void CAVIOMgr::DestroyVideoCodec()
- {
- m_CodecMgr.DestroyCodecV();
- }
- /*------------------------------------------------------------------------------*/
- void CAVIOMgr::GetDeviceSupport(DEVICE_SUPPORT &ds)
- {
- }
- /*------------------------------------------------------------------------------*/
- //呼叫某个IP
- BOOL CAVIOMgr::Call(char *ip, unsigned short port)
- {
- 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;
- }