现在我通过一个端口接受来自服务器视频数据包,当收到数据为一个人时解码显示OK
当收到多个人的数据包时候就会显示混乱,代码逻辑个人感觉没有什么问题:
帮忙解决的可另外加分,不胜感激,参与讨论的也会酌情给分,谢谢。关键代码如下:struct UserListItem
{
ID recvID;
//用户所在组指针
CGroupMgr *pGroup;
//用户是否需要显示
BOOL show; //接收到的用户视频数据
char videoData[MAX_VIDEO_SIZE]; //用户视频数据的窗口指针
CWnd* vWnd;
};
收到一个包ppv后,
void CGAVEngine::OnDecodeVideoData(PACK_VIDEO *ppv, int len)
{ vector<UserListItem>::iterator it;
for(it=m_UserList.begin();it!= m_UserList.end();it++)
{
//如果用户列表里面存在该数据包的发送用户,则通知该用户所在组
if (it->recvID == ppv->local_ID && it->show == TRUE)
{
//(char*)ppv)+sizeof(PACK_VIDEO)是将指针转到视频数据区,就是跳过包前面的包信息段;
if(m_CodecMgr.DecodeVideoData(((char*)ppv)+sizeof(PACK_VIDEO),ppv->data_size,it->videoData,0,0))
m_nCurVid=ppv -> id; //该函数将显示用户的视频,数据内容从it->videoData中获取
it->pGroup->OnRecvVideo(FALSE, ppv->local_ID, this);
}
}
}
当收到多个人的数据包时候就会显示混乱,代码逻辑个人感觉没有什么问题:
帮忙解决的可另外加分,不胜感激,参与讨论的也会酌情给分,谢谢。关键代码如下:struct UserListItem
{
ID recvID;
//用户所在组指针
CGroupMgr *pGroup;
//用户是否需要显示
BOOL show; //接收到的用户视频数据
char videoData[MAX_VIDEO_SIZE]; //用户视频数据的窗口指针
CWnd* vWnd;
};
收到一个包ppv后,
void CGAVEngine::OnDecodeVideoData(PACK_VIDEO *ppv, int len)
{ vector<UserListItem>::iterator it;
for(it=m_UserList.begin();it!= m_UserList.end();it++)
{
//如果用户列表里面存在该数据包的发送用户,则通知该用户所在组
if (it->recvID == ppv->local_ID && it->show == TRUE)
{
//(char*)ppv)+sizeof(PACK_VIDEO)是将指针转到视频数据区,就是跳过包前面的包信息段;
if(m_CodecMgr.DecodeVideoData(((char*)ppv)+sizeof(PACK_VIDEO),ppv->data_size,it->videoData,0,0))
m_nCurVid=ppv -> id; //该函数将显示用户的视频,数据内容从it->videoData中获取
it->pGroup->OnRecvVideo(FALSE, ppv->local_ID, this);
}
}
}
解决方案 »
- VC怎么做个VPN连接客户端以及服务端
- 应该是最简单的问题了,但我不懂,虚心请教
- 关于动态连接库中def文件的有关问题
- 我的机器c盘上装的是windows2000如何将c盘format?我手头除了windows2000以外,没有软件,是否需要下在什么软件?
- 客户端程序联接数据库的问题
- [热烈讨论]薄荷当水源大斑竹,对VC版的利弊!!!
- 100分求界面设计的书,最好是电子书,给初学者看的,不要太难……
- 请高手推荐几篇介绍COM的文章
- 如何在ListCtrl的某列中嵌入ComboBox控件
- VC ADO insert into的傻瓜问题!急!!!!
- 如何获取 hr(HRESULT hr;)的值??
- 关于分栏条的位置问题
谢谢wenxy1,获取数据的方式每个用户独立的videoData,上面结构体里面有定义,刚才检查了一遍,这块代码逻辑上没有什么问题
char* CGAVEngine::GetRemoteVideo(UINT &len, ID id)
{
vector<ReceivedListItem>::iterator it;
for(it=m_ReceiveList.begin();it!=m_ReceiveList.end();it++)
{
//如果接受列表里面存在该数据包的发送用户,则通知该用户所在组
if (it->recvID == id && it->videoData)
return it->videoData;
}
AfxMessageBox(_T("远程视频错误"));
return 0;
}
消息响应函数:
LRESULT CVideoWnd::OnMsgVideo(WPARAM wParam, LPARAM lParam)
{
if((CGAVEngine*)lParam && (ID)wParam)
m_vs.OnVideoData(ID(wParam), (CGAVEngine*)lParam); return 0;
}视频显示代码,通过消息触发:
/*------------------------------------------------------------------------------*/
//得到视频数据,并画出来。TODO:大小位置还需要斟酌
void CVideoShow::OnVideoData(DWORD id, CGAVEngine *pEngine)
{
RECT rc;
CDC* cdc=GetDC();
HDC hdc = cdc->GetSafeHdc();
HDC hMemDC=CreateCompatibleDC(hdc);
GetClientRect(&rc);
m_hBmp=CreateCompatibleBitmap(hdc,176,144);
HBITMAP hob=(HBITMAP)SelectObject(hMemDC,m_hBmp);
if(hob)
{
UINT len;
char* p;
if(id == pEngine->GetLocalID())
p=pEngine->GetLocalVideo(len);
else
p=pEngine->GetRemoteVideo(len, id); BITMAPINFOHEADER* pbih=&pEngine->GetBitampInfo()->bmiHeader;
HDRAWDIB h=DrawDibOpen();
DrawDibDraw(h,hMemDC,0,0,rc.right,rc.bottom,pbih,p,0,0,pbih->biWidth,pbih->biHeight,DDF_NOTKEYFRAME);
DrawDibClose(h);
BitBlt(hdc,0,0,rc.right,rc.bottom,hMemDC,0,0,SRCCOPY);
SelectObject(hMemDC,hob);
}
DeleteDC(hMemDC);
ReleaseDC(cdc);
if(!IsWindowVisible())
ShowWindow(SW_SHOW);
}
m_hSockThread=CreateThread(0,0,SockThreadProc,(LPVOID)this,0,&m_dwSockThreadId);然后收到数据包,之后就按照上面代码顺序执行了
像是你的这些m_UserList成员变量,都没有做互斥处理,多线程会有问题的
建议做同步后试一下
你这种情况用mutex就可以了
例如:m_UserList
你这种情况用mutex就可以了
例如:m_UserList
你这种情况用mutex就可以了
例如:m_UserList
我的理解是:监听端口线程,现在只是执行这段代码:
case FLAG_VIDEO:
{
PACK_VIDEO* packVideo= (PACK_VIDEO*) buf; //将视频数据包包解压;
if(pEngine->m_videoCodec)
pEngine->OnDecodeVideoData(packVideo, iLen);
}//视频解码
void CEngine::OnDecodeVideoData(PACK_VIDEO *ppv, int len)
{ vector<UserListItem>::iterator it;
for(it=m_UserList.begin();it!=m_UserList.end();it++)
{
//如果接受列表里面存在该数据包的发送用户,则通知该用户所在组
if (it->recvID == ppv->local_ID && it->show == TRUE)
{
if(m_CodecMgr.DecodeVideoData(((char*)ppv)+sizeof(PACK_VIDEO),ppv->data_size,it->videoData,0,0))
{
m_nCurVid=ppv -> id;
} //统计收到的数据
m_uDataRcv+=sizeof(PACK_VIDEO)+ppv->data_size; it->pGroup->OnRecvVideo(FALSE, ppv->local_ID, this);
}
}里面的ppv需不需要同步,因为m_UserList是保存了所有的用户列表,是通过ppv中的id来识别一个用户的,是不是说明该同步ppv,以前没有做过多线程的东西,希望高手指教