Mercurial > mplayer.hg
comparison libmpdemux/demux_rtp.cpp @ 10054:1342075f81f0
Added SIP (IP telephony) client support. (This was already supported in the
LIVE.COM libraries, so updating the MPlayer code to support it required
only relatively minor changes.)
author | rsf |
---|---|
date | Sat, 03 May 2003 06:13:11 +0000 |
parents | fa45d335a43b |
children | c34185f47b62 |
comparison
equal
deleted
inserted
replaced
10053:8e84e8deb529 | 10054:1342075f81f0 |
---|---|
85 // A structure of RTP-specific state, kept so that we can cleanly | 85 // A structure of RTP-specific state, kept so that we can cleanly |
86 // reclaim it: | 86 // reclaim it: |
87 typedef struct RTPState { | 87 typedef struct RTPState { |
88 char const* sdpDescription; | 88 char const* sdpDescription; |
89 RTSPClient* rtspClient; | 89 RTSPClient* rtspClient; |
90 SIPClient* sipClient; | |
90 MediaSession* mediaSession; | 91 MediaSession* mediaSession; |
91 ReadBufferQueue* audioBufferQueue; | 92 ReadBufferQueue* audioBufferQueue; |
92 ReadBufferQueue* videoBufferQueue; | 93 ReadBufferQueue* videoBufferQueue; |
93 unsigned flags; | 94 unsigned flags; |
94 struct timeval firstSyncTime; | 95 struct timeval firstSyncTime; |
95 }; | 96 }; |
96 | 97 |
97 extern "C" char* network_username; | 98 extern "C" char* network_username; |
98 extern "C" char* network_password; | 99 extern "C" char* network_password; |
100 static char* openURL_rtsp(RTSPClient* client, char const* url) { | |
101 // If we were given a user name (and optional password), then use them: | |
102 if (network_username != NULL) { | |
103 char const* password = network_password == NULL ? "" : network_password; | |
104 return client->describeWithPassword(url, network_username, password); | |
105 } else { | |
106 return client->describeURL(url); | |
107 } | |
108 } | |
109 | |
110 static char* openURL_sip(SIPClient* client, char const* url) { | |
111 // If we were given a user name (and optional password), then use them: | |
112 if (network_username != NULL) { | |
113 char const* password = network_password == NULL ? "" : network_password; | |
114 return client->inviteWithPassword(url, network_username, password); | |
115 } else { | |
116 return client->invite(url); | |
117 } | |
118 } | |
119 | |
99 int rtspStreamOverTCP = 0; | 120 int rtspStreamOverTCP = 0; |
100 | 121 |
101 extern "C" void demux_open_rtp(demuxer_t* demuxer) { | 122 extern "C" void demux_open_rtp(demuxer_t* demuxer) { |
102 do { | 123 do { |
103 TaskScheduler* scheduler = BasicTaskScheduler::createNew(); | 124 TaskScheduler* scheduler = BasicTaskScheduler::createNew(); |
104 if (scheduler == NULL) break; | 125 if (scheduler == NULL) break; |
105 UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); | 126 UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler); |
106 if (env == NULL) break; | 127 if (env == NULL) break; |
107 | 128 |
108 RTSPClient* rtspClient = NULL; | 129 RTSPClient* rtspClient = NULL; |
130 SIPClient* sipClient = NULL; | |
109 | 131 |
110 if (demuxer == NULL || demuxer->stream == NULL) break; // shouldn't happen | 132 if (demuxer == NULL || demuxer->stream == NULL) break; // shouldn't happen |
111 demuxer->stream->eof = 0; // just in case | 133 demuxer->stream->eof = 0; // just in case |
112 | 134 |
113 // Look at the stream's 'priv' field to see if we were initiated | 135 // Look at the stream's 'priv' field to see if we were initiated |
114 // via a SDP description: | 136 // via a SDP description: |
115 char* sdpDescription = (char*)(demuxer->stream->priv); | 137 char* sdpDescription = (char*)(demuxer->stream->priv); |
116 if (sdpDescription == NULL) { | 138 if (sdpDescription == NULL) { |
117 // We weren't given a SDP description directly, so assume that | 139 // We weren't given a SDP description directly, so assume that |
118 // we were given a RTSP URL: | 140 // we were given a RTSP or SIP URL: |
141 char const* protocol = demuxer->stream->streaming_ctrl->url->protocol; | |
119 char const* url = demuxer->stream->streaming_ctrl->url->url; | 142 char const* url = demuxer->stream->streaming_ctrl->url->url; |
120 | |
121 extern int verbose; | 143 extern int verbose; |
122 rtspClient = RTSPClient::createNew(*env, verbose, "MPlayer"); | 144 if (strcmp(protocol, "rtsp") == 0) { |
123 if (rtspClient == NULL) { | 145 rtspClient = RTSPClient::createNew(*env, verbose, "MPlayer"); |
124 fprintf(stderr, "Failed to create RTSP client: %s\n", | 146 if (rtspClient == NULL) { |
125 env->getResultMsg()); | 147 fprintf(stderr, "Failed to create RTSP client: %s\n", |
126 break; | 148 env->getResultMsg()); |
149 break; | |
150 } | |
151 sdpDescription = openURL_rtsp(rtspClient, url); | |
152 } else { // SIP | |
153 unsigned char desiredAudioType = 0; // PCMU (use 3 for GSM) | |
154 sipClient = SIPClient::createNew(*env, desiredAudioType, NULL, | |
155 verbose, "MPlayer"); | |
156 if (sipClient == NULL) { | |
157 fprintf(stderr, "Failed to create SIP client: %s\n", | |
158 env->getResultMsg()); | |
159 break; | |
160 } | |
161 sipClient->setClientStartPortNum(8000); | |
162 sdpDescription = openURL_sip(sipClient, url); | |
127 } | 163 } |
128 | 164 |
129 // If we were given a user name (and optional password), then use them: | |
130 if (network_username != NULL) { | |
131 char const* password | |
132 = network_password == NULL ? "" : network_password; | |
133 sdpDescription | |
134 = rtspClient->describeWithPassword(url, network_username, password); | |
135 } else { | |
136 sdpDescription = rtspClient->describeURL(url); | |
137 } | |
138 if (sdpDescription == NULL) { | 165 if (sdpDescription == NULL) { |
139 fprintf(stderr, "Failed to get a SDP description from URL \"%s\": %s\n", | 166 fprintf(stderr, "Failed to get a SDP description from URL \"%s\": %s\n", |
140 url, env->getResultMsg()); | 167 url, env->getResultMsg()); |
141 break; | 168 break; |
142 } | 169 } |
150 // Create a 'RTPState' structure containing the state that we just created, | 177 // Create a 'RTPState' structure containing the state that we just created, |
151 // and store it in the demuxer's 'priv' field, for future reference: | 178 // and store it in the demuxer's 'priv' field, for future reference: |
152 RTPState* rtpState = new RTPState; | 179 RTPState* rtpState = new RTPState; |
153 rtpState->sdpDescription = sdpDescription; | 180 rtpState->sdpDescription = sdpDescription; |
154 rtpState->rtspClient = rtspClient; | 181 rtpState->rtspClient = rtspClient; |
182 rtpState->sipClient = sipClient; | |
155 rtpState->mediaSession = mediaSession; | 183 rtpState->mediaSession = mediaSession; |
156 rtpState->audioBufferQueue = rtpState->videoBufferQueue = NULL; | 184 rtpState->audioBufferQueue = rtpState->videoBufferQueue = NULL; |
157 rtpState->flags = 0; | 185 rtpState->flags = 0; |
158 rtpState->firstSyncTime.tv_sec = rtpState->firstSyncTime.tv_usec = 0; | 186 rtpState->firstSyncTime.tv_sec = rtpState->firstSyncTime.tv_usec = 0; |
159 demuxer->priv = rtpState; | 187 demuxer->priv = rtpState; |
199 } | 227 } |
200 | 228 |
201 if (rtspClient != NULL) { | 229 if (rtspClient != NULL) { |
202 // Issue a RTSP aggregate "PLAY" command on the whole session: | 230 // Issue a RTSP aggregate "PLAY" command on the whole session: |
203 if (!rtspClient->playMediaSession(*mediaSession)) break; | 231 if (!rtspClient->playMediaSession(*mediaSession)) break; |
232 } else if (sipClient != NULL) { | |
233 sipClient->sendACK(); // to start the stream flowing | |
204 } | 234 } |
205 | 235 |
206 // Now that the session is ready to be read, do additional | 236 // Now that the session is ready to be read, do additional |
207 // MPlayer codec-specific initialization on each subsession: | 237 // MPlayer codec-specific initialization on each subsession: |
208 iter.reset(); | 238 iter.reset(); |
317 dp->pts = 0; | 347 dp->pts = 0; |
318 bufferQueue->savePendingBuffer(dp); | 348 bufferQueue->savePendingBuffer(dp); |
319 return True; | 349 return True; |
320 } | 350 } |
321 | 351 |
322 static void teardownRTSPSession(RTPState* rtpState); // forward | 352 static void teardownRTSPorSIPSession(RTPState* rtpState); // forward |
323 | 353 |
324 extern "C" void demux_close_rtp(demuxer_t* demuxer) { | 354 extern "C" void demux_close_rtp(demuxer_t* demuxer) { |
325 // Reclaim all RTP-related state: | 355 // Reclaim all RTP-related state: |
326 | 356 |
327 // Get the RTP state that was stored in the demuxer's 'priv' field: | 357 // Get the RTP state that was stored in the demuxer's 'priv' field: |
328 RTPState* rtpState = (RTPState*)(demuxer->priv); | 358 RTPState* rtpState = (RTPState*)(demuxer->priv); |
329 if (rtpState == NULL) return; | 359 if (rtpState == NULL) return; |
330 | 360 |
331 teardownRTSPSession(rtpState); | 361 teardownRTSPorSIPSession(rtpState); |
332 | 362 |
333 UsageEnvironment* env = NULL; | 363 UsageEnvironment* env = NULL; |
334 TaskScheduler* scheduler = NULL; | 364 TaskScheduler* scheduler = NULL; |
335 if (rtpState->mediaSession != NULL) { | 365 if (rtpState->mediaSession != NULL) { |
336 env = &(rtpState->mediaSession->envir()); | 366 env = &(rtpState->mediaSession->envir()); |
337 scheduler = &(env->taskScheduler()); | 367 scheduler = &(env->taskScheduler()); |
338 } | 368 } |
339 Medium::close(rtpState->mediaSession); | 369 Medium::close(rtpState->mediaSession); |
340 Medium::close(rtpState->rtspClient); | 370 Medium::close(rtpState->rtspClient); |
371 Medium::close(rtpState->sipClient); | |
341 delete rtpState->audioBufferQueue; | 372 delete rtpState->audioBufferQueue; |
342 delete rtpState->videoBufferQueue; | 373 delete rtpState->videoBufferQueue; |
343 delete rtpState->sdpDescription; | 374 delete rtpState->sdpDescription; |
344 delete rtpState; | 375 delete rtpState; |
345 | 376 |
477 } | 508 } |
478 | 509 |
479 return dp; | 510 return dp; |
480 } | 511 } |
481 | 512 |
482 static void teardownRTSPSession(RTPState* rtpState) { | 513 static void teardownRTSPorSIPSession(RTPState* rtpState) { |
483 RTSPClient* rtspClient = rtpState->rtspClient; | |
484 MediaSession* mediaSession = rtpState->mediaSession; | 514 MediaSession* mediaSession = rtpState->mediaSession; |
485 if (rtspClient == NULL || mediaSession == NULL) return; | 515 if (mediaSession == NULL) return; |
486 | 516 if (rtpState->rtspClient != NULL) { |
487 MediaSubsessionIterator iter(*mediaSession); | 517 MediaSubsessionIterator iter(*mediaSession); |
488 MediaSubsession* subsession; | 518 MediaSubsession* subsession; |
489 | 519 |
490 while ((subsession = iter.next()) != NULL) { | 520 while ((subsession = iter.next()) != NULL) { |
491 rtspClient->teardownMediaSubsession(*subsession); | 521 rtpState->rtspClient->teardownMediaSubsession(*subsession); |
522 } | |
523 } else if (rtpState->sipClient != NULL) { | |
524 rtpState->sipClient->sendBYE(); | |
492 } | 525 } |
493 } | 526 } |
494 | 527 |
495 ////////// "ReadBuffer" and "ReadBufferQueue" implementation: | 528 ////////// "ReadBuffer" and "ReadBufferQueue" implementation: |
496 | 529 |