📄 sdpmdparse.cpp
字号:
HX_RESULT SDPMediaDescParser::HandleBLine(char* pLine, IHXValues* pHdr){ HX_RESULT res = HXR_FAILED; char* pCur = pLine; if (ScanForDelim(pCur, ':')) { char* pColon = pCur; *pCur++ = '\0'; char* pEnd = 0; ULONG32 ulBwValue = strtoul(pCur, &pEnd, 10); if (*pCur && !*pEnd) { const char* pBwKey = 0; res = HXR_OK; if (!strcasecmp(pLine, "AS")) { // a=AvgBitRate has the higher precedence... ULONG32 ulTmp; if (!SUCCEEDED(pHdr->GetPropertyULONG32("AvgBitRate", ulTmp))) { // use this as a default. // it's kilobits per sec.... pBwKey = "AvgBitRate"; ulBwValue *= 1000; } } else if (!strcasecmp(pLine, "RR")) { pBwKey = "RtcpRRRate"; } else if (!strcasecmp(pLine, "RS")) { pBwKey = "RtcpRSRate"; } else { res = HXR_NOT_SUPPORTED; } if (pBwKey) { AddULONG32(pHdr, pBwKey, ulBwValue); } } *pColon = ':'; } return res;}HX_RESULT SDPMediaDescParser::ParseFieldValue(char*& pValue, FieldType& fieldType) const{ HX_RESULT res = HXR_OK; char* pCur = pValue; // Look for the following forms // a=anInt:integer;43 // a=aString:string;"this is a string" // a=aBuffer:buffer;"TWFjIFRWAA==" // Assume we don't know the type. fieldType = ftUnknown; if (ScanForDelim(pCur, ';')) { // Replace the ';' with a '\0' so we // can check to see if it matches the known // types char* pSemiColon = pCur; *pCur++ = '\0'; if (!strcmp(pValue, "integer")) { // Update the value pointer to the // start of the integer value pValue = pCur; fieldType = ftULONG32; } else if (!strcmp(pValue, "string")) { fieldType = ftString; } else if (!strcmp(pValue, "buffer")) { fieldType = ftBuffer; } if ((fieldType == ftString) || (fieldType == ftBuffer)) { BOOL bFailed = TRUE; // Look for starting '"' if (*pCur == '"') { pCur++; // skip '"' if (*pCur) { // Store start of the string char* pStrStart = pCur; // Create temporary buffer for unescaping char* pTmpBuf = new char[strlen(pStrStart) + 1]; if (pTmpBuf) { char* pDest = pTmpBuf; // Copy string into pTmpBuf and // unescape any escape sequences while (*pCur && *pCur != '"') { if (*pCur == '\\') { *pCur++; // skip '\\' } *pDest++ = *pCur++; } // Make sure the last character is a '"' if (*pCur == '"') { // Replace ending '"' with '\0' *pDest = '\0'; // Replace escaped string with // unescaped string. strcpy(pStrStart, pTmpBuf); // Update the value pointer to the // start of the string value pValue = pStrStart; bFailed = FALSE; } delete [] pTmpBuf; } } } if (bFailed) { fieldType = ftUnknown; } } if (fieldType == ftUnknown) { // This is not a type we recognize. // Replace the '\0' with a ';' so the // value is the way it was before. *pSemiColon = ';'; } } return res;}HX_RESULT SDPMediaDescParser::HandleSpecialFields(const char* pFieldName, char* pFieldValue, IHXValues* pHdr){ HX_RESULT res = HXR_FAILED; if (!strcasecmp("Range", pFieldName)) { res = HandleRangeField(pFieldValue, pHdr); } else if (!strcasecmp("length", pFieldName)) { res = HandleLengthField(pFieldValue, pHdr); } else if (!strcasecmp("rtpmap", pFieldName)) { res = HandleRTPMapField(pFieldValue, pHdr); } else if (!strcasecmp("fmtp", pFieldName)) { res = HandleFMTPField(pFieldValue, pHdr); } else if (!strcasecmp("ptime", pFieldName)) { // a=ptime:43 AddULONG32(pHdr, "Ptime", strtol(pFieldValue, 0, 10)); res = HXR_OK; } else if (!strcasecmp("x-bufferdelay", pFieldName)) { // a=x-bufferdelay:234 // x-bufferdelay units are 1/1000 of a sec res = HandlePrerollField(pFieldValue, 1000, pHdr); } else if (!strcasecmp("x-initpredecbufperiod", pFieldName)) { // 3GPP 26.234 Annex G field // a=x-initpredecbufperiod:45000 // x-initpredecbufperiod units are 1/90000 of a sec res = HandlePrerollField(pFieldValue, 90000, pHdr); } else if (!strcasecmp("x-predecbufsize", pFieldName)) { // 3GPP 26.234 Annex G field // a=x-predecbufsize:45000 // x-predecbufsize units are bytes AddULONG32(pHdr, "x-predecbufsize", strtoul(pFieldValue, 0, 10)); res = HXR_OK; } else if (!strcasecmp("SdpplinVersion", pFieldName)) { res = checkVersion(strtol(pFieldValue, 0, 10)); if (HXR_FAIL == res) { // need to update... // this flag causes to exit in "m=" case res = HXR_REQUEST_UPGRADE; } } else if (!strcasecmp("control", pFieldName)) { AddString(pHdr, "Control", pFieldValue); res = HXR_OK; } else { res = HXR_NOT_SUPPORTED; } return res;}HX_RESULT SDPMediaDescParser::HandleRangeField(char* pFieldValue, IHXValues* pHdr){ char* pCur = pFieldValue; ULONG32 duration = 0; BOOL bIsLegal = TRUE; if (ScanForDelim(pCur, '=')) { // replace '=' with '\0' *pCur++ = '\0'; if (!strcasecmp(pFieldValue, "npt")) { // Look for the following npt forms // a=range:npt=-xxx // a=range:npt=xxx- // a=range:npt=xxx-xxx char* pLeftVal = pCur; if (ScanForDelim(pCur, '-')) { // replace '-' with '\0' *pCur++ = '\0'; NPTime left(pLeftVal); NPTime right(pCur); if (*pCur) { // a=range:npt=xxx-xxx duration = (UINT32)(right - left); m_bDefiniteDuration = TRUE; } else { // a=range:npt=xxx- // Treat open-ended play ranges as live streams // unless it is overridden by a media range. } } else { // This must be the following illegal form // a=range:npt=xxx bIsLegal = FALSE; } } } else { duration = strtol(pFieldValue, 0, 10); } if (bIsLegal) { if (0 == m_ulDefaultDuration) { m_ulDefaultDuration = duration; } AddULONG32(pHdr, "Duration", duration); } return HXR_OK;}HX_RESULT SDPMediaDescParser::HandleLengthField(char* pFieldValue, IHXValues* pHdr){ HX_RESULT res = HXR_FAILED; char* pCur = pFieldValue; ULONG32 duration = 0; BOOL bIsLegal = TRUE; // Look for the following npt form // a=length:npt=xxx if (ScanForDelim(pCur, '=')) { char* pEqual = pCur; // replace '=' with '\0' *pCur++ = '\0'; if (!strcasecmp(pFieldValue, "npt") && *pCur) { NPTime dTime(pCur); duration = (UINT32)dTime; res = HXR_OK; } else { // Put back '=' character *pEqual = '='; } } else { duration = strtol(pFieldValue, 0, 10); res = HXR_OK; } if (duration) { m_bDefiniteDuration = TRUE; } if (0 == m_ulDefaultDuration) { m_ulDefaultDuration = duration; } AddULONG32(pHdr, "Duration", duration); return res;}HX_RESULT SDPMediaDescParser::HandleRTPMapField(char* pFieldValue, IHXValues* pHdr){ HX_RESULT res = HXR_FAILED; // e.g. a=rtpmap:101 xxx/90000/2 char* pCur = 0; UINT32 payload = strtol(pFieldValue, &pCur, 10); ULONG32 rtpPayloadType = 0; res = pHdr->GetPropertyULONG32("RTPPayloadType", rtpPayloadType); if (*pFieldValue && (*pCur == ' ')) { SkipSpaces(pCur); // there could be multiple of these... if (payload == rtpPayloadType) { CHXString mimeType(m_mediaType); res = getRTPMapInfo(pCur, mimeType, pHdr); /* make sure there is no mime type set! * MimeType from m= && a=rtpmap has the lowest precedence. * a=mimetype -> mimetype table -> this mimetype */ IHXBuffer* pMimeType = 0; if (!SUCCEEDED(pHdr->GetPropertyCString( "MimeType", pMimeType))) { AddString(pHdr, "MimeType", mimeType); } HX_RELEASE(pMimeType); } } return res;}HX_RESULT SDPMediaDescParser::HandleFMTPField(char* pFieldValue, IHXValues* pHdr){ // e.g. a=fmtp:101 emphasis=50/15;foo=bar char* pCur = 0; UINT32 payload = strtol(pFieldValue, &pCur, 10); ULONG32 rtpPayloadType = 0; HX_RESULT res = pHdr->GetPropertyULONG32("RTPPayloadType", rtpPayloadType); if (*pFieldValue && *pCur == ' ') { SkipSpaces(pCur); // If the RTPPayloadType field is present, compare it // to the value in the fmtp field. // There could be multiple of these... if ((HXR_OK != res) || (payload == rtpPayloadType)) { AddString(pHdr, "PayloadParameters", pCur); CHXFMTPParser fmtp(m_pCCF); res = fmtp.Parse(pCur, pHdr); } } return res;}HX_RESULT SDPMediaDescParser::HandlePrerollField(char* pFieldValue, ULONG32 ulPrerollUnits, IHXValues* pHdr){ ULONG32 ulPreroll = 0; if (HXR_OK != pHdr->GetPropertyULONG32("Preroll", ulPreroll)) { ULONG32 ulValue = strtoul(pFieldValue, 0, 10); // Convert Preroll value to milliseconds ulPreroll = (ulValue / ulPrerollUnits) * 1000; ulPreroll += ((ulValue % ulPrerollUnits) * 1000) / ulPrerollUnits; AddULONG32(pHdr, "Preroll", ulPreroll); } return HXR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -