RTSP学习笔记(2)live555
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
RTSPClient
RTSPClient?是RTSP協(xié)議的客戶(hù)端實(shí)現(xiàn),用于發(fā)送RTSP請(qǐng)求命令
?
類(lèi)接口:
static RTSPClient* createNew()
用于外部創(chuàng)建RTSPClient實(shí)例的方法,將構(gòu)造方法進(jìn)行了隱藏(protect);
unsigned sendXXXXCommand()
發(fā)送RTSP請(qǐng)求,會(huì)傳入回調(diào)函數(shù)responseHandler;
responseHandler是類(lèi)內(nèi)部定義的一個(gè)函數(shù)指針,統(tǒng)一回調(diào)的格式
typedef void (responseHandler)(RTSPClient* rtspClient,?int resultCode, char* resultString);
int socketNum() const
返回用于連接的socket;
staticBoolean lookupByName(UsageEnvironment& env,char const* sourceName,
????? RTSPClient*& resultClient)
查找sourceName指定的RTSPClient
staticBoolean parseRTSPURL(UsageEnvironment& env, char const* url,
????? char*& username, char*& password,NetAddress& address, portNumBits& portNum, char const** urlSuffix =NULL)
解析輸入的RTSPURL,主要用于獲取服務(wù)器地址NetAddress& address和端口號(hào)portNumBits& portNum,還會(huì)返回urlSuffix的指針,標(biāo)識(shí)媒體名等信息;
voidsetUserAgentString(char const* userAgentName)
指定RTSP回應(yīng)消息中的"User-Agent: %s\r\n"字段,類(lèi)內(nèi)部保存了fUserAgentHeaderStr,會(huì)將其內(nèi)容替換為userAgentName;
charconst* url() const
返回初始請(qǐng)求服務(wù)器的url信息,即rtsp://…//...;就是parseRTSPURL中的URL,保存在fBaseURL中;
保護(hù)方法:
voidreset()
重置RTSPClient,1、關(guān)閉socket;2、重置responseBuffer的指示變量;3、清除分BaseURL等
voidsetBaseURL(char const* url)
設(shè)置請(qǐng)求的URL信息fBaseURL;
virtualunsigned sendRequest(RequestRecord* request)
發(fā)送請(qǐng)求,請(qǐng)求統(tǒng)一封裝在RequestRecord;
------------------------------------------------------------------------------------------------------------------------------------------------------
內(nèi)部類(lèi)
RequestRecord?公開(kāi)
該類(lèi)封裝了請(qǐng)求命令,只用來(lái)保存請(qǐng)求的信息,如命令名稱(chēng)、回調(diào)函數(shù)等;
RequestRecord(unsignedcseq, char const* commandName, responseHandler* handler,
MediaSession*session = NULL, MediaSubsession* subsession = NULL,
u_int32_t?????booleanFlags = 0,
doublestart = 0.0f, double end = -1.0f, float scale = 1.0f,
charconst* contentStr = NULL);
所有信息都在初始化時(shí)傳入,之后類(lèi)為每一個(gè)信息都提供了訪問(wèn)方法
RequestQueue?私有
該類(lèi)定義了RequestRecord的隊(duì)列,可以保存請(qǐng)求信息,還提供了一些工具方法如下
voidputAtHead(RequestRecord* request); // "request" must not be NULL
RequestRecord*findByCSeq(unsigned cseq);
---------------------------------------------------------------------------------------------------------------------------------------------------------
成員變量:
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
ServerMediaSession
?
ServerMediaSession是RTSPServer中用于表示一個(gè)媒體信息的類(lèi),內(nèi)部會(huì)包含該媒體需要的子媒體ServerMediaSubsession,例如一個(gè)MP4文件既有視頻也有音頻,那這個(gè)ServerMediaSession就需要包含表示視頻的subSession和音頻的subSession。
?
類(lèi)接口:
staticServerMediaSession* createNew(UsageEnvironment& env,
?????? char const* streamName = NULL,
?????? char const* info = NULL,
?????? char const* description = NULL,
?????? Boolean isSSM = False,
?????? char const* miscSDPLines = NULL);
外部創(chuàng)建ServerMediaSession實(shí)例的方法,在Live555中對(duì)類(lèi)的實(shí)例化大多采用了這種方式,在方法內(nèi)部調(diào)用類(lèi)的構(gòu)造函數(shù),還不知道這么做有什么用意,為什么不直接用構(gòu)造函數(shù)?
staticBoolean lookupByName(UsageEnvironment& env,
??????????????????????????? char const*mediumName,
???????????????????????????ServerMediaSession*& resultSession);
查找mediaName對(duì)應(yīng)的serverMediaSession,內(nèi)部是通過(guò)Medium::lookupByName(env, mediumName, medium)這個(gè)靜態(tài)方法實(shí)現(xiàn)的,什么時(shí)候添加的?
char*generateSDPDescription();
生成媒體的SDP信息,分配的字符串內(nèi)存由調(diào)用者負(fù)責(zé)釋放;
關(guān)鍵部分
for each serverMediaSubSession {subSesssion->sdpLines()};//?產(chǎn)生各個(gè)子媒體的sdp描述
char const* streamName() const;
返回fStreamName,媒體名
BooleanaddSubsession(ServerMediaSubsession* subsession);
添加subSession,在ServerMediaSession內(nèi)有頭尾subSession的指針,可以形成單列表,
fSubsessionsTail= subsession;
subsession->fParentSession= this;
subsession->fTrackNumber =++fSubsessionCounter;?//?增加count數(shù),并將其設(shè)置為subSession的trackNameber
unsignednumSubsessions() const
返回fSubsessionCounter,在該ServerMediaSession總subSession的數(shù)目
unsignedreferenceCount() const { return fReferenceCount; }
voidincrementReferenceCount() { ++fReferenceCount; }
voiddecrementReferenceCount() { if (fReferenceCount > 0) --fReferenceCount; }
Boolean& deleteWhenUnreferenced() {return fDeleteWhenUnreferenced; }?//?指示是否已經(jīng)沒(méi)有了引用而可以析構(gòu)了
void deleteAllSubsessions();?//移除所有subSession
?
保護(hù)方法:
ServerMediaSession(UsageEnvironment&env, char const* streamName,
???? char const* info, char const* description,
???? Boolean isSSM, char const* miscSDPLines);
構(gòu)造方法,主要初始化一些sdp需要的描述信息:fStreamName,fInfoSDPString,fDescriptionSDPString,fMiscSDPLines,fCreationTime
?
成員變量:
ServerMediaSubSession
?
ServerMediaSubSession是一個(gè)媒體流中表示子媒體的結(jié)構(gòu)
?
類(lèi)接口:
unsignedtrackNumber() const
返回表示該subSession的ID:fTrackNumber,這個(gè)值會(huì)在ServerMediaSession添加subSession時(shí)賦予;
charconst* trackId();
返回trackID字符串fTrackId:("track%d",fTrackNumber)
virtualchar const* sdpLines() = 0;
純虛函數(shù),需子類(lèi)具體實(shí)現(xiàn),返回sdp描述中的媒體信息,如
/*
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=4D4033;
sprop-parameter-sets=Z01AM5p0FidCAAADAAIAAAMAZR4wZUA=,aO48gA==
a=control:track1
*/
virtualvoid getStreamParameters(unsigned clientSessionId, // in
?? netAddressBits clientAddress, // in
?? Port const& clientRTPPort, // in
?? Port const& clientRTCPPort, // in
?? int tcpSocketNum, // in (-1 means use UDP,not TCP)
?? unsigned char rtpChannelId, // in (used ifTCP)
?? unsigned char rtcpChannelId, // in (used ifTCP)
?? netAddressBits& destinationAddress, //in out
?? u_int8_t& destinationTTL, // in out
?? Boolean& isMulticast, // out
?? Port& serverRTPPort, // out
?? Port& serverRTCPPort, // out
?? void*& streamToken // out
?? ) = 0;
純虛函數(shù),返回各種流參數(shù);
virtualvoid startStream(unsigned clientSessionId, void* streamToken,
?? TaskFunc* rtcpRRHandler,
?? void* rtcpRRHandlerClientData,
?? unsigned short& rtpSeqNum,
?? unsigned& rtpTimestamp,
?? ServerRequestAlternativeByteHandler*serverRequestAlternativeByteHandler,
?? void*serverRequestAlternativeByteHandlerClientData) = 0;
純虛函數(shù),啟動(dòng)流傳輸,即開(kāi)始播放;
///
下面這些函數(shù)都只定義了接口,沒(méi)有做具體實(shí)現(xiàn),子類(lèi)可以根據(jù)情況完成
virtualvoid pauseStream(unsigned clientSessionId, void* streamToken);
virtual void seekStream(unsigned clientSessionId, void* streamToken,double& seekNPT, double????streamDuration,u_int64_t& numBytes);
???? // This routine is used to seek byrelative (i.e., NPT) time.
???? // "streamDuration", if >0.0,specifies how much data to stream, past "seekNPT".? (If <=0.0, all remaining data isstreamed.)
???? // "numBytes" returns the size(in bytes) of the data to be streamed, or 0 if unknown or unlimited.
virtualvoid seekStream(unsigned clientSessionId, void* streamToken, char*&absStart, char*& absEnd);
???? // This routine is used to seek by'absolute' time.
???? // "absStart" should be a stringof the form "YYYYMMDDTHHMMSSZ" or"YYYYMMDDTHHMMSS.<frac>Z".
???? // "absEnd" should be eitherNULL (for no end time), or a string of the same form as "absStart".
???? // These strings may be modified in-place,or can be reassigned to a newly-allocated value (after delete[]ing theoriginal).
virtualvoid setStreamScale(unsigned clientSessionId, void* streamToken, float scale);
virtualFramedSource* getStreamSource(void* streamToken);
virtualvoid deleteStream(unsigned clientSessionId, void*& streamToken);
virtualvoid testScaleFactor(float& scale); // sets "scale" to the actualsupported scale
virtualfloat duration() const;
??? // returns 0 for an unbounded session (thedefault)
??? // returns > 0 for a bounded session
virtualvoid getAbsoluteTimeRange(char*& absStartTime, char*& absEndTime)const;
/
轉(zhuǎn)載于:https://my.oschina.net/seanx/blog/619623
總結(jié)
以上是生活随笔為你收集整理的RTSP学习笔记(2)live555的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CentOS 6.5 搭建NFS文件服务
- 下一篇: 我喜欢的JavaScript编程风格