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