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 #ifdef SUPPORT_REAL_RTSP
00024 #include "../RealRTSP/include/RealRTSP.hh"
00025 #endif
00026 #include "GroupsockHelper.hh"
00027 #include <ctype.h>
00028
00030
00031 MediaSession* MediaSession::createNew(UsageEnvironment& env,
00032 char const* sdpDescription) {
00033 MediaSession* newSession = new MediaSession(env);
00034 if (newSession != NULL) {
00035 if (!newSession->initializeWithSDP(sdpDescription)) {
00036 delete newSession;
00037 return NULL;
00038 }
00039 }
00040
00041 return newSession;
00042 }
00043
00044 Boolean MediaSession::lookupByName(UsageEnvironment& env,
00045 char const* instanceName,
00046 MediaSession*& resultSession) {
00047 resultSession = NULL;
00048
00049 Medium* medium;
00050 if (!Medium::lookupByName(env, instanceName, medium)) return False;
00051
00052 if (!medium->isMediaSession()) {
00053 env.setResultMsg(instanceName, " is not a 'MediaSession' object");
00054 return False;
00055 }
00056
00057 resultSession = (MediaSession*)medium;
00058 return True;
00059 }
00060
00061 MediaSession::MediaSession(UsageEnvironment& env)
00062 : Medium(env),
00063 fSubsessionsHead(NULL), fSubsessionsTail(NULL),
00064 fConnectionEndpointName(NULL), fMaxPlayEndTime(0.0f),
00065 fScale(1.0f), fMediaSessionType(NULL), fSessionName(NULL), fSessionDescription(NULL) {
00066 #ifdef SUPPORT_REAL_RTSP
00067 RealInitSDPAttributes(this);
00068 #endif
00069 fSourceFilterAddr.s_addr = 0;
00070
00071
00072 const unsigned maxCNAMElen = 100;
00073 char CNAME[maxCNAMElen+1];
00074 #ifndef CRIS
00075 gethostname((char*)CNAME, maxCNAMElen);
00076 #else
00077
00078 sprintf(CNAME, "unknown host %d", (unsigned)(our_random()*0x7FFFFFFF));
00079 #endif
00080 CNAME[maxCNAMElen] = '\0';
00081 fCNAME = strDup(CNAME);
00082 }
00083
00084 MediaSession::~MediaSession() {
00085 delete fSubsessionsHead;
00086 delete[] fCNAME;
00087 delete[] fConnectionEndpointName;
00088 delete[] fMediaSessionType;
00089 delete[] fSessionName;
00090 delete[] fSessionDescription;
00091 #ifdef SUPPORT_REAL_RTSP
00092 RealReclaimSDPAttributes(this);
00093 #endif
00094 }
00095
00096 Boolean MediaSession::isMediaSession() const {
00097 return True;
00098 }
00099
00100 Boolean MediaSession::initializeWithSDP(char const* sdpDescription) {
00101 if (sdpDescription == NULL) return False;
00102
00103
00104 char const* sdpLine = sdpDescription;
00105 char const* nextSDPLine;
00106 while (1) {
00107 if (!parseSDPLine(sdpLine, nextSDPLine)) return False;
00108
00109
00110
00111 if (sdpLine[0] == 'm') break;
00112 sdpLine = nextSDPLine;
00113 if (sdpLine == NULL) break;
00114
00115
00116 if (parseSDPLine_s(sdpLine)) continue;
00117 if (parseSDPLine_i(sdpLine)) continue;
00118 if (parseSDPLine_c(sdpLine)) continue;
00119 if (parseSDPAttribute_range(sdpLine)) continue;
00120 if (parseSDPAttribute_type(sdpLine)) continue;
00121 if (parseSDPAttribute_source_filter(sdpLine)) continue;
00122 #ifdef SUPPORT_REAL_RTSP
00123 if (RealParseSDPAttributes(this, sdpLine)) continue;
00124 #endif
00125 }
00126
00127 while (sdpLine != NULL) {
00128
00129 MediaSubsession* subsession = new MediaSubsession(*this);
00130 if (subsession == NULL) {
00131 envir().setResultMsg("Unable to create new MediaSubsession");
00132 return False;
00133 }
00134
00135
00136
00137
00138 char* mediumName = strDupSize(sdpLine);
00139 char* protocolName = NULL;
00140 unsigned payloadFormat;
00141 if ((sscanf(sdpLine, "m=%s %hu RTP/AVP %u",
00142 mediumName, &subsession->fClientPortNum, &payloadFormat) == 3 ||
00143 sscanf(sdpLine, "m=%s %hu/%*u RTP/AVP %u",
00144 mediumName, &subsession->fClientPortNum, &payloadFormat) == 3)
00145 && payloadFormat <= 127) {
00146 protocolName = "RTP";
00147 } else if ((sscanf(sdpLine, "m=%s %hu UDP %u",
00148 mediumName, &subsession->fClientPortNum, &payloadFormat) == 3 ||
00149 sscanf(sdpLine, "m=%s %hu udp %u",
00150 mediumName, &subsession->fClientPortNum, &payloadFormat) == 3 ||
00151 sscanf(sdpLine, "m=%s %hu RAW/RAW/UDP %u",
00152 mediumName, &subsession->fClientPortNum, &payloadFormat) == 3)
00153 && payloadFormat <= 127) {
00154
00155 protocolName = "UDP";
00156 } else {
00157
00158 char* sdpLineStr;
00159 if (nextSDPLine == NULL) {
00160 sdpLineStr = (char*)sdpLine;
00161 } else {
00162 sdpLineStr = strDup(sdpLine);
00163 sdpLineStr[nextSDPLine-sdpLine] = '\0';
00164 }
00165 envir() << "Bad SDP \"m=\" line: " << sdpLineStr << "\n";
00166 if (sdpLineStr != (char*)sdpLine) delete[] sdpLineStr;
00167
00168 delete[] mediumName;
00169 delete subsession;
00170
00171
00172 while (1) {
00173 sdpLine = nextSDPLine;
00174 if (sdpLine == NULL) break;
00175 if (!parseSDPLine(sdpLine, nextSDPLine)) return False;
00176
00177 if (sdpLine[0] == 'm') break;
00178 }
00179 continue;
00180 }
00181
00182
00183 if (fSubsessionsTail == NULL) {
00184 fSubsessionsHead = fSubsessionsTail = subsession;
00185 } else {
00186 fSubsessionsTail->setNext(subsession);
00187 fSubsessionsTail = subsession;
00188 }
00189
00190 subsession->serverPortNum = subsession->fClientPortNum;
00191
00192 char const* mStart = sdpLine;
00193 subsession->fSavedSDPLines = strDup(mStart);
00194
00195 subsession->fMediumName = strDup(mediumName);
00196 delete[] mediumName;
00197 subsession->fProtocolName = strDup(protocolName);
00198 subsession->fRTPPayloadFormat = payloadFormat;
00199
00200
00201 while (1) {
00202 sdpLine = nextSDPLine;
00203 if (sdpLine == NULL) break;
00204 if (!parseSDPLine(sdpLine, nextSDPLine)) return False;
00205
00206 if (sdpLine[0] == 'm') break;
00207
00208
00209 if (subsession->parseSDPLine_c(sdpLine)) continue;
00210 if (subsession->parseSDPAttribute_rtpmap(sdpLine)) continue;
00211 if (subsession->parseSDPAttribute_control(sdpLine)) continue;
00212 if (subsession->parseSDPAttribute_range(sdpLine)) continue;
00213 if (subsession->parseSDPAttribute_fmtp(sdpLine)) continue;
00214 if (subsession->parseSDPAttribute_source_filter(sdpLine)) continue;
00215 if (subsession->parseSDPAttribute_x_mct_slap(sdpLine)) continue;
00216 if (subsession->parseSDPAttribute_x_dimensions(sdpLine)) continue;
00217 if (subsession->parseSDPAttribute_x_framerate(sdpLine)) continue;
00218 #ifdef SUPPORT_REAL_RTSP
00219 if (RealParseSDPAttributes(subsession, sdpLine)) continue;
00220 #endif
00221
00222
00223 }
00224 if (sdpLine != NULL) subsession->fSavedSDPLines[sdpLine-mStart] = '\0';
00225
00226
00227
00228 if (subsession->fCodecName == NULL) {
00229 subsession->fCodecName
00230 = lookupPayloadFormat(subsession->fRTPPayloadFormat,
00231 subsession->fRTPTimestampFrequency,
00232 subsession->fNumChannels);
00233 if (subsession->fCodecName == NULL) {
00234 char typeStr[20];
00235 sprintf(typeStr, "%d", subsession->fRTPPayloadFormat);
00236 envir().setResultMsg("Unknown codec name for RTP payload type ",
00237 typeStr);
00238 return False;
00239 }
00240 }
00241
00242
00243
00244
00245
00246 if (subsession->fRTPTimestampFrequency == 0) {
00247 subsession->fRTPTimestampFrequency
00248 = guessRTPTimestampFrequency(subsession->fMediumName,
00249 subsession->fCodecName);
00250 }
00251 }
00252
00253 return True;
00254 }
00255
00256 Boolean MediaSession::parseSDPLine(char const* inputLine,
00257 char const*& nextLine){
00258
00259 nextLine = NULL;
00260 for (char const* ptr = inputLine; *ptr != '\0'; ++ptr) {
00261 if (*ptr == '\r' || *ptr == '\n') {
00262
00263 ++ptr;
00264 while (*ptr == '\r' || *ptr == '\n') ++ptr;
00265 nextLine = ptr;
00266 if (nextLine[0] == '\0') nextLine = NULL;
00267 break;
00268 }
00269 }
00270
00271
00272
00273 if (inputLine[0] == '\r' || inputLine[0] == '\n') return True;
00274 if (strlen(inputLine) < 2 || inputLine[1] != '='
00275 || inputLine[0] < 'a' || inputLine[0] > 'z') {
00276 envir().setResultMsg("Invalid SDP line: ", inputLine);
00277 return False;
00278 }
00279
00280 return True;
00281 }
00282
00283 static char* parseCLine(char const* sdpLine) {
00284 char* resultStr = NULL;
00285 char* buffer = strDupSize(sdpLine);
00286 if (sscanf(sdpLine, "c=IN IP4 %[^/ ]", buffer) == 1) {
00287
00288 resultStr = strDup(buffer);
00289 }
00290 delete[] buffer;
00291
00292 return resultStr;
00293 }
00294
00295 Boolean MediaSession::parseSDPLine_s(char const* sdpLine) {
00296
00297 char* buffer = strDupSize(sdpLine);
00298 Boolean parseSuccess = False;
00299
00300 if (sscanf(sdpLine, "s=%[^\r\n]", buffer) == 1) {
00301 delete[] fSessionName; fSessionName = strDup(buffer);
00302 parseSuccess = True;
00303 }
00304 delete[] buffer;
00305
00306 return parseSuccess;
00307 }
00308
00309 Boolean MediaSession::parseSDPLine_i(char const* sdpLine) {
00310
00311 char* buffer = strDupSize(sdpLine);
00312 Boolean parseSuccess = False;
00313
00314 if (sscanf(sdpLine, "i=%[^\r\n]", buffer) == 1) {
00315 delete[] fSessionDescription; fSessionDescription = strDup(buffer);
00316 parseSuccess = True;
00317 }
00318 delete[] buffer;
00319
00320 return parseSuccess;
00321 }
00322
00323 Boolean MediaSession::parseSDPLine_c(char const* sdpLine) {
00324
00325
00326
00327 char* connectionEndpointName = parseCLine(sdpLine);
00328 if (connectionEndpointName != NULL) {
00329 delete[] fConnectionEndpointName;
00330 fConnectionEndpointName = connectionEndpointName;
00331 return True;
00332 }
00333
00334 return False;
00335 }
00336
00337 Boolean MediaSession::parseSDPAttribute_type(char const* sdpLine) {
00338
00339 Boolean parseSuccess = False;
00340
00341 char* buffer = strDupSize(sdpLine);
00342 if (sscanf(sdpLine, "a=type: %[^ ]", buffer) == 1) {
00343 delete[] fMediaSessionType;
00344 fMediaSessionType = strDup(buffer);
00345 parseSuccess = True;
00346 }
00347 delete[] buffer;
00348
00349 return parseSuccess;
00350 }
00351
00352 static Boolean parseRangeAttribute(char const* sdpLine, float& endTime) {
00353 return sscanf(sdpLine, "a=range: npt = %*g - %g", &endTime) == 1;
00354 }
00355
00356 Boolean MediaSession::parseSDPAttribute_range(char const* sdpLine) {
00357
00358
00359 Boolean parseSuccess = False;
00360
00361 float playEndTime;
00362 if (parseRangeAttribute(sdpLine, playEndTime)) {
00363 parseSuccess = True;
00364 if (playEndTime > fMaxPlayEndTime) {
00365 fMaxPlayEndTime = playEndTime;
00366 }
00367 }
00368
00369 return parseSuccess;
00370 }
00371
00372 static Boolean parseSourceFilterAttribute(char const* sdpLine,
00373 struct in_addr& sourceAddr) {
00374
00375
00376
00377
00378 Boolean result = False;
00379 char* sourceName = strDupSize(sdpLine);
00380 do {
00381 if (sscanf(sdpLine, "a=source-filter: incl IN IP4 %*s %s",
00382 sourceName) != 1) break;
00383
00384
00385 NetAddressList addresses(sourceName);
00386 if (addresses.numAddresses() == 0) break;
00387
00388 netAddressBits sourceAddrBits
00389 = *(netAddressBits*)(addresses.firstAddress()->data());
00390 if (sourceAddrBits == 0) break;
00391
00392 sourceAddr.s_addr = sourceAddrBits;
00393 result = True;
00394 } while (0);
00395
00396 delete[] sourceName;
00397 return result;
00398 }
00399
00400 Boolean MediaSession
00401 ::parseSDPAttribute_source_filter(char const* sdpLine) {
00402 return parseSourceFilterAttribute(sdpLine, fSourceFilterAddr);
00403 }
00404
00405 char* MediaSession::lookupPayloadFormat(unsigned char rtpPayloadType,
00406 unsigned& freq, unsigned& nCh) {
00407
00408
00409 char* temp = NULL;
00410 switch (rtpPayloadType) {
00411 case 0: {temp = "PCMU"; freq = 8000; nCh = 1; break;}
00412 case 2: {temp = "G726-32"; freq = 8000; nCh = 1; break;}
00413 case 3: {temp = "GSM"; freq = 8000; nCh = 1; break;}
00414 case 4: {temp = "G723"; freq = 8000; nCh = 1; break;}
00415 case 5: {temp = "DVI4"; freq = 8000; nCh = 1; break;}
00416 case 6: {temp = "DVI4"; freq = 16000; nCh = 1; break;}
00417 case 7: {temp = "LPC"; freq = 8000; nCh = 1; break;}
00418 case 8: {temp = "PCMA"; freq = 8000; nCh = 1; break;}
00419 case 9: {temp = "G722"; freq = 8000; nCh = 1; break;}
00420 case 10: {temp = "L16"; freq = 44100; nCh = 2; break;}
00421 case 11: {temp = "L16"; freq = 44100; nCh = 1; break;}
00422 case 12: {temp = "QCELP"; freq = 8000; nCh = 1; break;}
00423 case 14: {temp = "MPA"; freq = 90000; nCh = 1; break;}
00424
00425 case 15: {temp = "G728"; freq = 8000; nCh = 1; break;}
00426 case 16: {temp = "DVI4"; freq = 11025; nCh = 1; break;}
00427 case 17: {temp = "DVI4"; freq = 22050; nCh = 1; break;}
00428 case 18: {temp = "G729"; freq = 8000; nCh = 1; break;}
00429 case 25: {temp = "CELB"; freq = 90000; nCh = 1; break;}
00430 case 26: {temp = "JPEG"; freq = 90000; nCh = 1; break;}
00431 case 28: {temp = "NV"; freq = 90000; nCh = 1; break;}
00432 case 31: {temp = "H261"; freq = 90000; nCh = 1; break;}
00433 case 32: {temp = "MPV"; freq = 90000; nCh = 1; break;}
00434 case 33: {temp = "MP2T"; freq = 90000; nCh = 1; break;}
00435 case 34: {temp = "H263"; freq = 90000; nCh = 1; break;}
00436 };
00437
00438 return strDup(temp);
00439 }
00440
00441 unsigned MediaSession::guessRTPTimestampFrequency(char const* mediumName,
00442 char const* codecName) {
00443
00444
00445
00446
00447 if (strcmp(codecName, "L16") == 0) return 44100;
00448 if (strcmp(codecName, "MPA") == 0
00449 || strcmp(codecName, "MPA-ROBUST") == 0
00450 || strcmp(codecName, "X-MP3-DRAFT-00")) return 90000;
00451
00452
00453 if (strcmp(mediumName, "video") == 0) return 90000;
00454 return 8000;
00455 }
00456
00457 static unsigned computeSeqNumStagger(unsigned staggerSeconds) {
00458
00459
00460
00461
00462
00463 unsigned const samplesPerFrame = 1152;
00464 unsigned samplesPerSecond = 44100;
00465 double secondsPerFrame = (double)samplesPerFrame/samplesPerSecond;
00466 return (unsigned)(staggerSeconds/secondsPerFrame);
00467 }
00468
00469 Boolean MediaSession
00470 ::initiateByMediaType(char const* mimeType,
00471 MediaSubsession*& resultSubsession,
00472 PrioritizedRTPStreamSelector*& resultMultiSource,
00473 int& resultMultiSourceSessionId,
00474 int useSpecialRTPoffset) {
00475
00476 resultSubsession = NULL;
00477 resultMultiSource = NULL;
00478 resultMultiSourceSessionId = 0;
00479 unsigned maxStaggerSeconds = 0;
00480 MediaSubsessionIterator iter(*this);
00481 MediaSubsession* subsession;
00482 while ((subsession = iter.next()) != NULL) {
00483 if (resultMultiSourceSessionId != 0
00484 && subsession->mctSLAPSessionId() != resultMultiSourceSessionId) {
00485
00486
00487 continue;
00488 }
00489
00490 Boolean wasAlreadyInitiated = subsession->readSource() != NULL;
00491 if (!wasAlreadyInitiated) {
00492
00493 if (!subsession->initiate(useSpecialRTPoffset)) return False;
00494 }
00495
00496
00497 if (strcmp(subsession->readSource()->MIMEtype(), mimeType) != 0) {
00498 if (!wasAlreadyInitiated) subsession->deInitiate();
00499 continue;
00500 }
00501
00502 if (subsession->mctSLAPSessionId() == 0) {
00503
00504 resultSubsession = subsession;
00505 break;
00506 } else {
00507
00508 resultMultiSourceSessionId = subsession->mctSLAPSessionId();
00509 unsigned subsessionStaggerSeconds = subsession->mctSLAPStagger();
00510 if (subsessionStaggerSeconds > maxStaggerSeconds) {
00511 maxStaggerSeconds = subsessionStaggerSeconds;
00512 }
00513 }
00514 }
00515
00516 if (resultSubsession == NULL && resultMultiSourceSessionId == 0) {
00517 envir().setResultMsg("Session has no usable media subsession");
00518 return False;
00519 }
00520
00521 if (resultMultiSourceSessionId != 0) {
00522
00523 unsigned seqNumStagger = computeSeqNumStagger(maxStaggerSeconds);
00524 resultMultiSource
00525 = PrioritizedRTPStreamSelector::createNew(envir(), seqNumStagger);
00526 if (resultMultiSource == NULL) return False;
00527
00528
00529
00530 iter.reset();
00531 while ((subsession = iter.next()) != NULL) {
00532 if (subsession->mctSLAPSessionId() == resultMultiSourceSessionId) {
00533 resultMultiSource->addInputRTPStream(subsession->rtpSource(),
00534 subsession->rtcpInstance());
00535 }
00536 }
00537 }
00538
00539 return True;
00540 }
00541
00542
00544
00545 MediaSubsessionIterator::MediaSubsessionIterator(MediaSession& session)
00546 : fOurSession(session) {
00547 reset();
00548 }
00549
00550 MediaSubsessionIterator::~MediaSubsessionIterator() {
00551 }
00552
00553 MediaSubsession* MediaSubsessionIterator::next() {
00554 MediaSubsession* result = fNextPtr;
00555
00556 if (fNextPtr != NULL) fNextPtr = fNextPtr->fNext;
00557
00558 return result;
00559 }
00560
00561 void MediaSubsessionIterator::reset() {
00562 fNextPtr = fOurSession.fSubsessionsHead;
00563 }
00564
00566
00567 MediaSubsession::MediaSubsession(MediaSession& parent)
00568 : sessionId(NULL), serverPortNum(0), sink(NULL), miscPtr(NULL),
00569 fParent(parent), fNext(NULL),
00570 fConnectionEndpointName(NULL),
00571 fClientPortNum(0), fRTPPayloadFormat(0xFF),
00572 fSavedSDPLines(NULL), fMediumName(NULL), fCodecName(NULL), fProtocolName(NULL),
00573 fRTPTimestampFrequency(0), fControlPath(NULL),
00574 fSourceFilterAddr(parent.sourceFilterAddr()),
00575 fAuxiliarydatasizelength(0), fConstantduration(0), fConstantsize(0),
00576 fCRC(0), fCtsdeltalength(0), fDe_interleavebuffersize(0), fDtsdeltalength(0),
00577 fIndexdeltalength(0), fIndexlength(0), fInterleaving(0), fMaxdisplacement(0),
00578 fObjecttype(0), fOctetalign(0), fProfile_level_id(0), fRobustsorting(0),
00579 fSizelength(0), fStreamstateindication(0), fStreamtype(0),
00580 fCpresent(False), fRandomaccessindication(False),
00581 fConfig(NULL), fMode(NULL), fSpropParameterSets(NULL),
00582 fPlayEndTime(0.0),
00583 fMCT_SLAP_SessionId(0), fMCT_SLAP_Stagger(0),
00584 fVideoWidth(0), fVideoHeight(0), fVideoFPS(0), fNumChannels(1), fScale(1.0f),
00585 fRTPSocket(NULL), fRTCPSocket(NULL),
00586 fRTPSource(NULL), fRTCPInstance(NULL), fReadSource(NULL) {
00587 #ifdef SUPPORT_REAL_RTSP
00588 RealInitSDPAttributes(this);
00589 #endif
00590 }
00591
00592 MediaSubsession::~MediaSubsession() {
00593 deInitiate();
00594
00595 delete[] fConnectionEndpointName; delete[] fSavedSDPLines;
00596 delete[] fMediumName; delete[] fCodecName; delete[] fProtocolName;
00597 delete[] fControlPath; delete[] fConfig; delete[] fMode; delete[] fSpropParameterSets;
00598
00599 delete fNext;
00600 #ifdef SUPPORT_REAL_RTSP
00601 RealReclaimSDPAttributes(this);
00602 #endif
00603 }
00604
00605 float MediaSubsession::playEndTime() const {
00606 if (fPlayEndTime > 0) return fPlayEndTime;
00607
00608 return fParent.playEndTime();
00609 }
00610
00611 Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
00612 if (fReadSource != NULL) return True;
00613
00614 do {
00615 if (fCodecName == NULL) {
00616 env().setResultMsg("Codec is unspecified");
00617 break;
00618 }
00619
00620
00621
00622 Groupsock* oldGroupsock = NULL;
00623 Boolean success = False;
00624 struct in_addr tempAddr;
00625 tempAddr.s_addr = connectionEndpointAddress();
00626
00627 while (1) {
00628 unsigned short rtpPortNum = fClientPortNum&~1;
00629 if (isSSM()) {
00630 fRTPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr,
00631 rtpPortNum);
00632 } else {
00633 fRTPSocket = new Groupsock(env(), tempAddr, rtpPortNum, 255);
00634 }
00635 if (fRTPSocket == NULL) {
00636 env().setResultMsg("Failed to create RTP socket");
00637 break;
00638 }
00639
00640
00641 Port clientPort(0);
00642 if (!getSourcePort(env(), fRTPSocket->socketNum(), clientPort)) {
00643 break;
00644 }
00645 fClientPortNum = ntohs(clientPort.num());
00646
00647
00648 if ((fClientPortNum&1) == 0) {
00649 success = True;
00650 break;
00651 }
00652
00653 delete oldGroupsock;
00654 oldGroupsock = fRTPSocket;
00655 fClientPortNum = 0;
00656 }
00657 delete oldGroupsock;
00658 if (!success) break;
00659
00660
00661 unsigned short const rtcpPortNum = fClientPortNum|1;
00662 if (isSSM()) {
00663 fRTCPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr,
00664 rtcpPortNum);
00665
00666 if (fRTCPSocket != NULL) {
00667 fRTCPSocket->changeDestinationParameters(fSourceFilterAddr,0,~0);
00668 }
00669 } else {
00670 fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);
00671 }
00672 if (fRTCPSocket == NULL) {
00673 char tmpBuf[100];
00674 sprintf(tmpBuf, "Failed to create RTCP socket (port %d)",
00675 rtcpPortNum);
00676 env().setResultMsg(tmpBuf);
00677 break;
00678 }
00679
00680
00681 if (strcmp(fProtocolName, "UDP") == 0) {
00682
00683 fReadSource = BasicUDPSource::createNew(env(), fRTPSocket);
00684 fRTPSource = NULL;
00685
00686 if (strcmp(fCodecName, "MP2T") == 0) {
00687 fReadSource = MPEG2TransportStreamFramer::createNew(env(), fReadSource);
00688
00689 }
00690 } else {
00691
00692
00693
00694
00695 Boolean createSimpleRTPSource = False;
00696 Boolean doNormalMBitRule = False;
00697 if (strcmp(fCodecName, "QCELP") == 0) {
00698 fReadSource =
00699 QCELPAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,
00700 fRTPPayloadFormat,
00701 fRTPTimestampFrequency);
00702
00703 } else if (strcmp(fCodecName, "AMR") == 0) {
00704 fReadSource =
00705 AMRAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,
00706 fRTPPayloadFormat, 0 ,
00707 fNumChannels, fOctetalign, fInterleaving,
00708 fRobustsorting, fCRC);
00709
00710 } else if (strcmp(fCodecName, "AMR-WB") == 0) {
00711 fReadSource =
00712 AMRAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,
00713 fRTPPayloadFormat, 1 ,
00714 fNumChannels, fOctetalign, fInterleaving,
00715 fRobustsorting, fCRC);
00716
00717 } else if (strcmp(fCodecName, "MPA") == 0) {
00718 fReadSource = fRTPSource
00719 = MPEG1or2AudioRTPSource::createNew(env(), fRTPSocket,
00720 fRTPPayloadFormat,
00721 fRTPTimestampFrequency);
00722 } else if (strcmp(fCodecName, "MPA-ROBUST") == 0) {
00723 fRTPSource
00724 = MP3ADURTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,
00725 fRTPTimestampFrequency);
00726 if (fRTPSource == NULL) break;
00727
00728
00729 MP3ADUdeinterleaver* deinterleaver
00730 = MP3ADUdeinterleaver::createNew(env(), fRTPSource);
00731 if (deinterleaver == NULL) break;
00732
00733
00734 fReadSource = MP3FromADUSource::createNew(env(), deinterleaver);
00735 } else if (strcmp(fCodecName, "X-MP3-DRAFT-00") == 0) {
00736
00737
00738 fRTPSource
00739 = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,
00740 fRTPTimestampFrequency,
00741 "audio/MPA-ROBUST" );
00742 if (fRTPSource == NULL) break;
00743
00744
00745 fReadSource = MP3FromADUSource::createNew(env(), fRTPSource,
00746 False );
00747 } else if (strcmp(fCodecName, "MP4A-LATM") == 0) {
00748 fReadSource = fRTPSource
00749 = MPEG4LATMAudioRTPSource::createNew(env(), fRTPSocket,
00750 fRTPPayloadFormat,
00751 fRTPTimestampFrequency);
00752 } else if (strcmp(fCodecName, "AC3") == 0) {
00753 fReadSource = fRTPSource
00754 = AC3AudioRTPSource::createNew(env(), fRTPSocket,
00755 fRTPPayloadFormat,
00756 fRTPTimestampFrequency);
00757 } else if (strcmp(fCodecName, "MP4V-ES") == 0) {
00758 fReadSource = fRTPSource
00759 = MPEG4ESVideoRTPSource::createNew(env(), fRTPSocket,
00760 fRTPPayloadFormat,
00761 fRTPTimestampFrequency);
00762 } else if (strcmp(fCodecName, "MPEG4-GENERIC") == 0) {
00763 fReadSource = fRTPSource
00764 = MPEG4GenericRTPSource::createNew(env(), fRTPSocket,
00765 fRTPPayloadFormat,
00766 fRTPTimestampFrequency,
00767 fMediumName, fMode,
00768 fSizelength, fIndexlength,
00769 fIndexdeltalength);
00770 } else if (strcmp(fCodecName, "MPV") == 0) {
00771 fReadSource = fRTPSource
00772 = MPEG1or2VideoRTPSource::createNew(env(), fRTPSocket,
00773 fRTPPayloadFormat,
00774 fRTPTimestampFrequency);
00775 } else if (strcmp(fCodecName, "MP2T") == 0) {
00776 fRTPSource = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,
00777 fRTPTimestampFrequency, "video/MP2T",
00778 0, False);
00779 fReadSource = MPEG2TransportStreamFramer::createNew(env(), fRTPSource);
00780
00781 } else if (strcmp(fCodecName, "H261") == 0) {
00782 fReadSource = fRTPSource
00783 = H261VideoRTPSource::createNew(env(), fRTPSocket,
00784 fRTPPayloadFormat,
00785 fRTPTimestampFrequency);
00786 } else if (strcmp(fCodecName, "H263-1998") == 0 ||
00787 strcmp(fCodecName, "H263-2000") == 0) {
00788 fReadSource = fRTPSource
00789 = H263plusVideoRTPSource::createNew(env(), fRTPSocket,
00790 fRTPPayloadFormat,
00791 fRTPTimestampFrequency);
00792 } else if (strcmp(fCodecName, "H264") == 0) {
00793 fReadSource = fRTPSource
00794 = H264VideoRTPSource::createNew(env(), fRTPSocket,
00795 fRTPPayloadFormat,
00796 fRTPTimestampFrequency);
00797 } else if (strcmp(fCodecName, "JPEG") == 0) {
00798 fReadSource = fRTPSource
00799 = JPEGVideoRTPSource::createNew(env(), fRTPSocket,
00800 fRTPPayloadFormat,
00801 fRTPTimestampFrequency);
00802 } else if (strcmp(fCodecName, "X-QT") == 0
00803 || strcmp(fCodecName, "X-QUICKTIME") == 0) {
00804
00805
00806 char* mimeType
00807 = new char[strlen(mediumName()) + strlen(codecName()) + 2] ;
00808 sprintf(mimeType, "%s/%s", mediumName(), codecName());
00809 fReadSource = fRTPSource
00810 = QuickTimeGenericRTPSource::createNew(env(), fRTPSocket,
00811 fRTPPayloadFormat,
00812 fRTPTimestampFrequency,
00813 mimeType);
00814 delete[] mimeType;
00815 #ifdef SUPPORT_REAL_RTSP
00816 } else if (strcmp(fCodecName, "X-PN-REALAUDIO") == 0 ||
00817 strcmp(fCodecName, "X-PN-MULTIRATE-REALAUDIO-LIVE") == 0 ||
00818 strcmp(fCodecName, "X-PN-REALVIDEO") == 0 ||
00819 strcmp(fCodecName, "X-PN-MULTIRATE-REALVIDEO-LIVE") == 0) {
00820
00821 fReadSource = RealRDTSource::createNew(env());
00822 fRTPSource = NULL;
00823 parentSession().isRealNetworksRDT = True;
00824 #endif
00825 } else if ( strcmp(fCodecName, "PCMU") == 0
00826 || strcmp(fCodecName, "GSM") == 0
00827 || strcmp(fCodecName, "PCMA") == 0
00828 || strcmp(fCodecName, "L16") == 0
00829 || strcmp(fCodecName, "MP1S") == 0
00830 || strcmp(fCodecName, "MP2P") == 0
00831 || strcmp(fCodecName, "L8") == 0
00832 || strcmp(fCodecName, "G726-16") == 0
00833 || strcmp(fCodecName, "G726-24") == 0
00834 || strcmp(fCodecName, "G726-32") == 0
00835 || strcmp(fCodecName, "G726-40") == 0
00836 || strcmp(fCodecName, "SPEEX") == 0
00837 ) {
00838 createSimpleRTPSource = True;
00839 useSpecialRTPoffset = 0;
00840 } else if (useSpecialRTPoffset >= 0) {
00841
00842
00843 createSimpleRTPSource = True;
00844 } else {
00845 env().setResultMsg("RTP payload format unknown or not supported");
00846 break;
00847 }
00848
00849 if (createSimpleRTPSource) {
00850 char* mimeType
00851 = new char[strlen(mediumName()) + strlen(codecName()) + 2] ;
00852 sprintf(mimeType, "%s/%s", mediumName(), codecName());
00853 fReadSource = fRTPSource
00854 = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,
00855 fRTPTimestampFrequency, mimeType,
00856 (unsigned)useSpecialRTPoffset,
00857 doNormalMBitRule);
00858 delete[] mimeType;
00859 }
00860 }
00861
00862 if (fReadSource == NULL) {
00863 env().setResultMsg("Failed to create read source");
00864 break;
00865 }
00866
00867
00868 if (fRTPSource != NULL) {
00869 unsigned totSessionBandwidth = 500;
00870 fRTCPInstance = RTCPInstance::createNew(env(), fRTCPSocket,
00871 totSessionBandwidth,
00872 (unsigned char const*)
00873 fParent.CNAME(),
00874 NULL ,
00875 fRTPSource);
00876 if (fRTCPInstance == NULL) {
00877 env().setResultMsg("Failed to create RTCP instance");
00878 break;
00879 }
00880 }
00881
00882 return True;
00883 } while (0);
00884
00885 delete fRTPSocket; fRTPSocket = NULL;
00886 delete fRTCPSocket; fRTCPSocket = NULL;
00887 Medium::close(fRTCPInstance); fRTCPInstance = NULL;
00888 Medium::close(fReadSource); fReadSource = fRTPSource = NULL;
00889 fClientPortNum = 0;
00890 return False;
00891 }
00892
00893 void MediaSubsession::deInitiate() {
00894 Medium::close(fRTCPInstance);
00895 fRTCPInstance = NULL;
00896
00897 Medium::close(fReadSource);
00898 fReadSource = NULL; fRTPSource = NULL;
00899
00900 delete fRTCPSocket; delete fRTPSocket;
00901 fRTCPSocket = fRTPSocket = NULL;
00902 }
00903
00904 Boolean MediaSubsession::setClientPortNum(unsigned short portNum) {
00905 if (fReadSource != NULL) {
00906 env().setResultMsg("A read source has already been created");
00907 return False;
00908 }
00909
00910 fClientPortNum = portNum;
00911 return True;
00912 }
00913
00914 unsigned MediaSubsession::connectionEndpointAddress() const {
00915 do {
00916
00917 char const* endpointString = connectionEndpointName();
00918 if (endpointString == NULL) {
00919 endpointString = parentSession().connectionEndpointName();
00920 }
00921 if (endpointString == NULL) break;
00922
00923
00924 NetAddressList addresses(endpointString);
00925 if (addresses.numAddresses() == 0) break;
00926
00927 return *(unsigned*)(addresses.firstAddress()->data());
00928 } while (0);
00929
00930
00931 return 0;
00932 }
00933
00934 void MediaSubsession::setDestinations(unsigned defaultDestAddress) {
00935
00936
00937 unsigned destAddress = connectionEndpointAddress();
00938 if (destAddress == 0) destAddress = defaultDestAddress;
00939 struct in_addr destAddr; destAddr.s_addr = destAddress;
00940
00941
00942 int destTTL = ~0;
00943
00944 if (fRTPSocket != NULL) {
00945 Port destPort(serverPortNum);
00946 fRTPSocket->changeDestinationParameters(destAddr, destPort, destTTL);
00947 }
00948 if (fRTCPSocket != NULL && !isSSM()) {
00949
00950 Port destPort(serverPortNum+1);
00951 fRTCPSocket->
00952 changeDestinationParameters(destAddr, destPort, destTTL);
00953 }
00954 }
00955
00956 Boolean MediaSubsession::parseSDPLine_c(char const* sdpLine) {
00957
00958
00959
00960 char* connectionEndpointName = parseCLine(sdpLine);
00961 if (connectionEndpointName != NULL) {
00962 delete[] fConnectionEndpointName;
00963 fConnectionEndpointName = connectionEndpointName;
00964 return True;
00965 }
00966
00967 return False;
00968 }
00969
00970 Boolean MediaSubsession::parseSDPAttribute_rtpmap(char const* sdpLine) {
00971
00972
00973
00974 Boolean parseSuccess = False;
00975
00976 unsigned rtpmapPayloadFormat;
00977 char* codecName = strDupSize(sdpLine);
00978 unsigned rtpTimestampFrequency = 0;
00979 unsigned numChannels = 1;
00980 if (sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u/%u",
00981 &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency,
00982 &numChannels) == 4
00983 || sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u",
00984 &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency) == 3
00985 || sscanf(sdpLine, "a=rtpmap: %u %s",
00986 &rtpmapPayloadFormat, codecName) == 2) {
00987 parseSuccess = True;
00988 if (rtpmapPayloadFormat == fRTPPayloadFormat) {
00989
00990
00991
00992 for (char* p = codecName; *p != '\0'; ++p) {
00993 *p = toupper(*p);
00994 }
00995 delete[] fCodecName; fCodecName = strDup(codecName);
00996 fRTPTimestampFrequency = rtpTimestampFrequency;
00997 fNumChannels = numChannels;
00998 }
00999 }
01000 delete[] codecName;
01001
01002 return parseSuccess;
01003 }
01004
01005 Boolean MediaSubsession::parseSDPAttribute_control(char const* sdpLine) {
01006
01007 Boolean parseSuccess = False;
01008
01009 char* controlPath = strDupSize(sdpLine);
01010 if (sscanf(sdpLine, "a=control: %s", controlPath) == 1) {
01011 parseSuccess = True;
01012 delete[] fControlPath; fControlPath = strDup(controlPath);
01013 }
01014 delete[] controlPath;
01015
01016 return parseSuccess;
01017 }
01018
01019 Boolean MediaSubsession::parseSDPAttribute_range(char const* sdpLine) {
01020
01021
01022 Boolean parseSuccess = False;
01023
01024 float playEndTime;
01025 if (parseRangeAttribute(sdpLine, playEndTime)) {
01026 parseSuccess = True;
01027 if (playEndTime > fPlayEndTime) {
01028 fPlayEndTime = playEndTime;
01029 if (playEndTime > fParent.playEndTime()) {
01030 fParent.playEndTime() = playEndTime;
01031 }
01032 }
01033 }
01034
01035 return parseSuccess;
01036 }
01037
01038 Boolean MediaSubsession::parseSDPAttribute_fmtp(char const* sdpLine) {
01039
01040
01041
01042
01043 do {
01044 if (strncmp(sdpLine, "a=fmtp:", 7) != 0) break; sdpLine += 7;
01045 while (isdigit(*sdpLine)) ++sdpLine;
01046
01047
01048
01049
01050
01051 char* const lineCopy = strDup(sdpLine); char* line = lineCopy;
01052 for (char* c = line; *c != '\0'; ++c) *c = tolower(*c);
01053 while (*line != '\0' && *line != '\r' && *line != '\n') {
01054 unsigned u;
01055 char* valueStr = strDupSize(line);
01056 if (sscanf(line, " auxiliarydatasizelength = %u", &u) == 1) {
01057 fAuxiliarydatasizelength = u;
01058 } else if (sscanf(line, " constantduration = %u", &u) == 1) {
01059 fConstantduration = u;
01060 } else if (sscanf(line, " constantsize; = %u", &u) == 1) {
01061 fConstantsize = u;
01062 } else if (sscanf(line, " crc = %u", &u) == 1) {
01063 fCRC = u;
01064 } else if (sscanf(line, " ctsdeltalength = %u", &u) == 1) {
01065 fCtsdeltalength = u;
01066 } else if (sscanf(line, " de-interleavebuffersize = %u", &u) == 1) {
01067 fDe_interleavebuffersize = u;
01068 } else if (sscanf(line, " dtsdeltalength = %u", &u) == 1) {
01069 fDtsdeltalength = u;
01070 } else if (sscanf(line, " indexdeltalength = %u", &u) == 1) {
01071 fIndexdeltalength = u;
01072 } else if (sscanf(line, " indexlength = %u", &u) == 1) {
01073 fIndexlength = u;
01074 } else if (sscanf(line, " interleaving = %u", &u) == 1) {
01075 fInterleaving = u;
01076 } else if (sscanf(line, " maxdisplacement = %u", &u) == 1) {
01077 fMaxdisplacement = u;
01078 } else if (sscanf(line, " objecttype = %u", &u) == 1) {
01079 fObjecttype = u;
01080 } else if (sscanf(line, " octet-align = %u", &u) == 1) {
01081 fOctetalign = u;
01082 } else if (sscanf(line, " profile-level-id = %u", &u) == 1) {
01083 fProfile_level_id = u;
01084 } else if (sscanf(line, " robust-sorting = %u", &u) == 1) {
01085 fRobustsorting = u;
01086 } else if (sscanf(line, " sizelength = %u", &u) == 1) {
01087 fSizelength = u;
01088 } else if (sscanf(line, " streamstateindication = %u", &u) == 1) {
01089 fStreamstateindication = u;
01090 } else if (sscanf(line, " streamtype = %u", &u) == 1) {
01091 fStreamtype = u;
01092 } else if (sscanf(line, " cpresent = %u", &u) == 1) {
01093 fCpresent = u != 0;
01094 } else if (sscanf(line, " randomaccessindication = %u", &u) == 1) {
01095 fRandomaccessindication = u != 0;
01096 } else if (sscanf(line, " config = %[^; \t\r\n]", valueStr) == 1) {
01097 delete[] fConfig; fConfig = strDup(valueStr);
01098 } else if (sscanf(line, " mode = %[^; \t\r\n]", valueStr) == 1) {
01099 delete[] fMode; fMode = strDup(valueStr);
01100 } else if (sscanf(sdpLine, " sprop-parameter-sets = %[^; \t\r\n]", valueStr) == 1) {
01101
01102 delete[] fSpropParameterSets; fSpropParameterSets = strDup(valueStr);
01103 } else {
01104
01105
01106 if (sscanf(line, " %[^; \t\r\n]", valueStr) == 1) {
01107 if (strcmp(valueStr, "octet-align") == 0) {
01108 fOctetalign = 1;
01109 } else if (strcmp(valueStr, "cpresent") == 0) {
01110 fCpresent = True;
01111 } else if (strcmp(valueStr, "crc") == 0) {
01112 fCRC = 1;
01113 } else if (strcmp(valueStr, "robust-sorting") == 0) {
01114 fRobustsorting = 1;
01115 } else if (strcmp(valueStr, "randomaccessindication") == 0) {
01116 fRandomaccessindication = True;
01117 }
01118 }
01119 }
01120 delete[] valueStr;
01121
01122
01123 while (*line != '\0' && *line != '\r' && *line != '\n'
01124 && *line != ';') ++line;
01125 while (*line == ';') ++line;
01126
01127
01128 while (*sdpLine != '\0' && *sdpLine != '\r' && *sdpLine != '\n'
01129 && *sdpLine != ';') ++sdpLine;
01130 while (*sdpLine == ';') ++sdpLine;
01131 }
01132 delete[] lineCopy;
01133 return True;
01134 } while (0);
01135
01136 return False;
01137 }
01138
01139 Boolean MediaSubsession
01140 ::parseSDPAttribute_source_filter(char const* sdpLine) {
01141 return parseSourceFilterAttribute(sdpLine, fSourceFilterAddr);
01142 }
01143
01144 Boolean MediaSubsession::parseSDPAttribute_x_mct_slap(char const* sdpLine) {
01145
01146 Boolean parseSuccess = False;
01147
01148 int slapSessionId;
01149 int slapStagger;
01150 if (sscanf(sdpLine, "a=x-mct-slap: %d %d",
01151 &slapSessionId, &slapStagger) == 2) {
01152 parseSuccess = True;
01153 fMCT_SLAP_SessionId = slapSessionId;
01154 fMCT_SLAP_Stagger = (unsigned)slapStagger;
01155 }
01156
01157 return parseSuccess;
01158 }
01159
01160 Boolean MediaSubsession::parseSDPAttribute_x_dimensions(char const* sdpLine) {
01161
01162 Boolean parseSuccess = False;
01163
01164 int width, height;
01165 if (sscanf(sdpLine, "a=x-dimensions:%d,%d", &width, &height) == 2) {
01166 parseSuccess = True;
01167 fVideoWidth = (unsigned short)width;
01168 fVideoHeight = (unsigned short)height;
01169 }
01170
01171 return parseSuccess;
01172 }
01173
01174 Boolean MediaSubsession::parseSDPAttribute_x_framerate(char const* sdpLine) {
01175
01176 Boolean parseSuccess = False;
01177
01178 int rate;
01179 if (sscanf(sdpLine, "a=x-framerate:%d", &rate) == 1) {
01180 parseSuccess = True;
01181 fVideoFPS = (unsigned)rate;
01182 }
01183
01184 return parseSuccess;
01185 }