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