使用Live555开源库实现rtspclient

之前一个朋友遇到播放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



     

你可能感兴趣的:(音视频处理,物联网(NBIoT/Lora))