之前一个朋友遇到播放sony摄像机视频的问题,使用sony的SDK,播放一段时间后视频卡死,图像黑屏。将资源释放后,重新尝试还是不能播放视频,只有重启程序,SDK具体问题没有去分析。后来我采用RTSP协议来说实现获取摄像机视频并播放,从而规避SDK的问题。使用live555开源库实现rtspClient,下载的live555源码里有rtspClient的demo程序,不过有几个小问题,先将问题描述及解决办法记录下来,并附上修改了的关键代码,如果需要详细的代码可在CSDN下载区下载,希望可以帮助到有这方面需要的朋友。
1.使用live555的rtspClient demo,在一段时间后,会收到摄像机端的bye消息,后通过分析发现需要周期的向摄像机发送get parammeter命令消息。解决该问题。解决办法:收到第一帧视频数据后开始周期发送Get Parammeter消息到摄像机。主要代码如下:
void CRtspStreamProtocol::OnTimerMessage(CTimer* pTimer)
{
if(pTimer!=&m_Timer)
{
return;
}
if(m_rtspClient==NULL)
{
return;
}
ourRTSPClient *pOurRTSPClient =(ourRTSPClient*)m_rtspClient;
//check the server stat
if(pOurRTSPClient->m_nPlaying==1)
{
pOurRTSPClient->m_nWaitFrameCnt++;
}
if(pOurRTSPClient->m_nStartGetParam==1)
{
pOurRTSPClient->m_nSendGetParamTimerCnt++;
if(pOurRTSPClient->m_nSendGetParamTimerCnt==GET_PARAMETERS_INTERVAL)
{
UsageEnvironment& env = m_rtspClient->envir(); // alias
StreamClientState& scs = ((ourRTSPClient*)m_rtspClient)->scs; // alias
m_rtspClient->sendGetParameterCommand(*scs.session, getParameters,NULL);
pOurRTSPClient->m_nSendGetParamTimerCnt =0;
}
}
}
2. 支持重连摄像机,当与摄像机网络连接出故障时,需要重连摄像机。解决方法:使用摄像机发送的视频帧做为判断网络的条件,在一定时间内收不到摄像机的视频数据,认为网络异常,释放所有的live555库资源,重起rtsp连接过程。主要代码如下:
bool CRtspStreamProtocol::Live555Restart()
{
LOG<<"wait frame time out,restart\n";
if (NULL != m_rtspClient)
{
Medium::close(m_rtspClient);
m_rtspClient = NULL;
}
if (NULL != m_env)
{
m_env->reclaim();
m_env = NULL;
}
if (NULL != m_scheduler)
{
delete m_scheduler;
m_scheduler = NULL;
}
if (NULL == m_scheduler)
{
m_Basicscheduler = BasicTaskScheduler::createNew();
m_scheduler = m_Basicscheduler;
}
if (NULL == m_scheduler)
{
return false;
}
if (NULL == m_env)
{
m_env = BasicUsageEnvironment::createNew(*m_scheduler);
}
if (NULL == m_env)
{
return false;
}
if (NULL == m_rtspClient)
{
m_rtspClient =ourRTSPClient::createNew(*m_env, m_strRtspUrl.c_str(), RTSP_CLIENT_VERBOSITY_LEVEL,PROC_NAME);
}
if (NULL == m_rtspClient)
{
return false;
}
LOG<<"wait frame time out,restart end\n";
return true;
}
bool CRtspStreamProtocol::_RunTask()
{
m_Basicscheduler = BasicTaskScheduler::createNew();
m_scheduler = m_Basicscheduler;
m_env = BasicUsageEnvironment::createNew(*m_scheduler);
m_rtspClient = ourRTSPClient::createNew(*m_env, m_strRtspUrl.c_str(), RTSP_CLIENT_VERBOSITY_LEVEL,PROC_NAME);
if(m_scheduler==NULL || m_env==NULL || m_rtspClient==NULL)
{
Uninitialize();
return false;
}
ourRTSPClient *pOurRtspClient =(ourRTSPClient*)m_rtspClient;
pOurRtspClient->m_pStream =this;
m_rtspClient->sendDescribeCommand(continueAfterDESCRIBE);
m_cEventLoopWatchVariable =1;
while(m_cEventLoopWatchVariable)
{
m_Basicscheduler->SingleStep();
if(pOurRtspClient->m_nWaitFrameCnt < SERVER_OUTLINE_JUDGE_INTVAL)
{
continue;
}
if(Live555Restart()==false)
{
break;
}
else
{
pOurRtspClient =(ourRTSPClient*)m_rtspClient;
pOurRtspClient->m_pStream =this;
m_rtspClient->sendDescribeCommand(continueAfterDESCRIBE);
}
}
// release the resource
if (NULL != m_rtspClient)
{
Medium::close(m_rtspClient);
m_rtspClient = NULL;
}
if (NULL != m_env)
{
m_env->reclaim();
m_env = NULL;
}
if (NULL != m_scheduler)
{
delete m_scheduler;
m_scheduler = NULL;
}
return true;
}
为了支持连接多个摄像机,为每个摄像机连接分配一个task。task 任务开始前分配live555连接的所有资源,在任务中判断重连条件(一定时间内收不到视频数据),条件触发后调用live555Restart,然后发送Describe命令重起rtsp连接过程。从而支持对摄像机的断线重连。
3. 多连接支持。封装所有资源(task,内部资源)为CRtspStreamProtocol类。支持连接多摄像机视频数据。
class CRtspStreamProtocol: public CStreamProtocol,public CTimerUser,public CTask
{
public:
CRtspStreamProtocol();
virtual ~CRtspStreamProtocol();
public:
bool Initialize(int nBoardCardId,const char* rtspURL);
void Uninitialize();
bool OnRecvStreamProcess(unsigned char *pBuffer,unsigned int nLen);
bool Live555Restart();
void Clear();
protected:
virtual void OnTimerMessage(CTimer* pTimer);
virtual bool _RunTask();
private:
public:
BasicTaskScheduler0* m_Basicscheduler;
TaskScheduler* m_scheduler;
UsageEnvironment* m_env;
CTimer m_Timer;
RTSPClient* m_rtspClient;
int m_nBoardCardId;
std::string m_strRtspUrl;
char m_cEventLoopWatchVariable;
};
封装的软件经朋友环境测试可长时间稳定播放摄像机视频。
完整代码CSDN下载地址:http://download.csdn.net/download/lb811018/10263397