00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "liveMedia.hh"
00023 #include "RTSPCommon.hh"
00024 #include "GroupsockHelper.hh"
00025
00026 #ifndef MILLION
00027 #define MILLION 1000000
00028 #endif
00029
00030
00031
00032 class ProxyServerMediaSubsession: public OnDemandServerMediaSubsession {
00033 public:
00034 ProxyServerMediaSubsession(MediaSubsession& mediaSubsession);
00035 virtual ~ProxyServerMediaSubsession();
00036
00037 char const* codecName() const { return fClientMediaSubsession.codecName(); }
00038
00039 private:
00040 virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
00041 unsigned& estBitrate);
00042 virtual void closeStreamSource(FramedSource *inputSource);
00043 virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
00044 unsigned char rtpPayloadTypeIfDynamic,
00045 FramedSource* inputSource);
00046
00047 private:
00048 static void subsessionByeHandler(void* clientData);
00049 void subsessionByeHandler();
00050
00051 int verbosityLevel() const { return ((ProxyServerMediaSession*)fParentSession)->fVerbosityLevel; }
00052
00053 private:
00054 friend class ProxyRTSPClient;
00055 MediaSubsession& fClientMediaSubsession;
00056 ProxyServerMediaSubsession* fNext;
00057 Boolean fHaveSetupStream;
00058 };
00059
00060
00062
00063 UsageEnvironment& operator<<(UsageEnvironment& env, const ProxyServerMediaSession& psms) {
00064 return env << "ProxyServerMediaSession[\"" << psms.url() << "\"]";
00065 }
00066
00067 ProxyServerMediaSession* ProxyServerMediaSession
00068 ::createNew(UsageEnvironment& env, RTSPServer* ourRTSPServer,
00069 char const* inputStreamURL, char const* streamName,
00070 char const* username, char const* password, portNumBits tunnelOverHTTPPortNum, int verbosityLevel) {
00071 return new ProxyServerMediaSession(env, ourRTSPServer, inputStreamURL, streamName, username, password, tunnelOverHTTPPortNum, verbosityLevel);
00072 }
00073
00074
00075 ProxyServerMediaSession::ProxyServerMediaSession(UsageEnvironment& env, RTSPServer* ourRTSPServer,
00076 char const* inputStreamURL, char const* streamName,
00077 char const* username, char const* password,
00078 portNumBits tunnelOverHTTPPortNum, int verbosityLevel)
00079 : ServerMediaSession(env, streamName, NULL, NULL, False, NULL),
00080 describeCompletedFlag(0), fOurRTSPServer(ourRTSPServer), fClientMediaSession(NULL),
00081 fVerbosityLevel(verbosityLevel), fPresentationTimeSessionNormalizer(new PresentationTimeSessionNormalizer(envir())) {
00082
00083
00084 fProxyRTSPClient = createNewProxyRTSPClient(inputStreamURL, username, password,
00085 tunnelOverHTTPPortNum, verbosityLevel > 0 ? verbosityLevel-1 : verbosityLevel);
00086 ProxyRTSPClient::sendDESCRIBE(fProxyRTSPClient);
00087 }
00088
00089 ProxyServerMediaSession::~ProxyServerMediaSession() {
00090 if (fVerbosityLevel > 0) {
00091 envir() << *this << "::~ProxyServerMediaSession()\n";
00092 }
00093
00094
00095 if (fProxyRTSPClient != NULL) fProxyRTSPClient->sendTeardownCommand(*fClientMediaSession, NULL, fProxyRTSPClient->auth());
00096
00097
00098 Medium::close(fClientMediaSession);
00099 Medium::close(fProxyRTSPClient);
00100 delete fPresentationTimeSessionNormalizer;
00101 }
00102
00103 char const* ProxyServerMediaSession::url() const {
00104 return fProxyRTSPClient == NULL ? NULL : fProxyRTSPClient->url();
00105 }
00106
00107 ProxyRTSPClient* ProxyServerMediaSession
00108 ::createNewProxyRTSPClient(char const* rtspURL, char const* username, char const* password,
00109 portNumBits tunnelOverHTTPPortNum, int verbosityLevel){
00110
00111 return new ProxyRTSPClient(*this, rtspURL, username, password, tunnelOverHTTPPortNum, verbosityLevel);
00112 }
00113
00114 void ProxyServerMediaSession::continueAfterDESCRIBE(char const* sdpDescription) {
00115 describeCompletedFlag = 1;
00116
00117
00118
00119 do {
00120 fClientMediaSession = MediaSession::createNew(envir(), sdpDescription);
00121 if (fClientMediaSession == NULL) break;
00122
00123 MediaSubsessionIterator iter(*fClientMediaSession);
00124 for (MediaSubsession* mss = iter.next(); mss != NULL; mss = iter.next()) {
00125 ServerMediaSubsession* smss = new ProxyServerMediaSubsession(*mss);
00126 addSubsession(smss);
00127 if (fVerbosityLevel > 0) {
00128 envir() << *this << " added new \"ProxyServerMediaSubsession\" for "
00129 << mss->protocolName() << "/" << mss->mediumName() << "/" << mss->codecName() << " track\n";
00130 }
00131 }
00132 } while (0);
00133 }
00134
00135 void ProxyServerMediaSession::resetDESCRIBEState() {
00136
00137 if (fOurRTSPServer != NULL) {
00138
00139 fOurRTSPServer->closeAllClientSessionsForServerMediaSession(this);
00140 }
00141 deleteAllSubsessions();
00142
00143
00144 Medium::close(fClientMediaSession); fClientMediaSession = NULL;
00145 }
00146
00148
00149 static void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) {
00150 char const* res;
00151
00152 if (resultCode == 0) {
00153
00154 res = resultString;
00155 } else {
00156
00157 res = NULL;
00158 }
00159 ((ProxyRTSPClient*)rtspClient)->continueAfterDESCRIBE(res);
00160 delete[] resultString;
00161 }
00162
00163 static void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString) {
00164 if (resultCode == 0) {
00165 ((ProxyRTSPClient*)rtspClient)->continueAfterSETUP();
00166 }
00167 delete[] resultString;
00168 }
00169
00170 static void continueAfterOPTIONS(RTSPClient* rtspClient, int resultCode, char* resultString) {
00171 Boolean serverSupportsGetParameter = False;
00172 if (resultCode == 0) {
00173
00174 serverSupportsGetParameter = RTSPOptionIsSupported("GET_PARAMETER", resultString);
00175 }
00176 ((ProxyRTSPClient*)rtspClient)->continueAfterLivenessCommand(resultCode, serverSupportsGetParameter);
00177 delete[] resultString;
00178 }
00179
00180 #ifdef SEND_GET_PARAMETER_IF_SUPPORTED
00181 static void continueAfterGET_PARAMETER(RTSPClient* rtspClient, int resultCode, char* resultString) {
00182 ((ProxyRTSPClient*)rtspClient)->continueAfterLivenessCommand(resultCode, True);
00183 delete[] resultString;
00184 }
00185 #endif
00186
00187
00189
00190 UsageEnvironment& operator<<(UsageEnvironment& env, const ProxyRTSPClient& proxyRTSPClient) {
00191 return env << "ProxyRTSPClient[\"" << proxyRTSPClient.url() << "\"]";
00192 }
00193
00194 ProxyRTSPClient::ProxyRTSPClient(ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
00195 char const* username, char const* password, portNumBits tunnelOverHTTPPortNum, int verbosityLevel)
00196 : RTSPClient(ourServerMediaSession.envir(), rtspURL, verbosityLevel, "ProxyRTSPClient",
00197 tunnelOverHTTPPortNum == (portNumBits)(~0) ? 0 : tunnelOverHTTPPortNum),
00198 fOurServerMediaSession(ourServerMediaSession), fOurURL(strDup(rtspURL)), fStreamRTPOverTCP(tunnelOverHTTPPortNum != 0),
00199 fSetupQueueHead(NULL), fSetupQueueTail(NULL), fNumSetupsDone(0), fNextDESCRIBEDelay(1),
00200 fServerSupportsGetParameter(False), fLastCommandWasPLAY(False),
00201 fLivenessCommandTask(NULL), fDESCRIBECommandTask(NULL), fSubsessionTimerTask(NULL) {
00202 if (username != NULL && password != NULL) {
00203 fOurAuthenticator = new Authenticator(username, password);
00204 } else {
00205 fOurAuthenticator = NULL;
00206 }
00207 }
00208
00209 void ProxyRTSPClient::reset() {
00210 envir().taskScheduler().unscheduleDelayedTask(fLivenessCommandTask); fLivenessCommandTask = NULL;
00211 envir().taskScheduler().unscheduleDelayedTask(fDESCRIBECommandTask); fDESCRIBECommandTask = NULL;
00212 envir().taskScheduler().unscheduleDelayedTask(fSubsessionTimerTask); fSubsessionTimerTask = NULL;
00213
00214 fSetupQueueHead = fSetupQueueTail = NULL;
00215 fNumSetupsDone = 0;
00216 fNextDESCRIBEDelay = 1;
00217 fLastCommandWasPLAY = False;
00218
00219 RTSPClient::reset();
00220 }
00221
00222 ProxyRTSPClient::~ProxyRTSPClient() {
00223 reset();
00224
00225 delete fOurAuthenticator;
00226 delete[] fOurURL;
00227 }
00228
00229 void ProxyRTSPClient::continueAfterDESCRIBE(char const* sdpDescription) {
00230 if (sdpDescription != NULL) {
00231 fOurServerMediaSession.continueAfterDESCRIBE(sdpDescription);
00232
00233
00234
00235
00236
00237
00238 scheduleLivenessCommand();
00239 } else {
00240
00241
00242 scheduleDESCRIBECommand();
00243 }
00244 }
00245
00246 void ProxyRTSPClient::continueAfterLivenessCommand(int resultCode, Boolean serverSupportsGetParameter) {
00247 if (resultCode != 0) {
00248
00249
00250
00251
00252
00253 fServerSupportsGetParameter = False;
00254
00255 if (resultCode < 0) {
00256
00257
00258 if (fVerbosityLevel > 0) {
00259 envir() << *this << ": lost connection to server ('errno': " << -resultCode << "). Resetting...\n";
00260 }
00261 }
00262
00263 reset();
00264 fOurServerMediaSession.resetDESCRIBEState();
00265
00266 setBaseURL(fOurURL);
00267 sendDESCRIBE(this);
00268 return;
00269 }
00270
00271 fServerSupportsGetParameter = serverSupportsGetParameter;
00272
00273
00274 scheduleLivenessCommand();
00275 }
00276
00277 #define SUBSESSION_TIMEOUT_SECONDS 10 // how many seconds to wait for the last track's "SETUP" to be done (note below)
00278
00279 void ProxyRTSPClient::continueAfterSETUP() {
00280 if (fVerbosityLevel > 0) {
00281 envir() << *this << "::continueAfterSETUP(): head codec: " << fSetupQueueHead->fClientMediaSubsession.codecName()
00282 << "; numSubsessions " << fSetupQueueHead->fParentSession->numSubsessions() << "\n\tqueue:";
00283 for (ProxyServerMediaSubsession* p = fSetupQueueHead; p != NULL; p = p->fNext) {
00284 envir() << "\t" << p->fClientMediaSubsession.codecName();
00285 }
00286 envir() << "\n";
00287 }
00288 envir().taskScheduler().unscheduleDelayedTask(fSubsessionTimerTask);
00289
00290
00291 ProxyServerMediaSubsession* smss = fSetupQueueHead;
00292 fSetupQueueHead = fSetupQueueHead->fNext;
00293 if (fSetupQueueHead == NULL) fSetupQueueTail = NULL;
00294
00295 if (fSetupQueueHead != NULL) {
00296
00297
00298 sendSetupCommand(fSetupQueueHead->fClientMediaSubsession, ::continueAfterSETUP,
00299 False, fStreamRTPOverTCP, False, fOurAuthenticator);
00300 ++fNumSetupsDone;
00301 fSetupQueueHead->fHaveSetupStream = True;
00302 } else {
00303 if (fNumSetupsDone >= smss->fParentSession->numSubsessions()) {
00304
00305
00306 sendPlayCommand(smss->fClientMediaSubsession.parentSession(), NULL, -1.0f, -1.0f, 1.0f, fOurAuthenticator);
00307
00308
00309 fLastCommandWasPLAY = True;
00310 } else {
00311
00312
00313
00314
00315 fSubsessionTimerTask
00316 = envir().taskScheduler().scheduleDelayedTask(SUBSESSION_TIMEOUT_SECONDS*MILLION, (TaskFunc*)subsessionTimeout, this);
00317 }
00318 }
00319 }
00320
00321 void ProxyRTSPClient::scheduleLivenessCommand() {
00322
00323 unsigned delayMax = sessionTimeoutParameter();
00324 if (delayMax == 0) {
00325 delayMax = 60;
00326 }
00327
00328
00329 unsigned const dM5 = delayMax*500000;
00330 unsigned uSecondsToDelay = dM5 + (dM5*our_random())%dM5;
00331 fLivenessCommandTask = envir().taskScheduler().scheduleDelayedTask(uSecondsToDelay, sendLivenessCommand, this);
00332 }
00333
00334 void ProxyRTSPClient::sendLivenessCommand(void* clientData) {
00335 ProxyRTSPClient* rtspClient = (ProxyRTSPClient*)clientData;
00336
00337
00338
00339
00340 #ifdef SEND_GET_PARAMETER_IF_SUPPORTED
00341 MediaSession* sess = rtspClient->fOurServerMediaSession.fClientMediaSession;
00342
00343 if (rtspClient->fServerSupportsGetParameter && rtspClient->fNumSetupsDone > 0 && sess != NULL) {
00344 rtspClient->sendGetParameterCommand(*sess, ::continueAfterGET_PARAMETER, "", rtspClient->auth());
00345 } else {
00346 #endif
00347 rtspClient->sendOptionsCommand(::continueAfterOPTIONS, rtspClient->auth());
00348 #ifdef SEND_GET_PARAMETER_IF_SUPPORTED
00349 }
00350 #endif
00351 }
00352
00353 void ProxyRTSPClient::scheduleDESCRIBECommand() {
00354
00355 unsigned secondsToDelay;
00356 if (fNextDESCRIBEDelay <= 256) {
00357 secondsToDelay = fNextDESCRIBEDelay;
00358 fNextDESCRIBEDelay *= 2;
00359 } else {
00360 secondsToDelay = 256 + (our_random()&0xFF);
00361 }
00362
00363 if (fVerbosityLevel > 0) {
00364 envir() << *this << ": RTSP \"DESCRIBE\" command failed; trying again in " << secondsToDelay << " seconds\n";
00365 }
00366 fDESCRIBECommandTask = envir().taskScheduler().scheduleDelayedTask(secondsToDelay*MILLION, sendDESCRIBE, this);
00367 }
00368
00369 void ProxyRTSPClient::sendDESCRIBE(void* clientData) {
00370 ProxyRTSPClient* rtspClient = (ProxyRTSPClient*)clientData;
00371 if (rtspClient != NULL) rtspClient->sendDescribeCommand(::continueAfterDESCRIBE, rtspClient->auth());
00372 }
00373
00374 void ProxyRTSPClient::subsessionTimeout(void* clientData) {
00375 ((ProxyRTSPClient*)clientData)->handleSubsessionTimeout();
00376 }
00377
00378 void ProxyRTSPClient::handleSubsessionTimeout() {
00379
00380 MediaSession* sess = fOurServerMediaSession.fClientMediaSession;
00381 if (sess != NULL) sendPlayCommand(*sess, NULL, -1.0f, -1.0f, 1.0f, fOurAuthenticator);
00382 fLastCommandWasPLAY = True;
00383 }
00384
00385
00387
00388 ProxyServerMediaSubsession::ProxyServerMediaSubsession(MediaSubsession& mediaSubsession)
00389 : OnDemandServerMediaSubsession(mediaSubsession.parentSession().envir(), True),
00390 fClientMediaSubsession(mediaSubsession), fNext(NULL), fHaveSetupStream(False) {
00391 }
00392
00393 UsageEnvironment& operator<<(UsageEnvironment& env, const ProxyServerMediaSubsession& psmss) {
00394 return env << "ProxyServerMediaSubsession[\"" << psmss.codecName() << "\"]";
00395 }
00396
00397 ProxyServerMediaSubsession::~ProxyServerMediaSubsession() {
00398 if (verbosityLevel() > 0) {
00399 envir() << *this << "::~ProxyServerMediaSubsession()\n";
00400 }
00401 }
00402
00403 FramedSource* ProxyServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
00404 ProxyServerMediaSession* const sms = (ProxyServerMediaSession*)fParentSession;
00405
00406 if (verbosityLevel() > 0) {
00407 envir() << *this << "::createNewStreamSource(session id " << clientSessionId << ")\n";
00408 }
00409
00410
00411 if (fClientMediaSubsession.readSource() == NULL) {
00412 fClientMediaSubsession.receiveRawMP3ADUs();
00413 fClientMediaSubsession.receiveRawJPEGFrames();
00414 fClientMediaSubsession.initiate();
00415 if (verbosityLevel() > 0) {
00416 envir() << "\tInitiated: " << *this << "\n";
00417 }
00418
00419 if (fClientMediaSubsession.readSource() != NULL) {
00420
00421
00422 char const* const codecName = fClientMediaSubsession.codecName();
00423 FramedFilter* normalizerFilter = sms->fPresentationTimeSessionNormalizer
00424 ->createNewPresentationTimeSubsessionNormalizer(fClientMediaSubsession.readSource(), fClientMediaSubsession.rtpSource(),
00425 codecName);
00426 fClientMediaSubsession.addFilter(normalizerFilter);
00427
00428
00429 if (strcmp(codecName, "H264") == 0) {
00430 fClientMediaSubsession.addFilter(H264VideoStreamDiscreteFramer::createNew(envir(), fClientMediaSubsession.readSource()));
00431 } else if (strcmp(codecName, "MP4V-ES") == 0) {
00432 fClientMediaSubsession.addFilter(MPEG4VideoStreamDiscreteFramer
00433 ::createNew(envir(), fClientMediaSubsession.readSource(), True));
00434 } else if (strcmp(codecName, "MPV") == 0) {
00435 fClientMediaSubsession.addFilter(MPEG1or2VideoStreamDiscreteFramer::createNew(envir(), fClientMediaSubsession.readSource(),
00436 False, 5.0, True));
00437 } else if (strcmp(codecName, "DV") == 0) {
00438 fClientMediaSubsession.addFilter(DVVideoStreamFramer::createNew(envir(), fClientMediaSubsession.readSource(),
00439 False, True));
00440 }
00441 }
00442
00443 if (fClientMediaSubsession.rtcpInstance() != NULL) {
00444 fClientMediaSubsession.rtcpInstance()->setByeHandler(subsessionByeHandler, this);
00445 }
00446 }
00447
00448 ProxyRTSPClient* const proxyRTSPClient = sms->fProxyRTSPClient;
00449 if (clientSessionId != 0) {
00450
00451 if (!fHaveSetupStream) {
00452
00453
00454
00455 Boolean queueWasEmpty = proxyRTSPClient->fSetupQueueHead == NULL;
00456 if (queueWasEmpty) {
00457 proxyRTSPClient->fSetupQueueHead = this;
00458 } else {
00459 proxyRTSPClient->fSetupQueueTail->fNext = this;
00460 }
00461 proxyRTSPClient->fSetupQueueTail = this;
00462
00463
00464
00465 if (queueWasEmpty) {
00466 proxyRTSPClient->sendSetupCommand(fClientMediaSubsession, ::continueAfterSETUP,
00467 False, proxyRTSPClient->fStreamRTPOverTCP, False, proxyRTSPClient->auth());
00468 ++proxyRTSPClient->fNumSetupsDone;
00469 fHaveSetupStream = True;
00470 }
00471 } else {
00472
00473
00474
00475 if (!proxyRTSPClient->fLastCommandWasPLAY) {
00476 proxyRTSPClient->sendPlayCommand(fClientMediaSubsession.parentSession(), NULL, -1.0f,
00477 -1.0f, 1.0f, proxyRTSPClient->auth());
00478 proxyRTSPClient->fLastCommandWasPLAY = True;
00479 }
00480 }
00481 }
00482
00483 estBitrate = fClientMediaSubsession.bandwidth();
00484 if (estBitrate == 0) estBitrate = 50;
00485 return fClientMediaSubsession.readSource();
00486 }
00487
00488 void ProxyServerMediaSubsession::closeStreamSource(FramedSource* inputSource) {
00489 if (verbosityLevel() > 0) {
00490 envir() << *this << "::closeStreamSource()\n";
00491 }
00492
00493
00494
00495
00496 if (fHaveSetupStream) {
00497 ProxyServerMediaSession* const sms = (ProxyServerMediaSession*)fParentSession;
00498 ProxyRTSPClient* const proxyRTSPClient = sms->fProxyRTSPClient;
00499 if (proxyRTSPClient->fLastCommandWasPLAY) {
00500 proxyRTSPClient->sendPauseCommand(fClientMediaSubsession.parentSession(), NULL, proxyRTSPClient->auth());
00501 proxyRTSPClient->fLastCommandWasPLAY = False;
00502 }
00503 }
00504 }
00505
00506 RTPSink* ProxyServerMediaSubsession
00507 ::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource) {
00508 if (verbosityLevel() > 0) {
00509 envir() << *this << "::createNewRTPSink()\n";
00510 }
00511
00512
00513 RTPSink* newSink;
00514 char const* const codecName = fClientMediaSubsession.codecName();
00515 if (strcmp(codecName, "AC3") == 0 || strcmp(codecName, "EAC3") == 0) {
00516 newSink = AC3AudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00517 fClientMediaSubsession.rtpTimestampFrequency());
00518 #if 0 // This code does not work; do *not* enable it:
00519 } else if (strcmp(codecName, "AMR") == 0 || strcmp(codecName, "AMR-WB") == 0) {
00520 Boolean isWideband = strcmp(codecName, "AMR-WB") == 0;
00521 newSink = AMRAudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00522 isWideband, fClientMediaSubsession.numChannels());
00523 #endif
00524 } else if (strcmp(codecName, "DV") == 0) {
00525 newSink = DVVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
00526 } else if (strcmp(codecName, "GSM") == 0) {
00527 newSink = GSMAudioRTPSink::createNew(envir(), rtpGroupsock);
00528 } else if (strcmp(codecName, "H263-1998") == 0 || strcmp(codecName, "H263-2000") == 0) {
00529 newSink = H263plusVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00530 fClientMediaSubsession.rtpTimestampFrequency());
00531 } else if (strcmp(codecName, "H264") == 0) {
00532 newSink = H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00533 fClientMediaSubsession.fmtp_spropparametersets());
00534 } else if (strcmp(codecName, "JPEG") == 0) {
00535 newSink = SimpleRTPSink::createNew(envir(), rtpGroupsock, 26, 90000, "video", "JPEG",
00536 1, False, False);
00537 } else if (strcmp(codecName, "MP4A-LATM") == 0) {
00538 newSink = MPEG4LATMAudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00539 fClientMediaSubsession.rtpTimestampFrequency(),
00540 fClientMediaSubsession.fmtp_config(),
00541 fClientMediaSubsession.numChannels());
00542 } else if (strcmp(codecName, "MP4V-ES") == 0) {
00543 newSink = MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00544 fClientMediaSubsession.rtpTimestampFrequency(),
00545 fClientMediaSubsession.fmtp_profile_level_id(), fClientMediaSubsession.fmtp_config());
00546 } else if (strcmp(codecName, "MPA") == 0) {
00547 newSink = MPEG1or2AudioRTPSink::createNew(envir(), rtpGroupsock);
00548 } else if (strcmp(codecName, "MPA-ROBUST") == 0) {
00549 newSink = MP3ADURTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
00550 } else if (strcmp(codecName, "MPEG4-GENERIC") == 0) {
00551 newSink = MPEG4GenericRTPSink::createNew(envir(), rtpGroupsock,
00552 rtpPayloadTypeIfDynamic, fClientMediaSubsession.rtpTimestampFrequency(),
00553 fClientMediaSubsession.mediumName(), fClientMediaSubsession.fmtp_mode(),
00554 fClientMediaSubsession.fmtp_config(), fClientMediaSubsession.numChannels());
00555 } else if (strcmp(codecName, "MPV") == 0) {
00556 newSink = MPEG1or2VideoRTPSink::createNew(envir(), rtpGroupsock);
00557 } else if (strcmp(codecName, "T140") == 0) {
00558 newSink = T140TextRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
00559 } else if (strcmp(codecName, "VORBIS") == 0) {
00560 newSink = VorbisAudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
00561 fClientMediaSubsession.rtpTimestampFrequency(), fClientMediaSubsession.numChannels(),
00562 fClientMediaSubsession.fmtp_config());
00563 } else if (strcmp(codecName, "VP8") == 0) {
00564 newSink = VP8VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
00565 } else if (strcmp(codecName, "AMR") == 0 || strcmp(codecName, "AMR-WB") == 0) {
00566
00567
00568 if (verbosityLevel() > 0) {
00569 envir() << "\treturns NULL (because we currently don't support the proxying of \""
00570 << fClientMediaSubsession.mediumName() << "/" << codecName << "\" streams)\n";
00571 }
00572 return NULL;
00573 } else if (strcmp(codecName, "QCELP") == 0 ||
00574 strcmp(codecName, "H261") == 0 ||
00575 strcmp(codecName, "H263-1998") == 0 || strcmp(codecName, "H263-2000") == 0 ||
00576 strcmp(codecName, "X-QT") == 0 || strcmp(codecName, "X-QUICKTIME") == 0) {
00577
00578 if (verbosityLevel() > 0) {
00579 envir() << "\treturns NULL (because we don't have a \"RTPSink\" subclass for this RTP payload format)\n";
00580 }
00581 return NULL;
00582 } else {
00583
00584 Boolean allowMultipleFramesPerPacket = True;
00585 Boolean doNormalMBitRule = True;
00586
00587 if (strcmp(codecName, "MP2T") == 0) {
00588 doNormalMBitRule = False;
00589 }
00590 newSink = SimpleRTPSink::createNew(envir(), rtpGroupsock,
00591 rtpPayloadTypeIfDynamic, fClientMediaSubsession.rtpTimestampFrequency(),
00592 fClientMediaSubsession.mediumName(), fClientMediaSubsession.codecName(),
00593 fClientMediaSubsession.numChannels(), allowMultipleFramesPerPacket, doNormalMBitRule);
00594 }
00595
00596
00597
00598 newSink->enableRTCPReports() = False;
00599
00600
00601 PresentationTimeSubsessionNormalizer* ssNormalizer;
00602 if (strcmp(codecName, "H264") == 0 ||
00603 strcmp(codecName, "MP4V-ES") == 0 ||
00604 strcmp(codecName, "MPV") == 0 ||
00605 strcmp(codecName, "DV") == 0) {
00606
00607 ssNormalizer = (PresentationTimeSubsessionNormalizer*)(((FramedFilter*)inputSource)->inputSource());
00608 } else {
00609 ssNormalizer = (PresentationTimeSubsessionNormalizer*)inputSource;
00610 }
00611 ssNormalizer->setRTPSink(newSink);
00612
00613 return newSink;
00614 }
00615
00616 void ProxyServerMediaSubsession::subsessionByeHandler(void* clientData) {
00617 ((ProxyServerMediaSubsession*)clientData)->subsessionByeHandler();
00618 }
00619
00620 void ProxyServerMediaSubsession::subsessionByeHandler() {
00621 if (verbosityLevel() > 0) {
00622 envir() << *this << ": received RTCP \"BYE\"\n";
00623 }
00624
00625
00626 FramedSource::handleClosure(fClientMediaSubsession.readSource());
00627
00628
00629 fClientMediaSubsession.deInitiate();
00630 }
00631
00632
00634
00635
00636
00637 PresentationTimeSessionNormalizer::PresentationTimeSessionNormalizer(UsageEnvironment& env)
00638 : Medium(env),
00639 fSubsessionNormalizers(NULL), fMasterSSNormalizer(NULL) {
00640 }
00641
00642 PresentationTimeSessionNormalizer::~PresentationTimeSessionNormalizer() {
00643 while (fSubsessionNormalizers != NULL) {
00644 delete fSubsessionNormalizers;
00645 }
00646 }
00647
00648 PresentationTimeSubsessionNormalizer*
00649 PresentationTimeSessionNormalizer::createNewPresentationTimeSubsessionNormalizer(FramedSource* inputSource, RTPSource* rtpSource,
00650 char const* codecName) {
00651 fSubsessionNormalizers
00652 = new PresentationTimeSubsessionNormalizer(*this, inputSource, rtpSource, codecName, fSubsessionNormalizers);
00653 return fSubsessionNormalizers;
00654 }
00655
00656 void PresentationTimeSessionNormalizer::normalizePresentationTime(PresentationTimeSubsessionNormalizer* ssNormalizer,
00657 struct timeval& toPT, struct timeval const& fromPT) {
00658 Boolean const hasBeenSynced = ssNormalizer->fRTPSource->hasBeenSynchronizedUsingRTCP();
00659
00660 if (!hasBeenSynced) {
00661
00662
00663 toPT = fromPT;
00664 } else {
00665 if (fMasterSSNormalizer == NULL) {
00666
00667
00668
00669 fMasterSSNormalizer = ssNormalizer;
00670
00671 struct timeval timeNow;
00672 gettimeofday(&timeNow, NULL);
00673
00674
00675 fPTAdjustment.tv_sec = timeNow.tv_sec - fromPT.tv_sec;
00676 fPTAdjustment.tv_usec = timeNow.tv_usec - fromPT.tv_usec;
00677
00678 }
00679
00680
00681 toPT.tv_sec = fromPT.tv_sec + fPTAdjustment.tv_sec - 1;
00682 toPT.tv_usec = fromPT.tv_usec + fPTAdjustment.tv_usec + MILLION;
00683 while (toPT.tv_usec > MILLION) { ++toPT.tv_sec; toPT.tv_usec -= MILLION; }
00684
00685
00686 RTPSink* const rtpSink = ssNormalizer->fRTPSink;
00687 if (rtpSink != NULL) {
00688 rtpSink->enableRTCPReports() = True;
00689 }
00690 }
00691 }
00692
00693 void PresentationTimeSessionNormalizer
00694 ::removePresentationTimeSubsessionNormalizer(PresentationTimeSubsessionNormalizer* ssNormalizer) {
00695
00696 if (fSubsessionNormalizers == ssNormalizer) {
00697 fSubsessionNormalizers = fSubsessionNormalizers->fNext;
00698 } else {
00699 PresentationTimeSubsessionNormalizer** ssPtrPtr = &(fSubsessionNormalizers->fNext);
00700 while (*ssPtrPtr != ssNormalizer) ssPtrPtr = &((*ssPtrPtr)->fNext);
00701 *ssPtrPtr = (*ssPtrPtr)->fNext;
00702 }
00703 }
00704
00705
00706
00707 PresentationTimeSubsessionNormalizer
00708 ::PresentationTimeSubsessionNormalizer(PresentationTimeSessionNormalizer& parent, FramedSource* inputSource, RTPSource* rtpSource,
00709 char const* codecName, PresentationTimeSubsessionNormalizer* next)
00710 : FramedFilter(parent.envir(), inputSource),
00711 fParent(parent), fRTPSource(rtpSource), fRTPSink(NULL), fCodecName(codecName), fNext(next) {
00712 }
00713
00714 PresentationTimeSubsessionNormalizer::~PresentationTimeSubsessionNormalizer() {
00715 fParent.removePresentationTimeSubsessionNormalizer(this);
00716 }
00717
00718 void PresentationTimeSubsessionNormalizer::afterGettingFrame(void* clientData, unsigned frameSize,
00719 unsigned numTruncatedBytes,
00720 struct timeval presentationTime,
00721 unsigned durationInMicroseconds) {
00722 ((PresentationTimeSubsessionNormalizer*)clientData)
00723 ->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
00724 }
00725
00726 void PresentationTimeSubsessionNormalizer::afterGettingFrame(unsigned frameSize,
00727 unsigned numTruncatedBytes,
00728 struct timeval presentationTime,
00729 unsigned durationInMicroseconds) {
00730
00731 fFrameSize = frameSize;
00732 fNumTruncatedBytes = numTruncatedBytes;
00733 fDurationInMicroseconds = durationInMicroseconds;
00734
00735 fParent.normalizePresentationTime(this, fPresentationTime, presentationTime);
00736
00737
00738
00739 if (fRTPSource->curPacketMarkerBit() && strcmp(fCodecName, "JPEG") == 0) ((SimpleRTPSink*)fRTPSink)->setMBitOnNextPacket();
00740
00741
00742 FramedSource::afterGetting(this);
00743 }
00744
00745 void PresentationTimeSubsessionNormalizer::doGetNextFrame() {
00746 fInputSource->getNextFrame(fTo, fMaxSize, afterGettingFrame, this, FramedSource::handleClosure, this);
00747 }