📄 mediasession.cpp
字号:
fReadSource = fRTPSource = QuickTimeGenericRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat, fRTPTimestampFrequency, mimeType); delete[] mimeType; } else if (strcmp(fCodecName, "X-MCT-TEXT") == 0) { // A UDP-packetized text stream (*not* a RTP stream) fReadSource = BasicUDPSource::createNew(env(), fRTPSocket); fRTPSource = NULL; // Note!#ifdef SUPPORT_REAL_RTSP } else if (strcmp(fCodecName, "X-PN-REALAUDIO") == 0 || strcmp(fCodecName, "X-PN-MULTIRATE-REALAUDIO-LIVE") == 0 || strcmp(fCodecName, "X-PN-REALVIDEO") == 0 || strcmp(fCodecName, "X-PN-MULTIRATE-REALVIDEO-LIVE") == 0) { // A RealNetworks 'RDT' stream (*not* a RTP stream) fReadSource = RealRDTSource::createNew(env()); fRTPSource = NULL; // Note! parentSession().isRealNetworksRDT = True;#endif } else if ( strcmp(fCodecName, "PCMU") == 0 // PCM u-law audio || strcmp(fCodecName, "GSM") == 0 // GSM audio || strcmp(fCodecName, "PCMA") == 0 // PCM a-law audio || strcmp(fCodecName, "L16") == 0 // 16-bit linear audio || strcmp(fCodecName, "MP1S") == 0 // MPEG-1 System Stream || strcmp(fCodecName, "MP2P") == 0 // MPEG-2 Program Stream || strcmp(fCodecName, "L8") == 0 // 8-bit linear audio || strcmp(fCodecName, "SPEEX") == 0 // SPEEX audio ) { createSimpleRTPSource = True; useSpecialRTPoffset = 0; } else if (useSpecialRTPoffset >= 0) { // We don't know this RTP payload format, but try to receive // it using a 'SimpleRTPSource' with the specified header offset: createSimpleRTPSource = True; } else { env().setResultMsg("RTP payload format unknown or not supported"); break; } if (createSimpleRTPSource) { char* mimeType = new char[strlen(mediumName()) + strlen(codecName()) + 2] ; sprintf(mimeType, "%s/%s", mediumName(), codecName()); fReadSource = fRTPSource = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat, fRTPTimestampFrequency, mimeType, (unsigned)useSpecialRTPoffset, doNormalMBitRule); delete[] mimeType; } } if (fReadSource == NULL) { env().setResultMsg("Failed to create read source"); break; } // Finally, create our RTCP instance. (It starts running automatically) if (fRTPSource != NULL) { unsigned totSessionBandwidth = 500; // HACK - later get from SDP##### fRTCPInstance = RTCPInstance::createNew(env(), fRTCPSocket, totSessionBandwidth, (unsigned char const*) fParent.CNAME(), NULL /* we're a client */, fRTPSource); if (fRTCPInstance == NULL) { env().setResultMsg("Failed to create RTCP instance"); break; } } return True; } while (0); delete fRTPSocket; fRTPSocket = NULL; delete fRTCPSocket; fRTCPSocket = NULL; Medium::close(fRTCPInstance); fRTCPInstance = NULL; Medium::close(fReadSource); fReadSource = fRTPSource = NULL; fClientPortNum = 0; return False;}void MediaSubsession::deInitiate() { Medium::close(fRTCPInstance); fRTCPInstance = NULL; Medium::close(fReadSource); // this is assumed to also close fRTPSource fReadSource = NULL; fRTPSource = NULL; delete fRTCPSocket; delete fRTPSocket; fRTCPSocket = fRTPSocket = NULL;}Boolean MediaSubsession::setClientPortNum(unsigned short portNum) { if (fReadSource != NULL) { env().setResultMsg("A read source has already been created"); return False; } fClientPortNum = portNum; return True;}unsigned MediaSubsession::connectionEndpointAddress() const { do { // Get the endpoint name from with us, or our parent session: char const* endpointString = connectionEndpointName(); if (endpointString == NULL) { endpointString = parentSession().connectionEndpointName(); } if (endpointString == NULL) break; // Now, convert this name to an address, if we can: NetAddressList addresses(endpointString); if (addresses.numAddresses() == 0) break; return *(unsigned*)(addresses.firstAddress()->data()); } while (0); // No address known: return 0;}void MediaSubsession::setDestinations(unsigned defaultDestAddress) { // Get the destination address from the connection endpoint name // (This will be 0 if it's not known, in which case we use the default) unsigned destAddress = connectionEndpointAddress(); if (destAddress == 0) destAddress = defaultDestAddress; struct in_addr destAddr; destAddr.s_addr = destAddress; // The destination TTL remains unchanged: int destTTL = ~0; // means: don't change if (fRTPSocket != NULL) { Port destPort(serverPortNum); fRTPSocket->changeDestinationParameters(destAddr, destPort, destTTL); } if (fRTCPSocket != NULL && !isSSM()) { // Note: For SSM sessions, the dest address for RTCP was already set. Port destPort(serverPortNum+1); fRTCPSocket-> changeDestinationParameters(destAddr, destPort, destTTL); }}Boolean MediaSubsession::parseSDPLine_c(char const* sdpLine) { // Check for "c=IN IP4 <connection-endpoint>" // or "c=IN IP4 <connection-endpoint>/<ttl+numAddresses>" // (Later, do something with <ttl+numAddresses> also #####) char* connectionEndpointName = parseCLine(sdpLine); if (connectionEndpointName != NULL) { delete[] fConnectionEndpointName; fConnectionEndpointName = connectionEndpointName; return True; } return False;}Boolean MediaSubsession::parseSDPAttribute_rtpmap(char const* sdpLine) { // Check for a "a=rtpmap:<fmt> <codec>/<freq>" line: // (Also check without the "/<freq>"; RealNetworks omits this) // Also check for a trailing "/<numChannels>". Boolean parseSuccess = False; unsigned rtpmapPayloadFormat; char* codecName = strDupSize(sdpLine); // ensures we have enough space unsigned rtpTimestampFrequency = 0; unsigned numChannels = 1; if (sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u/%u", &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency, &numChannels) == 4 || sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u", &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency) == 3 || sscanf(sdpLine, "a=rtpmap: %u %s", &rtpmapPayloadFormat, codecName) == 2) { parseSuccess = True; if (rtpmapPayloadFormat == fRTPPayloadFormat) { // This "rtpmap" matches our payload format, so set our // codec name and timestamp frequency: // (First, make sure the codec name is upper case) for (char* p = codecName; *p != '\0'; ++p) { *p = toupper(*p); } delete[] fCodecName; fCodecName = strDup(codecName); fRTPTimestampFrequency = rtpTimestampFrequency; fNumChannels = numChannels; } } delete[] codecName; return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_control(char const* sdpLine) { // Check for a "a=control:<control-path>" line: Boolean parseSuccess = False; char* controlPath = strDupSize(sdpLine); // ensures we have enough space if (sscanf(sdpLine, "a=control: %s", controlPath) == 1) { parseSuccess = True; delete[] fControlPath; fControlPath = strDup(controlPath); } delete[] controlPath; return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_range(char const* sdpLine) { // Check for a "a=range:npt=<startTime>-<endTime>" line: // (Later handle other kinds of "a=range" attributes also???#####) Boolean parseSuccess = False; float playEndTime; if (parseRangeAttribute(sdpLine, playEndTime)) { parseSuccess = True; if (playEndTime > fPlayEndTime) { fPlayEndTime = playEndTime; if (playEndTime > fParent.playEndTime()) { fParent.playEndTime() = playEndTime; } } } return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_fmtp(char const* sdpLine) { // Check for a "a=fmtp:" line: // TEMP: We check only for a handful of expected parameter names ##### // Later: (i) check that payload format number matches; ##### // (ii) look for other parameters also (generalize?) ##### do { if (strncmp(sdpLine, "a=fmtp:", 7) != 0) break; sdpLine += 7; while (isdigit(*sdpLine)) ++sdpLine; // The remaining "sdpLine" should be a sequence of // <name>=<value>; // parameter assignments. Look at each of these. // First, convert the line to lower-case, to ease comparison: char* const lineCopy = strDup(sdpLine); char* line = lineCopy; for (char* c = line; *c != '\0'; ++c) *c = tolower(*c); while (*line != '\0' && *line != '\r' && *line != '\n') { unsigned u; char* valueStr = strDupSize(line); if (sscanf(line, " auxiliarydatasizelength = %u", &u) == 1) { fAuxiliarydatasizelength = u; } else if (sscanf(line, " constantduration = %u", &u) == 1) { fConstantduration = u; } else if (sscanf(line, " constantsize; = %u", &u) == 1) { fConstantsize = u; } else if (sscanf(line, " crc = %u", &u) == 1) { fCRC = u; } else if (sscanf(line, " ctsdeltalength = %u", &u) == 1) { fCtsdeltalength = u; } else if (sscanf(line, " de-interleavebuffersize = %u", &u) == 1) { fDe_interleavebuffersize = u; } else if (sscanf(line, " dtsdeltalength = %u", &u) == 1) { fDtsdeltalength = u; } else if (sscanf(line, " indexdeltalength = %u", &u) == 1) { fIndexdeltalength = u; } else if (sscanf(line, " indexlength = %u", &u) == 1) { fIndexlength = u; } else if (sscanf(line, " interleaving = %u", &u) == 1) { fInterleaving = u; } else if (sscanf(line, " maxdisplacement = %u", &u) == 1) { fMaxdisplacement = u; } else if (sscanf(line, " objecttype = %u", &u) == 1) { fObjecttype = u; } else if (sscanf(line, " octet-align = %u", &u) == 1) { fOctetalign = u; } else if (sscanf(line, " profile-level-id = %u", &u) == 1) { fProfile_level_id = u; } else if (sscanf(line, " robust-sorting = %u", &u) == 1) { fRobustsorting = u; } else if (sscanf(line, " sizelength = %u", &u) == 1) { fSizelength = u; } else if (sscanf(line, " streamstateindication = %u", &u) == 1) { fStreamstateindication = u; } else if (sscanf(line, " streamtype = %u", &u) == 1) { fStreamtype = u; } else if (sscanf(line, " cpresent = %u", &u) == 1) { fCpresent = u != 0; } else if (sscanf(line, " randomaccessindication = %u", &u) == 1) { fRandomaccessindication = u != 0; } else if (sscanf(line, " config = %[^; \t\r\n]", valueStr) == 1) { delete[] fConfig; fConfig = strDup(valueStr); } else if (sscanf(line, " mode = %[^; \t\r\n]", valueStr) == 1) { delete[] fMode; fMode = strDup(valueStr); } else if (sscanf(sdpLine, " sprop-parameter-sets = %[^; \t\r\n]", valueStr) == 1) { // Note: We used "sdpLine" here, because the value is case-sensitive. delete[] fSpropParameterSets; fSpropParameterSets = strDup(valueStr); } else { // Some of the above parameters are Boolean. Check whether the parameter // names appear alone, without a "= 1" at the end: if (sscanf(line, " %[^; \t\r\n]", valueStr) == 1) { if (strcmp(valueStr, "octet-align") == 0) { fOctetalign = 1; } else if (strcmp(valueStr, "cpresent") == 0) { fCpresent = True; } else if (strcmp(valueStr, "crc") == 0) { fCRC = 1; } else if (strcmp(valueStr, "robust-sorting") == 0) { fRobustsorting = 1; } else if (strcmp(valueStr, "randomaccessindication") == 0) { fRandomaccessindication = True; } } } delete[] valueStr; // Move to the next parameter assignment string: while (*line != '\0' && *line != '\r' && *line != '\n' && *line != ';') ++line; while (*line == ';') ++line; // Do the same with sdpLine; needed for finding case sensitive values: while (*sdpLine != '\0' && *sdpLine != '\r' && *sdpLine != '\n' && *sdpLine != ';') ++sdpLine; while (*sdpLine == ';') ++sdpLine; } delete[] lineCopy; return True; } while (0); return False;}Boolean MediaSubsession::parseSDPAttribute_source_filter(char const* sdpLine) { return parseSourceFilterAttribute(sdpLine, fSourceFilterAddr);}Boolean MediaSubsession::parseSDPAttribute_x_mct_slap(char const* sdpLine) { // Check for a "a=x-mct-slap:<slap-session-id> <stagger>" line: Boolean parseSuccess = False; int slapSessionId; int slapStagger; if (sscanf(sdpLine, "a=x-mct-slap: %d %d", &slapSessionId, &slapStagger) == 2) { parseSuccess = True; fMCT_SLAP_SessionId = slapSessionId; fMCT_SLAP_Stagger = (unsigned)slapStagger; } return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_x_dimensions(char const* sdpLine) { // Check for a "a=x-dimensions:<width>,<height>" line: Boolean parseSuccess = False; int width, height; if (sscanf(sdpLine, "a=x-dimensions:%d,%d", &width, &height) == 2) { parseSuccess = True; fVideoWidth = (unsigned short)width; fVideoHeight = (unsigned short)height; } return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_x_framerate(char const* sdpLine) { // Check for a "a=x-framerate:<fps>" line: Boolean parseSuccess = False; int rate; if (sscanf(sdpLine, "a=x-framerate:%d", &rate) == 1) { parseSuccess = True; fVideoFPS = (unsigned)rate; } return parseSuccess;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -