Openrtsp Analysis 3

Source: Internet
Author: User

Next, I will analyze it in the previous article. If the option command is complete

unsigned RTSPClient::sendDescribeCommand(responseHandler* responseHandler, Authenticator* authenticator) {  if (authenticator != NULL) fCurrentAuthenticator = *authenticator;  return sendRequest(new RequestRecord(++fCSeq, "DESCRIBE", responseHandler));}

The basic process has been analyzed in the previous article. In sendrequest, The DESCRIBE request assembly is sent, and siglesetup continues to run. Because read has been added to the select listener, it will be added to handleresponsebytes. In handleresponsebytes, no special processing is performed on the describe response, and then the continueafterdescribe is executed.

In continueafterdescribe, we can see session = mediasession: createnew (* ENV, sdpdescription );

The session is assembled Based on the sdpdescription of the response.

MediaSession* MediaSession::createNew(UsageEnvironment& env,      char const* sdpDescription) {  MediaSession* newSession = new MediaSession(env);  if (newSession != NULL) {    if (!newSession->initializeWithSDP(sdpDescription)) {      delete newSession;      return NULL;    }  }  return newSession;}

Initializewithsdp creates a session based on sdp.

However, we didn't see the establishment process of RTP socket. However, in continueafterdescribe, we saw subsession-> initiate (simplertpoffsetarg)

Boolean mediasubsession: Initiate (INT usespecialrtpoffset) {If (freadsource! = NULL) return true; // has already been initiated do {If (fcodecname = NULL) {ENV (). setresultmsg ("codec is unspecified"); break;} // create RTP and RTCP 'grouplocks' on which to receive incoming data. // (groupsocks will work even for unicast addresses) struct in_addr tempaddr; tempaddr. s_addr = connectionendpointaddress (); // This cocould get changed later, as a result of a RTSP "setup" If (FCL Ientportnum! = 0) {// The sockets 'port numbers were specified for us. use these: Boolean const protocolisrtp = strcmp (fprotocolname, "RTP") = 0; If (protocolisrtp) {fclientportnum = fclientportnum &~ 1; // use an even-numbered port for RTP, And the next (odd-numbered) port for rtcp} If (isssm ()) {frtpsocket = new groupsock (ENV (), tempaddr, fsourcefilteraddr, fclientportnum);} else {frtpsocket = new groupsock (ENV (), tempaddr, fclientportnum, 255 ); // create rtpsocket} If (frtpsocket = NULL) {ENV (). setresultmsg ("failed to create RTP socket"); break;} If (protocolisrtp) {// set our RTCP port to be th E rtp Port + 1 portnumbits const rtcpportnum = fclientportnum | 1; if (isssm () {frtcpsocket = new groupsock (ENV (), tempaddr, fsourcefilteraddr, rtcpportnum );} else {frtcpsocket = new groupsock (ENV (), tempaddr, rtcpportnum, 255) ;}} else {// port numbers were not specified in advance, so we use ephemeral port numbers. // create sockets until we get a port-number pair (even: RTP; even + 1: RTCP ). // We need to make sure that we don't keep trying to use the same bad port numbers over and over again. // so we store bad sockets in a table, and delete them all when we re done. hashtable * sockethashtable = hashtable: Create (one_word_hash_keys); If (sockethashtable = NULL) break; Boolean success = false; noreuse dummy (ENV ()); // ensures that our new ephemeral port number won't be one that's alread Y in use while (1) {// create a new socket: If (isssm () {frtpsocket = new groupsock (ENV (), tempaddr, fsourcefilteraddr, 0 );} else {frtpsocket = new groupsock (ENV (), tempaddr, 0,255);} If (frtpsocket = NULL) {ENV (). setresultmsg ("mediasession: Initiate (): Unable to create RTP and RTCP sockets"); break;} // get the client port number, and check whether it's even (for RTP): Port clientport (0); If (! Getsourceport (ENV (), frtpsocket-> socketnum (), clientport) {break;} fclientportnum = ntohs (clientport. Num (); If (fclientportnum & 1 )! = 0) {// It's odd // record this socket in our table, and keep trying: Unsigned key = (unsigned) fclientportnum; groupsock * Existing = (groupsock *) sockethashtable-> Add (char const *) Key, frtpsocket); Delete existing; // in case it wasn't null continue ;} // make sure we can use the next (I. E ., odd) port number, for RTCP: portnumbits rtcpportnum = fclientportnum | 1; if (isssm () {frtcpsocket = new groups Ock (ENV (), tempaddr, fsourcefilteraddr, rtcpportnum);} else {frtcpsocket = new groupsock (ENV (), tempaddr, rtcpportnum, 255);} If (frtcpsocket! = NULL & frtcpsocket-> socketnum ()> = 0) {// success! Use these two sockets. Success = true; break;} else {// We couldn't create the RTCP socket (perhaps that port number's already in use elsewhere ?). Delete frtcpsocket; // record the first socket in our table, and keep trying: Unsigned key = (unsigned) fclientportnum; groupsock * Existing = (groupsock *) sockethashtable-> Add (char const *) Key, frtpsocket); Delete existing; // in case it wasn't null continue ;}} // clean up the socket hash table (and contents): groupsock * oldgs; while (oldgs = (groupsock *) sockethashtable-> removenext ())! = NULL) {Delete oldgs;} Delete sockethashtable; If (! Success) break; // a fatal error occurred trying to create the RTP and RTCP sockets; we can't continue} // try to use a big receive buffer for RTP-at least 0.1 second of // specified bandwidth and at least 50 kb unsigned rtpbufsize = fbandwidth * 25/2; // 1 kbps * 0.1 s = 12.5 bytes if (rtpbufsize <50*1024) rtpbufsize = 50*1024; increasereceivebufferto (ENV (), frtpsocket-> socketnum (), rtpb Ufsize); If (isssm () & frtcpsocket! = NULL) {// special case for rtcp ssm: Send RTCP packets back to the source via unicast: frtcpsocket-> changedestinationparameters (fsourcefilteraddr, 0 ,~ 0);} // create "frtpsource" and "freadsource": If (! Createsourceobjects (usespecialrtpoffset) break; If (freadsource = NULL) {ENV (). setresultmsg ("failed to create read source"); break;} // Finally, create our RTCP instance. (It starts running automatically) if (frtpsource! = NULL & frtcpsocket! = NULL) {// If bandwidth is specified, use it and add 5% for RTCP overhead. // otherwise make a guess at 500 kbps. Unsigned totsessionbandwidth = fbandwidth? Fbandwidth + fbandwidth/20: 500; frtcpinstance = rtcpinstance: createnew (ENV (), frtcpsocket, totsessionbandwidth, (unsigned char const *) fparent. cname (), null/* We're a client */, frtpsource); If (frtcpinstance = NULL) {ENV (). setresultmsg ("failed to create RTCP instance"); break ;}return true ;}while (0); Delete frtpsocket; frtpsocket = NULL; Delete frtcpsocket; frtcpsocket = NULL; medium:: Close (frtcpinstance); frtcpinstance = NULL; medium: Close (freadsource); freadsource = frtpsource = NULL; fclientportnum = 0; return false ;}

Here we mainly establish RTP socket,

Too many codes are not listed one by one, mainly analyzing the process and clues. The fclientportnum here is 0, so execute frtpsocket = new groupsock (ENV (), tempaddr, 0,255 );

Fsocketnum value: int newsocket = createsocket (sock_dgram );

After the RTP socket is created, the frtcpinstance is created. Then, rtpsource is created, in createsourceobjects (usespecialrtpoffset ).

Create rtpsource Based on fcodecname. Here we use h264 as an example.

fReadSource = fRTPSource  = H264VideoRTPSource::createNew(env(), fRTPSocket,  fRTPPayloadFormat,  fRTPTimestampFrequency);

So far, the important work in continueafterdescribe has been completed, and I will continue to look at it. Then execute setupstreams, in which the following code is executed.

static MediaSubsessionIterator* setupIter = NULL;  if (setupIter == NULL) setupIter = new MediaSubsessionIterator(*session);  while ((subsession = setupIter->next()) != NULL) {    // We have another subsession left to set up:    if (subsession->clientPortNum() == 0) continue; // port # was not set    setupSubsession(subsession, streamUsingTCP, continueAfterSETUP);    return;  }

Sendsetupcommand (* subsession, afterfunc, false, streamusingtcp, forcemulticastonunspecified, ourauthenticator );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.