bool SipccSdpMediaSection::Load(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder) { switch (sdp_get_media_type(sdp, level)) { case SDP_MEDIA_AUDIO: mMediaType = kAudio; break; case SDP_MEDIA_VIDEO: mMediaType = kVideo; break; case SDP_MEDIA_APPLICATION: mMediaType = kApplication; break; case SDP_MEDIA_TEXT: mMediaType = kText; break; default: errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Unsupported media section type"); return false; } mPort = sdp_get_media_portnum(sdp, level); int32_t pc = sdp_get_media_portcount(sdp, level); if (pc == SDP_INVALID_VALUE) { // SDP_INVALID_VALUE (ie; -2) is used when there is no port count. :( mPortCount = 0; } else if (pc > static_cast<int32_t>(UINT16_MAX) || pc < 0) { errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Invalid port count"); return false; } else { mPortCount = pc; } if (!LoadProtocol(sdp, level, errorHolder)) { return false; } if (!LoadFormats(sdp, level, errorHolder)) { return false; } if (!mAttributeList.Load(sdp, level, errorHolder)) { return false; } if (!mBandwidths.Load(sdp, level, errorHolder)) { return false; } return LoadConnection(sdp, level, errorHolder); }
bool SipccSdpAttributeList::LoadRtpmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder) { auto rtpmap = MakeUnique<SdpRtpmapAttributeList>(); uint16_t count; sdp_result_e result = sdp_attr_num_instances(sdp, level, 0, SDP_ATTR_RTPMAP, &count); if (result != SDP_SUCCESS) { MOZ_ASSERT(false, "Unable to get rtpmap size"); errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Unable to get rtpmap size"); return false; } for (uint16_t i = 0; i < count; ++i) { uint16_t pt = sdp_attr_get_rtpmap_payload_type(sdp, level, 0, i + 1); const char* ccName = sdp_attr_get_rtpmap_encname(sdp, level, 0, i + 1); if (!ccName) { // Probably no rtpmap attribute for a pt in an m-line errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "No rtpmap attribute for payload type"); continue; } std::string name(ccName); SdpRtpmapAttributeList::CodecType codec = GetCodecType(sdp_get_known_payload_type(sdp, level, pt)); uint32_t clock = sdp_attr_get_rtpmap_clockrate(sdp, level, 0, i + 1); uint16_t channels = 0; // sipcc gives us a channels value of "1" for video if (sdp_get_media_type(sdp, level) == SDP_MEDIA_AUDIO) { channels = sdp_attr_get_rtpmap_num_chan(sdp, level, 0, i + 1); } std::ostringstream osPayloadType; osPayloadType << pt; rtpmap->PushEntry(osPayloadType.str(), codec, name, clock, channels); } if (!rtpmap->mRtpmaps.empty()) { SetAttribute(rtpmap.release()); } return true; }
bool SipccSdpMediaSection::LoadConnection(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder) { if (!sdp_connection_valid(sdp, level)) { level = SDP_SESSION_LEVEL; if (!sdp_connection_valid(sdp, level)) { errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Missing c= line"); return false; } } sdp_nettype_e type = sdp_get_conn_nettype(sdp, level); if (type != SDP_NT_INTERNET) { errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Unsupported network type"); return false; } sdp::AddrType addrType; switch (sdp_get_conn_addrtype(sdp, level)) { case SDP_AT_IP4: addrType = sdp::kIPv4; break; case SDP_AT_IP6: addrType = sdp::kIPv6; break; default: errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Unsupported address type"); return false; } std::string address = sdp_get_conn_address(sdp, level); int16_t ttl = static_cast<uint16_t>(sdp_get_mcast_ttl(sdp, level)); if (ttl < 0) { ttl = 0; } int32_t numAddr = static_cast<uint32_t>(sdp_get_mcast_num_of_addresses(sdp, level)); if (numAddr < 0) { numAddr = 0; } mConnection = MakeUnique<SdpConnection>(addrType, address, ttl, numAddr); return true; }
bool SipccSdpMediaSection::LoadProtocol(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder) { switch (sdp_get_media_transport(sdp, level)) { case SDP_TRANSPORT_RTPAVP: mProtocol = kRtpAvp; break; case SDP_TRANSPORT_RTPSAVP: mProtocol = kRtpSavp; break; case SDP_TRANSPORT_RTPAVPF: mProtocol = kRtpAvpf; break; case SDP_TRANSPORT_RTPSAVPF: mProtocol = kRtpSavpf; break; case SDP_TRANSPORT_UDPTLSRTPSAVP: mProtocol = kUdpTlsRtpSavp; break; case SDP_TRANSPORT_UDPTLSRTPSAVPF: mProtocol = kUdpTlsRtpSavpf; break; case SDP_TRANSPORT_TCPTLSRTPSAVP: mProtocol = kTcpTlsRtpSavp; break; case SDP_TRANSPORT_TCPTLSRTPSAVPF: mProtocol = kTcpTlsRtpSavpf; break; case SDP_TRANSPORT_DTLSSCTP: mProtocol = kDtlsSctp; break; default: errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Unsupported media transport type"); return false; } return true; }
bool SipccSdpMediaSection::LoadFormats(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder) { sdp_media_e mtype = sdp_get_media_type(sdp, level); if (mtype == SDP_MEDIA_APPLICATION) { uint32_t ptype = sdp_get_media_sctp_port(sdp, level); std::ostringstream osPayloadType; osPayloadType << ptype; mFormats.push_back(osPayloadType.str()); } else if (mtype == SDP_MEDIA_AUDIO || mtype == SDP_MEDIA_VIDEO) { uint16_t count = sdp_get_media_num_payload_types(sdp, level); for (uint16_t i = 0; i < count; ++i) { sdp_payload_ind_e indicator; // we ignore this, which is fine uint32_t ptype = sdp_get_media_payload_type(sdp, level, i + 1, &indicator); if (GET_DYN_PAYLOAD_TYPE_VALUE(ptype) > UINT8_MAX) { errorHolder.AddParseError(sdp_get_media_line_number(sdp, level), "Format is too large"); return false; } std::ostringstream osPayloadType; // sipcc stores payload types in a funny way. When sipcc and the SDP it // parsed differ on what payload type number should be used for a given // codec, sipcc's value goes in the lower byte, and the SDP's value in // the upper byte. When they do not differ, only the lower byte is used. // We want what was in the SDP, verbatim. osPayloadType << GET_DYN_PAYLOAD_TYPE_VALUE(ptype); mFormats.push_back(osPayloadType.str()); } } return true; }