1. 程式人生 > >使用Live555開源庫實現rtspclient

使用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