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