M
录像播放
选中需要播放录像的通道后,单击播放按钮,响应函数如下
void CReplayPaneDlg::OnPlay()
{
IVideoReplayModel* pModel = GetInlPtr<IVideoReplayModel*>(_T("VideoReplayModel"));
if(pModel == NULL)
{
return;
}
if(m_bPlaying)
{ //解除暂停
if (pModel->IsSycReplay())
{
pModel->ResumeReplayAll();
}
else
{
pModel->ResumeReplayChannel();
}
m_bPause = false;
}
else
{ //播放
int ret;
if (pModel->IsSycReplay())
{
ret = pModel->OpenVideoReplayAll();
}
else
{
ret = pModel->OpenVideoReplayChannel();
}
if (ret == 1)
{
/*播放前请先勾选通道并进行录像文件的搜索*/
}
else if (ret==2)
{
/*没有录像文件*/
}
m_bPlaying = true;
m_bLinked = false;
m_slider_speed.SetPos(4);
}
RefreshBtnStatus(); //更新播放控制面板上的按钮状态
}
主要调用的是VideoReplayModel里的几个函数,先看OpenVideoReplayChannel
LONG CVideoReplayModel::OpenVideoReplayChannel()
{
if(!m_bAsyncReplayFlag) //异步回放
{
return errError;
}
if(m_selectedItemIndex < 1 || m_selectedItemIndex > 4)
{
return errBadArg;
}
ReplayCmdData cmdData;
cmdData.cmd = eReplayStart;
m_modelLock.Acquire();
//判断是否搜索过
if(m_ItemBuf.size() == 0)
{
m_modelLock.Release();
return errNotExist;
}
for(std::list<ReplayItemData>::iterator it = m_ItemBuf.begin(); it != m_ItemBuf.end(); it++)
{
if(it->bExistedFile && m_selectedItemIndex == it->nIndexItem && !it->bPlaying)
{
cmdData.listItem.push_back(*it);
it->status = eReplayStatusLinking;
it->bPlaying = true;
it->bValid = true;
break;
}
}
m_modelLock.Release();
if(cmdData.listItem.size()==0)
{
return errNotExist;
}
Notify(EVT_REPLAY_CMD, &cmdData);
return errNone;
}
事件EVT_REPLAY_CMD的响应函数位于Replay中的PlaybackManager,这里对播放命令汇总再转发出去,这里先看eReplayStart
LRESULT CPlaybackManager::OnReplayCmd(IEventData *pData)
{
ReplayCmdData *cmdData = dynamic_cast<ReplayCmdData*>(pData);
if (cmdData)
{
switch (cmdData->cmd)
{
case eReplayStart:
StartReplay(cmdData->listItem);
break;
case eReplayStop:
StopReplay(cmdData->listItem);
break;
case eReplayJump:
JumpReplay(cmdData->listItem);
break;
case eReplayPause:
PauseReplay(cmdData->listItem);
break;
case eReplayResume:
ResumeReplay(cmdData->listItem);
break;
case eReplayChangeSpeed:
SetSpeed(cmdData->listItem, cmdData->param);
break;
case eReplayFast:
PlayFast(cmdData->listItem);
break;
case eReplaySlow:
PlaySlow(cmdData->listItem);
break;
case eReplayCapture:
CaptureImage(cmdData->listItem);
break;
case eReplayStartEditVideo:
EditVideo(cmdData->listItem, true);
break;
case eReplayStopEditVideo:
EditVideo(cmdData->listItem, false);
break;
case eReplayIncreaseBright:
IncreaseBright();
break;
case eReplayReduceBright:
ReduceBright();
break;
case eReplayIncreaseContrast:
IncreaseContrast();
break;
case eReplayReduceContrast:
ReduceContrast();
break;
default:
break;
}
}
return S_OK;
}
调用StartReplay
int CPlaybackManager::StartReplay(std::list<ReplayItemData> &listItem)
{
IVideoReplayControl* replayControl = GetInlPtr<IVideoReplayControl*>(_T("VideoReplayControl"));
if (replayControl==NULL)
{
return 1;
}
IVideoReplayModel* pModel = GetInlPtr<IVideoReplayModel*>(_T("VideoReplayModel"));
if (pModel==NULL)
{
return 1;
}
IMitModel * pMitObj = GetInlPtr<IMitModel*>(_T("MitModel"));
if (pMitObj==NULL)
{
return 1;
}
{
std::list<ReplayItemData>::iterator it = listItem.begin();
for (; it != listItem.end(); it++)
{
CPlaybacker *wnd = dynamic_cast<CPlaybacker*>(GetItem(it->nIndexItem));
HWND hWnd = wnd->GetPlayWnd();
if (hWnd)
{
LONG streamId;
LONG ret;
ret = replayControl->Play(it->fileRes, it->oid, ULONG((it->tm_end-it->tm_begin)/1000), hWnd, NULL, it->tm_begin+it->jumpPos*1000, streamId, DrawZoomInFun, (LONG)wnd);
if (ret == errNone)
{
pModel->SetReplayStreamID(it->nIndexItem, streamId);
//设置title状态
wnd->SetStreamStatus(eReplayStatusLinking, streamId);
}
else
{
wnd->SetStreamStatus(eReplayStatusMaxLimit,-1);
}
}
}
}
return 0;
}
主要看调用的play函数
LONG CVideoReplayControl::Play(CString szOid, CString szEncOid, ULONG nTotalTime,HWND hWnd, void* pParam, SDPTIME jumpPos, LONG &id, DrawFunEx func, LONG drawData)
{
IAVStream *pAVStream = GetInlPtr<IAVStream*>(_T("AVStream"));
if (pAVStream==NULL)
{
return errNotExist;
}
//note未知修改,但是回放、电子地图有可能同时回放同一段录像文件
//先判断是否重复,依据窗口句柄
m_lockDataList.Acquire();
std::list<ReplayInf>::iterator it = m_listReplayInf.begin();
for (; it != m_listReplayInf.end(); it++)
{
if (it->hWnd == hWnd)
{
DEBUGINFO(DEBUG_WARNING, _T("warning -- 在同一窗口中重复开启录像文件"), szOid);
m_lockDataList.Release();
return 1;
}
}
m_lockDataList.Release();
ULONG maxwidth = 0;
ULONG maxheight = 0;
if(pAVStream->Connect(szOid, ENEAVProtocol_all,ReplayStream,CB_RecvStream,hWnd,false,id,NULL,maxwidth,maxheight) == true)
{
ReplayInf rp;
rp.id = id;
rp.strOid = szOid;
rp.nBright = 8;
rp.nContrast = 8;
rp.nSpeed = 0;
rp.hWnd = hWnd;
rp.nStatus = 0;
rp.bSound = FALSE;
rp.bFull = FALSE;
rp.nTm = jumpPos;
rp.nTotalTime=nTotalTime;
rp.bLink = FALSE;
rp.strEncOid = szEncOid;
rp.nNoDataCome = 0;
rp.width=maxwidth;
rp.height=maxheight;
rp.drawFunc=func;
rp.drawData=drawData;
addReplayInf(rp);
ReplayDataInf rpDataInf;
rpDataInf.id = id;
rpDataInf.nPacket = 0;
rpDataInf.bPlay = TRUE;
rpDataInf.pData = NULL;
rpDataInf.bCheck = FALSE;
rpDataInf.bCanInputData = TRUE;
rpDataInf.bFirst = false;
rpDataInf.fEdit=NULL;
addReplayDataInf(rpDataInf);
m_mapAvStreamStatus[id] = 1;
return errNone;
}
return errError;
}
在后面的处理都位于AVStream中,在此不再深究。