EasyRTSPClient 基於live555構建而成. 今天講講EasyRTSPClient的設計過程服務器
EasyRTSPClient,主要包括如下部分:
1. 建立live555對象, 鏈接相機和收流
2. 解析收到的視頻分辨率
3. 將SDP、音視頻流、分辨率及其它相關信息經過回調函數進行回調
4. 回調鏈接、斷線狀態
5. 根據參數執行是否重連markdown
網上不少介紹的都是使用testRTSPClient來作客戶端, 這個是沒有問題的,但有一點須要注意的是demo中的代碼,都是阻塞式的,以下:session
env->taskScheduler().doEventLoop(&eventLoopWatchVariable);
這樣就在主線程中阻塞了, 若是我須要它退出,該怎樣實現呢?
有兩種方法,目的是相同的,實現方式略有不一樣罷了:
1. 外部改變eventLoopWatchVariable的值爲1
2. 經過BasicTaskScheduler0::doEventLoop(char* watchVariable)的實現能夠看出, 這裏其實是進行一個無限循環. 當 watchVariable的值不爲0時就退出. 因此咱們能夠本身建立一個線程,在線程內部實現調用 pTaskScheduler0->SingleStep(0), 便可實現對該線程的自由控制; 至關於1個線程對應1路到攝像機的取流;ide
解析分辨率主要是sps_pps.h .c實現,是從VLC中提取出來的相關代碼, 可正常解析H264,H265的分辨率;函數
在Live555的continueAfterDESCRIBE的回調函數中, 解析出SDP信息進行回調
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) 工具
if (NULL != sdpDescription) { if (NULL != pClient) pClient->SetSDP(sdpDescription, (int)strlen(sdpDescription)); char *sprop_parameter_sets = strstr(sdpDescription, "sprop-parameter-sets="); if (NULL != sprop_parameter_sets) { AnalysisH264SPSPPS(pClient, sprop_parameter_sets+21); } else { sprop_parameter_sets = strstr(sdpDescription, "sprop-sps="); if (NULL != sprop_parameter_sets) { AnalysisH265SPSPPS(pClient, sprop_parameter_sets); } } //回調出媒體信息 MediaSubsessionIterator iter(*scs.session); MediaSubsession* subsession; while ((subsession = iter.next()) != NULL) { if (strcmp(subsession->mediumName(), "video") == 0) { if (strcmp(subsession->codecName(), "H264") == 0) { mediainfo.videoCodec = VIDEO_CODEC_H264; } else if (strcmp(subsession->codecName(), "H265") == 0) { mediainfo.videoCodec = VIDEO_CODEC_H265; } else if (strcmp(subsession->codecName(), "MP4V-ES") == 0) { mediainfo.videoCodec = VIDEO_CODEC_MPEG4; } else if (strcmp(subsession->codecName(), "JPEG") == 0) { mediainfo.videoCodec = VIDEO_CODEC_MJPEG; } mediainfo.videoFps = (float)subsession->videoFPS(); mediainfo.videoWidth = pClient->params.width; mediainfo.videoHeight = pClient->params.height; } if (strcmp(subsession->mediumName(), "audio") == 0) { } } if (NULL != clientObj && NULL !=clientObj->callback) { RTSPClientCallBack pRtspCallback = (RTSPClientCallBack )clientObj->callback; if (NULL != pRtspCallback) { pRtspCallback(clientObj->channelInfo.id, (int *)clientObj->userPtr, MEDIA_TYPE_CODEC_INFO, (char*)&mediainfo, NULL); } } }
斷線狀態的檢測, 這裏使用了一個時間對比的方式. 即用當前時間減去上一次獲取到音視頻流的時間,若是大於指定時長,則認爲斷線; oop
檢查重連參數,若是須要重連,則銷燬當前的全部對象,再建立新的對象, 繼續開始新的循環url
if (NULL != pClient->rtspClient) { Medium::close(pClient->rtspClient); pClient->rtspClient = NULL; } if (NULL != pClient->env) { pClient->env->reclaim(); pClient->env = NULL; } if (NULL != pClient->scheduler) { delete pClient->scheduler; pClient->scheduler = NULL; } if (NULL != pClient->auth) { delete pClient->auth; pClient->auth = NULL; } if (NULL == pClient->scheduler) pClient->scheduler = BasicTaskScheduler::createNew(); if (NULL == pClient->scheduler) break; if (NULL == pClient->env) pClient->env = BasicUsageEnvironment::createNew(*pClient->scheduler); if (NULL == pClient->env) break; if (NULL == pClient->rtspClient) pClient->rtspClient = LiveRTSPClient::createNew(*pClient->env, pClient->channelInfo.url, RTSP_CLIENT_VERBOSITY_LEVEL, RTSP_CLIENT_NAME, 0, (void *)pClient); if (NULL == pClient->rtspClient) break;
今天主要概述了EasyRTSPClient的設計流程, 下一篇將開始着重講解具體實現細節;線程
如下是我寫的基於live555的兩個應用:設計
EasyRTSPClient是一套很是穩定、易用、支持重連的RTSPClient工具,SDK形式提供,接口調用很是簡單,不再用像調用live555那樣處理整個RTSP OPTIONS/DESCRIBE/SETUP/PLAY的複雜流程,擔憂內存釋放的問題了,全平臺支持(包括Windows/Linux 32&64,ARM各平臺,Android,iOS),支持RTP Over TCP/UDP,支持斷線重連,連續維護與迭代超過5年,可以接入市面上99%以上的IPC,調用簡單且成熟穩定!
EasyIPCamera是一套很是穩定、易用、支持多種平臺(包括Windows/Linux 32&64,Android,ARM hisiv100/hisiv200/hisiv400等平臺)的RTSP Server組件,適用於IPCamera、內網RTSP服務等小型RTSP流媒體服務器,接口調用很是簡單成熟,無需關注RTSPServer中關於客戶端監聽接入、音視頻多路複用、RTSP具體流程、RTP打包與發送等相關問題,支持多種音視頻格式,不再用像調用live555 RTSPServer那樣處理整個RTSP OPTIONS/DESCRIBE/SETUP/PLAY/RTP/RTCP的複雜流程和擔憂內存釋放的問題了!
Copyright © EasyDarwin.org 2012-2017