void SipccSdpAttributeList::LoadFmtp(sdp_t* sdp, uint16_t level) { auto fmtps = MakeUnique<SdpFmtpAttributeList>(); for (uint16_t i = 1; i < UINT16_MAX; ++i) { sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_FMTP, i); if (!attr) { break; } sdp_fmtp_t* fmtp = &(attr->attr.fmtp); // Get the payload type std::stringstream osPayloadType; // payload_num is the number in the fmtp attribute, verbatim osPayloadType << fmtp->payload_num; // Get parsed form of parameters, if supported UniquePtr<SdpFmtpAttributeList::Parameters> parameters; rtp_ptype codec = sdp_get_known_payload_type(sdp, level, fmtp->payload_num); switch (codec) { case RTP_H264_P0: case RTP_H264_P1: { SdpFmtpAttributeList::H264Parameters* h264Parameters( new SdpFmtpAttributeList::H264Parameters); sstrncpy(h264Parameters->sprop_parameter_sets, fmtp->parameter_sets, sizeof(h264Parameters->sprop_parameter_sets)); h264Parameters->level_asymmetry_allowed = !!(fmtp->level_asymmetry_allowed); h264Parameters->packetization_mode = fmtp->packetization_mode; sscanf(fmtp->profile_level_id, "%x", &h264Parameters->profile_level_id); h264Parameters->max_mbps = fmtp->max_mbps; h264Parameters->max_fs = fmtp->max_fs; h264Parameters->max_cpb = fmtp->max_cpb; h264Parameters->max_dpb = fmtp->max_dpb; h264Parameters->max_br = fmtp->max_br; parameters.reset(h264Parameters); } break; case RTP_VP9: { SdpFmtpAttributeList::VP8Parameters* vp9Parameters( new SdpFmtpAttributeList::VP8Parameters( SdpRtpmapAttributeList::kVP9)); vp9Parameters->max_fs = fmtp->max_fs; vp9Parameters->max_fr = fmtp->max_fr; parameters.reset(vp9Parameters); } break; case RTP_VP8: { SdpFmtpAttributeList::VP8Parameters* vp8Parameters( new SdpFmtpAttributeList::VP8Parameters( SdpRtpmapAttributeList::kVP8)); vp8Parameters->max_fs = fmtp->max_fs; vp8Parameters->max_fr = fmtp->max_fr; parameters.reset(vp8Parameters); } break; case RTP_RED: { SdpFmtpAttributeList::RedParameters* redParameters( new SdpFmtpAttributeList::RedParameters); for (int i = 0; i < SDP_FMTP_MAX_REDUNDANT_ENCODINGS && fmtp->redundant_encodings[i]; ++i) { redParameters->encodings.push_back(fmtp->redundant_encodings[i]); } parameters.reset(redParameters); } break; case RTP_OPUS: { SdpFmtpAttributeList::OpusParameters* opusParameters( new SdpFmtpAttributeList::OpusParameters); opusParameters->maxplaybackrate = fmtp->maxplaybackrate; opusParameters->stereo = fmtp->stereo; opusParameters->useInBandFec = fmtp->useinbandfec; parameters.reset(opusParameters); } break; default: { } } fmtps->PushEntry(osPayloadType.str(), Move(parameters)); } if (!fmtps->mFmtps.empty()) { SetAttribute(fmtps.release()); } }
void SipccSdpAttributeList::LoadFmtp(sdp_t* sdp, uint16_t level) { auto fmtps = MakeUnique<SdpFmtpAttributeList>(); for (uint16_t i = 1; i < UINT16_MAX; ++i) { sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_FMTP, i); if (!attr) { break; } sdp_fmtp_t* fmtp = &(attr->attr.fmtp); // Get the payload type std::stringstream osPayloadType; // payload_num is the number in the fmtp attribute, verbatim osPayloadType << fmtp->payload_num; // Get the serialized form of the parameters flex_string fs; flex_string_init(&fs); // Very lame, but we need direct access so we can get the serialized form sdp_result_e sdpres = sdp_build_attr_fmtp_params(sdp, fmtp, &fs); if (sdpres != SDP_SUCCESS) { flex_string_free(&fs); continue; } std::string paramsString(fs.buffer); flex_string_free(&fs); // Get parsed form of parameters, if supported UniquePtr<SdpFmtpAttributeList::Parameters> parameters; rtp_ptype codec = sdp_get_known_payload_type(sdp, level, fmtp->payload_num); switch (codec) { case RTP_H264_P0: case RTP_H264_P1: { SdpFmtpAttributeList::H264Parameters* h264Parameters( new SdpFmtpAttributeList::H264Parameters); sstrncpy(h264Parameters->sprop_parameter_sets, fmtp->parameter_sets, sizeof(h264Parameters->sprop_parameter_sets)); h264Parameters->level_asymmetry_allowed = !!(fmtp->level_asymmetry_allowed); h264Parameters->packetization_mode = fmtp->packetization_mode; // Copied from VcmSIPCCBinding #ifdef _WIN32 sscanf_s(fmtp->profile_level_id, "%x", &h264Parameters->profile_level_id, sizeof(unsigned*)); #else sscanf(fmtp->profile_level_id, "%xu", &h264Parameters->profile_level_id); #endif h264Parameters->max_mbps = fmtp->max_mbps; h264Parameters->max_fs = fmtp->max_fs; h264Parameters->max_cpb = fmtp->max_cpb; h264Parameters->max_dpb = fmtp->max_dpb; h264Parameters->max_br = fmtp->max_br; parameters.reset(h264Parameters); } break; case RTP_VP9: { SdpFmtpAttributeList::VP8Parameters* vp9Parameters( new SdpFmtpAttributeList::VP8Parameters( SdpRtpmapAttributeList::kVP9)); vp9Parameters->max_fs = fmtp->max_fs; vp9Parameters->max_fr = fmtp->max_fr; parameters.reset(vp9Parameters); } break; case RTP_VP8: { SdpFmtpAttributeList::VP8Parameters* vp8Parameters( new SdpFmtpAttributeList::VP8Parameters( SdpRtpmapAttributeList::kVP8)); vp8Parameters->max_fs = fmtp->max_fs; vp8Parameters->max_fr = fmtp->max_fr; parameters.reset(vp8Parameters); } break; default: { } } fmtps->PushEntry(osPayloadType.str(), paramsString, Move(parameters)); } if (!fmtps->mFmtps.empty()) { SetAttribute(fmtps.release()); } }