OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2011 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 const std::string& message, | 262 const std::string& message, |
263 const TransportDescription& session_td, | 263 const TransportDescription& session_td, |
264 const RtpHeaderExtensions& session_extmaps, | 264 const RtpHeaderExtensions& session_extmaps, |
265 size_t* pos, cricket::SessionDescription* desc, | 265 size_t* pos, cricket::SessionDescription* desc, |
266 std::vector<JsepIceCandidate*>* candidates, | 266 std::vector<JsepIceCandidate*>* candidates, |
267 SdpParseError* error); | 267 SdpParseError* error); |
268 static bool ParseContent(const std::string& message, | 268 static bool ParseContent(const std::string& message, |
269 const MediaType media_type, | 269 const MediaType media_type, |
270 int mline_index, | 270 int mline_index, |
271 const std::string& protocol, | 271 const std::string& protocol, |
272 const std::vector<int>& codec_preference, | 272 const std::vector<int>& payload_types, |
273 size_t* pos, | 273 size_t* pos, |
274 std::string* content_name, | 274 std::string* content_name, |
275 MediaContentDescription* media_desc, | 275 MediaContentDescription* media_desc, |
276 TransportDescription* transport, | 276 TransportDescription* transport, |
277 std::vector<JsepIceCandidate*>* candidates, | 277 std::vector<JsepIceCandidate*>* candidates, |
278 SdpParseError* error); | 278 SdpParseError* error); |
279 static bool ParseSsrcAttribute(const std::string& line, | 279 static bool ParseSsrcAttribute(const std::string& line, |
280 SsrcInfoVec* ssrc_infos, | 280 SsrcInfoVec* ssrc_infos, |
281 SdpParseError* error); | 281 SdpParseError* error); |
282 static bool ParseSsrcGroupAttribute(const std::string& line, | 282 static bool ParseSsrcGroupAttribute(const std::string& line, |
283 SsrcGroupVec* ssrc_groups, | 283 SsrcGroupVec* ssrc_groups, |
284 SdpParseError* error); | 284 SdpParseError* error); |
285 static bool ParseCryptoAttribute(const std::string& line, | 285 static bool ParseCryptoAttribute(const std::string& line, |
286 MediaContentDescription* media_desc, | 286 MediaContentDescription* media_desc, |
287 SdpParseError* error); | 287 SdpParseError* error); |
288 static bool ParseRtpmapAttribute(const std::string& line, | 288 static bool ParseRtpmapAttribute(const std::string& line, |
289 const MediaType media_type, | 289 const MediaType media_type, |
290 const std::vector<int>& codec_preference, | 290 const std::vector<int>& payload_types, |
291 MediaContentDescription* media_desc, | 291 MediaContentDescription* media_desc, |
292 SdpParseError* error); | 292 SdpParseError* error); |
293 static bool ParseFmtpAttributes(const std::string& line, | 293 static bool ParseFmtpAttributes(const std::string& line, |
294 const MediaType media_type, | 294 const MediaType media_type, |
295 MediaContentDescription* media_desc, | 295 MediaContentDescription* media_desc, |
296 SdpParseError* error); | 296 SdpParseError* error); |
297 static bool ParseFmtpParam(const std::string& line, std::string* parameter, | 297 static bool ParseFmtpParam(const std::string& line, std::string* parameter, |
298 std::string* value, SdpParseError* error); | 298 std::string* value, SdpParseError* error); |
299 static bool ParseCandidate(const std::string& message, Candidate* candidate, | 299 static bool ParseCandidate(const std::string& message, Candidate* candidate, |
300 SdpParseError* error, bool is_raw); | 300 SdpParseError* error, bool is_raw); |
(...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1632 } | 1632 } |
1633 | 1633 |
1634 bool AddSctpDataCodec(DataContentDescription* media_desc, | 1634 bool AddSctpDataCodec(DataContentDescription* media_desc, |
1635 int sctp_port) { | 1635 int sctp_port) { |
1636 if (media_desc->HasCodec(cricket::kGoogleSctpDataCodecId)) { | 1636 if (media_desc->HasCodec(cricket::kGoogleSctpDataCodecId)) { |
1637 return ParseFailed("", | 1637 return ParseFailed("", |
1638 "Can't have multiple sctp port attributes.", | 1638 "Can't have multiple sctp port attributes.", |
1639 NULL); | 1639 NULL); |
1640 } | 1640 } |
1641 // Add the SCTP Port number as a pseudo-codec "port" parameter | 1641 // Add the SCTP Port number as a pseudo-codec "port" parameter |
1642 cricket::DataCodec codec_port( | 1642 cricket::DataCodec codec_port(cricket::kGoogleSctpDataCodecId, |
1643 cricket::kGoogleSctpDataCodecId, cricket::kGoogleSctpDataCodecName, | 1643 cricket::kGoogleSctpDataCodecName); |
1644 0); | |
1645 codec_port.SetParam(cricket::kCodecParamPort, sctp_port); | 1644 codec_port.SetParam(cricket::kCodecParamPort, sctp_port); |
1646 LOG(INFO) << "AddSctpDataCodec: Got SCTP Port Number " | 1645 LOG(INFO) << "AddSctpDataCodec: Got SCTP Port Number " |
1647 << sctp_port; | 1646 << sctp_port; |
1648 media_desc->AddCodec(codec_port); | 1647 media_desc->AddCodec(codec_port); |
1649 return true; | 1648 return true; |
1650 } | 1649 } |
1651 | 1650 |
1652 bool GetMinValue(const std::vector<int>& values, int* value) { | 1651 bool GetMinValue(const std::vector<int>& values, int* value) { |
1653 if (values.empty()) { | 1652 if (values.empty()) { |
1654 return false; | 1653 return false; |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2160 { "DVI4", 11025, 1 }, | 2159 { "DVI4", 11025, 1 }, |
2161 { "DVI4", 22050, 1 }, | 2160 { "DVI4", 22050, 1 }, |
2162 { "G729", 8000, 1 }, | 2161 { "G729", 8000, 1 }, |
2163 }; | 2162 }; |
2164 | 2163 |
2165 void MaybeCreateStaticPayloadAudioCodecs( | 2164 void MaybeCreateStaticPayloadAudioCodecs( |
2166 const std::vector<int>& fmts, AudioContentDescription* media_desc) { | 2165 const std::vector<int>& fmts, AudioContentDescription* media_desc) { |
2167 if (!media_desc) { | 2166 if (!media_desc) { |
2168 return; | 2167 return; |
2169 } | 2168 } |
2170 int preference = static_cast<int>(fmts.size()); | 2169 RTC_DCHECK(media_desc->codecs().empty()); |
2171 std::vector<int>::const_iterator it = fmts.begin(); | 2170 std::vector<int>::const_iterator it = fmts.begin(); |
2172 bool add_new_codec = false; | |
2173 for (; it != fmts.end(); ++it) { | 2171 for (; it != fmts.end(); ++it) { |
2174 int payload_type = *it; | 2172 int payload_type = *it; |
2175 if (!media_desc->HasCodec(payload_type) && | 2173 if (!media_desc->HasCodec(payload_type) && |
2176 payload_type >= 0 && | 2174 payload_type >= 0 && |
2177 payload_type < arraysize(kStaticPayloadAudioCodecs)) { | 2175 payload_type < arraysize(kStaticPayloadAudioCodecs)) { |
2178 std::string encoding_name = kStaticPayloadAudioCodecs[payload_type].name; | 2176 std::string encoding_name = kStaticPayloadAudioCodecs[payload_type].name; |
2179 int clock_rate = kStaticPayloadAudioCodecs[payload_type].clockrate; | 2177 int clock_rate = kStaticPayloadAudioCodecs[payload_type].clockrate; |
2180 size_t channels = kStaticPayloadAudioCodecs[payload_type].channels; | 2178 size_t channels = kStaticPayloadAudioCodecs[payload_type].channels; |
2181 media_desc->AddCodec(cricket::AudioCodec(payload_type, encoding_name, | 2179 media_desc->AddCodec(cricket::AudioCodec(payload_type, encoding_name, |
2182 clock_rate, 0, channels, | 2180 clock_rate, 0, channels)); |
2183 preference)); | |
2184 add_new_codec = true; | |
2185 } | 2181 } |
2186 --preference; | |
2187 } | |
2188 if (add_new_codec) { | |
2189 media_desc->SortCodecs(); | |
2190 } | 2182 } |
2191 } | 2183 } |
2192 | 2184 |
2193 template <class C> | 2185 template <class C> |
2194 static C* ParseContentDescription(const std::string& message, | 2186 static C* ParseContentDescription(const std::string& message, |
2195 const MediaType media_type, | 2187 const MediaType media_type, |
2196 int mline_index, | 2188 int mline_index, |
2197 const std::string& protocol, | 2189 const std::string& protocol, |
2198 const std::vector<int>& codec_preference, | 2190 const std::vector<int>& payload_types, |
2199 size_t* pos, | 2191 size_t* pos, |
2200 std::string* content_name, | 2192 std::string* content_name, |
2201 TransportDescription* transport, | 2193 TransportDescription* transport, |
2202 std::vector<JsepIceCandidate*>* candidates, | 2194 std::vector<JsepIceCandidate*>* candidates, |
2203 webrtc::SdpParseError* error) { | 2195 webrtc::SdpParseError* error) { |
2204 C* media_desc = new C(); | 2196 C* media_desc = new C(); |
2205 switch (media_type) { | 2197 switch (media_type) { |
2206 case cricket::MEDIA_TYPE_AUDIO: | 2198 case cricket::MEDIA_TYPE_AUDIO: |
2207 *content_name = cricket::CN_AUDIO; | 2199 *content_name = cricket::CN_AUDIO; |
2208 break; | 2200 break; |
2209 case cricket::MEDIA_TYPE_VIDEO: | 2201 case cricket::MEDIA_TYPE_VIDEO: |
2210 *content_name = cricket::CN_VIDEO; | 2202 *content_name = cricket::CN_VIDEO; |
2211 break; | 2203 break; |
2212 case cricket::MEDIA_TYPE_DATA: | 2204 case cricket::MEDIA_TYPE_DATA: |
2213 *content_name = cricket::CN_DATA; | 2205 *content_name = cricket::CN_DATA; |
2214 break; | 2206 break; |
2215 default: | 2207 default: |
2216 ASSERT(false); | 2208 ASSERT(false); |
2217 break; | 2209 break; |
2218 } | 2210 } |
2219 if (!ParseContent(message, media_type, mline_index, protocol, | 2211 if (!ParseContent(message, media_type, mline_index, protocol, payload_types, |
2220 codec_preference, pos, content_name, | 2212 pos, content_name, media_desc, transport, candidates, |
2221 media_desc, transport, candidates, error)) { | 2213 error)) { |
2222 delete media_desc; | 2214 delete media_desc; |
2223 return NULL; | 2215 return NULL; |
2224 } | 2216 } |
2225 // Sort the codecs according to the m-line fmt list. | 2217 // Sort the codecs according to the m-line fmt list. |
2226 media_desc->SortCodecs(); | 2218 std::vector<typename C::CodecType> codecs = media_desc->codecs(); |
2219 std::sort(codecs.begin(), codecs.end(), [payload_types]( | |
2220 const typename C::CodecType& a, | |
2221 const typename C::CodecType& b) { | |
2222 return std::find(payload_types.begin(), payload_types.end(), a.id) < | |
2223 std::find(payload_types.begin(), payload_types.end(), b.id); | |
2224 }); | |
2225 media_desc->set_codecs(codecs); | |
pthatcher1
2016/04/11 21:53:40
It would be nice if this weren't O(n^2), but I gue
Taylor Brandstetter
2016/04/12 00:18:00
It's actually O(N^2 log N) :)
I fixed this pretty
| |
2227 return media_desc; | 2226 return media_desc; |
2228 } | 2227 } |
2229 | 2228 |
2230 bool ParseMediaDescription(const std::string& message, | 2229 bool ParseMediaDescription(const std::string& message, |
2231 const TransportDescription& session_td, | 2230 const TransportDescription& session_td, |
2232 const RtpHeaderExtensions& session_extmaps, | 2231 const RtpHeaderExtensions& session_extmaps, |
2233 size_t* pos, | 2232 size_t* pos, |
2234 cricket::SessionDescription* desc, | 2233 cricket::SessionDescription* desc, |
2235 std::vector<JsepIceCandidate*>* candidates, | 2234 std::vector<JsepIceCandidate*>* candidates, |
2236 SdpParseError* error) { | 2235 SdpParseError* error) { |
(...skipping 18 matching lines...) Expand all Loading... | |
2255 // RFC 3264 | 2254 // RFC 3264 |
2256 // To reject an offered stream, the port number in the corresponding stream | 2255 // To reject an offered stream, the port number in the corresponding stream |
2257 // in the answer MUST be set to zero. | 2256 // in the answer MUST be set to zero. |
2258 if (fields[1] == kMediaPortRejected) { | 2257 if (fields[1] == kMediaPortRejected) { |
2259 rejected = true; | 2258 rejected = true; |
2260 } | 2259 } |
2261 | 2260 |
2262 std::string protocol = fields[2]; | 2261 std::string protocol = fields[2]; |
2263 | 2262 |
2264 // <fmt> | 2263 // <fmt> |
2265 std::vector<int> codec_preference; | 2264 std::vector<int> payload_types; |
2266 if (IsRtp(protocol)) { | 2265 if (IsRtp(protocol)) { |
2267 for (size_t j = 3 ; j < fields.size(); ++j) { | 2266 for (size_t j = 3 ; j < fields.size(); ++j) { |
2268 // TODO(wu): Remove when below bug is fixed. | 2267 // TODO(wu): Remove when below bug is fixed. |
2269 // https://bugzilla.mozilla.org/show_bug.cgi?id=996329 | 2268 // https://bugzilla.mozilla.org/show_bug.cgi?id=996329 |
2270 if (fields[j].empty() && j == fields.size() - 1) { | 2269 if (fields[j].empty() && j == fields.size() - 1) { |
2271 continue; | 2270 continue; |
2272 } | 2271 } |
2273 | 2272 |
2274 int pl = 0; | 2273 int pl = 0; |
2275 if (!GetPayloadTypeFromString(line, fields[j], &pl, error)) { | 2274 if (!GetPayloadTypeFromString(line, fields[j], &pl, error)) { |
2276 return false; | 2275 return false; |
2277 } | 2276 } |
2278 codec_preference.push_back(pl); | 2277 payload_types.push_back(pl); |
2279 } | 2278 } |
2280 } | 2279 } |
2281 | 2280 |
2282 // Make a temporary TransportDescription based on |session_td|. | 2281 // Make a temporary TransportDescription based on |session_td|. |
2283 // Some of this gets overwritten by ParseContent. | 2282 // Some of this gets overwritten by ParseContent. |
2284 TransportDescription transport( | 2283 TransportDescription transport( |
2285 session_td.transport_options, session_td.ice_ufrag, session_td.ice_pwd, | 2284 session_td.transport_options, session_td.ice_ufrag, session_td.ice_pwd, |
2286 session_td.ice_mode, session_td.connection_role, | 2285 session_td.ice_mode, session_td.connection_role, |
2287 session_td.identity_fingerprint.get()); | 2286 session_td.identity_fingerprint.get()); |
2288 | 2287 |
2289 rtc::scoped_ptr<MediaContentDescription> content; | 2288 rtc::scoped_ptr<MediaContentDescription> content; |
2290 std::string content_name; | 2289 std::string content_name; |
2291 if (HasAttribute(line, kMediaTypeVideo)) { | 2290 if (HasAttribute(line, kMediaTypeVideo)) { |
2292 content.reset(ParseContentDescription<VideoContentDescription>( | 2291 content.reset(ParseContentDescription<VideoContentDescription>( |
2293 message, cricket::MEDIA_TYPE_VIDEO, mline_index, protocol, | 2292 message, cricket::MEDIA_TYPE_VIDEO, mline_index, protocol, |
2294 codec_preference, pos, &content_name, | 2293 payload_types, pos, &content_name, &transport, candidates, error)); |
2295 &transport, candidates, error)); | |
2296 } else if (HasAttribute(line, kMediaTypeAudio)) { | 2294 } else if (HasAttribute(line, kMediaTypeAudio)) { |
2297 content.reset(ParseContentDescription<AudioContentDescription>( | 2295 content.reset(ParseContentDescription<AudioContentDescription>( |
2298 message, cricket::MEDIA_TYPE_AUDIO, mline_index, protocol, | 2296 message, cricket::MEDIA_TYPE_AUDIO, mline_index, protocol, |
2299 codec_preference, pos, &content_name, | 2297 payload_types, pos, &content_name, &transport, candidates, error)); |
2300 &transport, candidates, error)); | |
2301 } else if (HasAttribute(line, kMediaTypeData)) { | 2298 } else if (HasAttribute(line, kMediaTypeData)) { |
2302 DataContentDescription* data_desc = | 2299 DataContentDescription* data_desc = |
2303 ParseContentDescription<DataContentDescription>( | 2300 ParseContentDescription<DataContentDescription>( |
2304 message, cricket::MEDIA_TYPE_DATA, mline_index, protocol, | 2301 message, cricket::MEDIA_TYPE_DATA, mline_index, protocol, |
2305 codec_preference, pos, &content_name, | 2302 payload_types, pos, &content_name, &transport, candidates, error); |
2306 &transport, candidates, error); | |
2307 content.reset(data_desc); | 2303 content.reset(data_desc); |
2308 | 2304 |
2309 int p; | 2305 int p; |
2310 if (data_desc && IsDtlsSctp(protocol) && rtc::FromString(fields[3], &p)) { | 2306 if (data_desc && IsDtlsSctp(protocol) && rtc::FromString(fields[3], &p)) { |
2311 if (!AddSctpDataCodec(data_desc, p)) | 2307 if (!AddSctpDataCodec(data_desc, p)) |
2312 return false; | 2308 return false; |
2313 } | 2309 } |
2314 } else { | 2310 } else { |
2315 LOG(LS_WARNING) << "Unsupported media type: " << line; | 2311 LOG(LS_WARNING) << "Unsupported media type: " << line; |
2316 continue; | 2312 continue; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2503 iter != codecs.end(); ++iter) { | 2499 iter != codecs.end(); ++iter) { |
2504 iter->params[name] = value; | 2500 iter->params[name] = value; |
2505 } | 2501 } |
2506 audio_desc->set_codecs(codecs); | 2502 audio_desc->set_codecs(codecs); |
2507 } | 2503 } |
2508 | 2504 |
2509 bool ParseContent(const std::string& message, | 2505 bool ParseContent(const std::string& message, |
2510 const MediaType media_type, | 2506 const MediaType media_type, |
2511 int mline_index, | 2507 int mline_index, |
2512 const std::string& protocol, | 2508 const std::string& protocol, |
2513 const std::vector<int>& codec_preference, | 2509 const std::vector<int>& payload_types, |
2514 size_t* pos, | 2510 size_t* pos, |
2515 std::string* content_name, | 2511 std::string* content_name, |
2516 MediaContentDescription* media_desc, | 2512 MediaContentDescription* media_desc, |
2517 TransportDescription* transport, | 2513 TransportDescription* transport, |
2518 std::vector<JsepIceCandidate*>* candidates, | 2514 std::vector<JsepIceCandidate*>* candidates, |
2519 SdpParseError* error) { | 2515 SdpParseError* error) { |
2520 ASSERT(media_desc != NULL); | 2516 ASSERT(media_desc != NULL); |
2521 ASSERT(content_name != NULL); | 2517 ASSERT(content_name != NULL); |
2522 ASSERT(transport != NULL); | 2518 ASSERT(transport != NULL); |
2523 | 2519 |
2524 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 2520 if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
2525 MaybeCreateStaticPayloadAudioCodecs( | 2521 MaybeCreateStaticPayloadAudioCodecs( |
2526 codec_preference, static_cast<AudioContentDescription*>(media_desc)); | 2522 payload_types, static_cast<AudioContentDescription*>(media_desc)); |
2527 } | 2523 } |
2528 | 2524 |
2529 // The media level "ice-ufrag" and "ice-pwd". | 2525 // The media level "ice-ufrag" and "ice-pwd". |
2530 // The candidates before update the media level "ice-pwd" and "ice-ufrag". | 2526 // The candidates before update the media level "ice-pwd" and "ice-ufrag". |
2531 Candidates candidates_orig; | 2527 Candidates candidates_orig; |
2532 std::string line; | 2528 std::string line; |
2533 std::string mline_id; | 2529 std::string mline_id; |
2534 // Tracks created out of the ssrc attributes. | 2530 // Tracks created out of the ssrc attributes. |
2535 StreamParamsVec tracks; | 2531 StreamParamsVec tracks; |
2536 SsrcInfoVec ssrc_infos; | 2532 SsrcInfoVec ssrc_infos; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2651 } | 2647 } |
2652 } else if (HasAttribute(line, kAttributeSsrc)) { | 2648 } else if (HasAttribute(line, kAttributeSsrc)) { |
2653 if (!ParseSsrcAttribute(line, &ssrc_infos, error)) { | 2649 if (!ParseSsrcAttribute(line, &ssrc_infos, error)) { |
2654 return false; | 2650 return false; |
2655 } | 2651 } |
2656 } else if (HasAttribute(line, kAttributeCrypto)) { | 2652 } else if (HasAttribute(line, kAttributeCrypto)) { |
2657 if (!ParseCryptoAttribute(line, media_desc, error)) { | 2653 if (!ParseCryptoAttribute(line, media_desc, error)) { |
2658 return false; | 2654 return false; |
2659 } | 2655 } |
2660 } else if (HasAttribute(line, kAttributeRtpmap)) { | 2656 } else if (HasAttribute(line, kAttributeRtpmap)) { |
2661 if (!ParseRtpmapAttribute(line, media_type, codec_preference, | 2657 if (!ParseRtpmapAttribute(line, media_type, payload_types, media_desc, |
2662 media_desc, error)) { | 2658 error)) { |
2663 return false; | 2659 return false; |
2664 } | 2660 } |
2665 } else if (HasAttribute(line, kCodecParamMaxPTime)) { | 2661 } else if (HasAttribute(line, kCodecParamMaxPTime)) { |
2666 if (!GetValue(line, kCodecParamMaxPTime, &maxptime_as_string, error)) { | 2662 if (!GetValue(line, kCodecParamMaxPTime, &maxptime_as_string, error)) { |
2667 return false; | 2663 return false; |
2668 } | 2664 } |
2669 } else if (HasAttribute(line, kAttributeRtcpFb)) { | 2665 } else if (HasAttribute(line, kAttributeRtcpFb)) { |
2670 if (!ParseRtcpFbAttribute(line, media_type, media_desc, error)) { | 2666 if (!ParseRtcpFbAttribute(line, media_type, media_desc, error)) { |
2671 return false; | 2667 return false; |
2672 } | 2668 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2908 std::string session_params; | 2904 std::string session_params; |
2909 if (fields.size() > 3) { | 2905 if (fields.size() > 3) { |
2910 session_params = fields[3]; | 2906 session_params = fields[3]; |
2911 } | 2907 } |
2912 media_desc->AddCrypto(CryptoParams(tag, crypto_suite, key_params, | 2908 media_desc->AddCrypto(CryptoParams(tag, crypto_suite, key_params, |
2913 session_params)); | 2909 session_params)); |
2914 return true; | 2910 return true; |
2915 } | 2911 } |
2916 | 2912 |
2917 // Updates or creates a new codec entry in the audio description with according | 2913 // Updates or creates a new codec entry in the audio description with according |
2918 // to |name|, |clockrate|, |bitrate|, |channels| and |preference|. | 2914 // to |name|, |clockrate|, |bitrate|, and |channels|. |
2919 void UpdateCodec(int payload_type, const std::string& name, int clockrate, | 2915 void UpdateCodec(int payload_type, |
2920 int bitrate, size_t channels, int preference, | 2916 const std::string& name, |
2917 int clockrate, | |
2918 int bitrate, | |
2919 size_t channels, | |
2921 AudioContentDescription* audio_desc) { | 2920 AudioContentDescription* audio_desc) { |
2922 // Codec may already be populated with (only) optional parameters | 2921 // Codec may already be populated with (only) optional parameters |
2923 // (from an fmtp). | 2922 // (from an fmtp). |
2924 cricket::AudioCodec codec = | 2923 cricket::AudioCodec codec = |
2925 GetCodecWithPayloadType(audio_desc->codecs(), payload_type); | 2924 GetCodecWithPayloadType(audio_desc->codecs(), payload_type); |
2926 codec.name = name; | 2925 codec.name = name; |
2927 codec.clockrate = clockrate; | 2926 codec.clockrate = clockrate; |
2928 codec.bitrate = bitrate; | 2927 codec.bitrate = bitrate; |
2929 codec.channels = channels; | 2928 codec.channels = channels; |
2930 codec.preference = preference; | |
2931 AddOrReplaceCodec<AudioContentDescription, cricket::AudioCodec>(audio_desc, | 2929 AddOrReplaceCodec<AudioContentDescription, cricket::AudioCodec>(audio_desc, |
2932 codec); | 2930 codec); |
2933 } | 2931 } |
2934 | 2932 |
2935 // Updates or creates a new codec entry in the video description according to | 2933 // Updates or creates a new codec entry in the video description according to |
2936 // |name|, |width|, |height|, |framerate| and |preference|. | 2934 // |name|, |width|, |height|, and |framerate|. |
2937 void UpdateCodec(int payload_type, const std::string& name, int width, | 2935 void UpdateCodec(int payload_type, |
2938 int height, int framerate, int preference, | 2936 const std::string& name, |
2937 int width, | |
2938 int height, | |
2939 int framerate, | |
2939 VideoContentDescription* video_desc) { | 2940 VideoContentDescription* video_desc) { |
2940 // Codec may already be populated with (only) optional parameters | 2941 // Codec may already be populated with (only) optional parameters |
2941 // (from an fmtp). | 2942 // (from an fmtp). |
2942 cricket::VideoCodec codec = | 2943 cricket::VideoCodec codec = |
2943 GetCodecWithPayloadType(video_desc->codecs(), payload_type); | 2944 GetCodecWithPayloadType(video_desc->codecs(), payload_type); |
2944 codec.name = name; | 2945 codec.name = name; |
2945 codec.width = width; | 2946 codec.width = width; |
2946 codec.height = height; | 2947 codec.height = height; |
2947 codec.framerate = framerate; | 2948 codec.framerate = framerate; |
2948 codec.preference = preference; | |
2949 AddOrReplaceCodec<VideoContentDescription, cricket::VideoCodec>(video_desc, | 2949 AddOrReplaceCodec<VideoContentDescription, cricket::VideoCodec>(video_desc, |
2950 codec); | 2950 codec); |
2951 } | 2951 } |
2952 | 2952 |
2953 bool ParseRtpmapAttribute(const std::string& line, | 2953 bool ParseRtpmapAttribute(const std::string& line, |
2954 const MediaType media_type, | 2954 const MediaType media_type, |
2955 const std::vector<int>& codec_preference, | 2955 const std::vector<int>& payload_types, |
2956 MediaContentDescription* media_desc, | 2956 MediaContentDescription* media_desc, |
2957 SdpParseError* error) { | 2957 SdpParseError* error) { |
2958 std::vector<std::string> fields; | 2958 std::vector<std::string> fields; |
2959 rtc::split(line.substr(kLinePrefixLength), | 2959 rtc::split(line.substr(kLinePrefixLength), |
2960 kSdpDelimiterSpace, &fields); | 2960 kSdpDelimiterSpace, &fields); |
2961 // RFC 4566 | 2961 // RFC 4566 |
2962 // a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encodingparameters>] | 2962 // a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encodingparameters>] |
2963 const size_t expected_min_fields = 2; | 2963 const size_t expected_min_fields = 2; |
2964 if (fields.size() < expected_min_fields) { | 2964 if (fields.size() < expected_min_fields) { |
2965 return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); | 2965 return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); |
2966 } | 2966 } |
2967 std::string payload_type_value; | 2967 std::string payload_type_value; |
2968 if (!GetValue(fields[0], kAttributeRtpmap, &payload_type_value, error)) { | 2968 if (!GetValue(fields[0], kAttributeRtpmap, &payload_type_value, error)) { |
2969 return false; | 2969 return false; |
2970 } | 2970 } |
2971 int payload_type = 0; | 2971 int payload_type = 0; |
2972 if (!GetPayloadTypeFromString(line, payload_type_value, &payload_type, | 2972 if (!GetPayloadTypeFromString(line, payload_type_value, &payload_type, |
2973 error)) { | 2973 error)) { |
2974 return false; | 2974 return false; |
2975 } | 2975 } |
2976 | 2976 |
2977 // Set the preference order depending on the order of the pl type in the | 2977 if (std::find(payload_types.begin(), payload_types.end(), payload_type) == |
2978 // <fmt> of the m-line. | 2978 payload_types.end()) { |
2979 const int preference = codec_preference.end() - | |
2980 std::find(codec_preference.begin(), codec_preference.end(), | |
2981 payload_type); | |
2982 if (preference == 0) { | |
2983 LOG(LS_WARNING) << "Ignore rtpmap line that did not appear in the " | 2979 LOG(LS_WARNING) << "Ignore rtpmap line that did not appear in the " |
2984 << "<fmt> of the m-line: " << line; | 2980 << "<fmt> of the m-line: " << line; |
2985 return true; | 2981 return true; |
2986 } | 2982 } |
2987 const std::string& encoder = fields[1]; | 2983 const std::string& encoder = fields[1]; |
2988 std::vector<std::string> codec_params; | 2984 std::vector<std::string> codec_params; |
2989 rtc::split(encoder, '/', &codec_params); | 2985 rtc::split(encoder, '/', &codec_params); |
2990 // <encoding name>/<clock rate>[/<encodingparameters>] | 2986 // <encoding name>/<clock rate>[/<encodingparameters>] |
2991 // 2 mandatory fields | 2987 // 2 mandatory fields |
2992 if (codec_params.size() < 2 || codec_params.size() > 3) { | 2988 if (codec_params.size() < 2 || codec_params.size() > 3) { |
2993 return ParseFailed(line, | 2989 return ParseFailed(line, |
2994 "Expected format \"<encoding name>/<clock rate>" | 2990 "Expected format \"<encoding name>/<clock rate>" |
2995 "[/<encodingparameters>]\".", | 2991 "[/<encodingparameters>]\".", |
2996 error); | 2992 error); |
2997 } | 2993 } |
2998 const std::string& encoding_name = codec_params[0]; | 2994 const std::string& encoding_name = codec_params[0]; |
2999 int clock_rate = 0; | 2995 int clock_rate = 0; |
3000 if (!GetValueFromString(line, codec_params[1], &clock_rate, error)) { | 2996 if (!GetValueFromString(line, codec_params[1], &clock_rate, error)) { |
3001 return false; | 2997 return false; |
3002 } | 2998 } |
3003 if (media_type == cricket::MEDIA_TYPE_VIDEO) { | 2999 if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
3004 VideoContentDescription* video_desc = | 3000 VideoContentDescription* video_desc = |
3005 static_cast<VideoContentDescription*>(media_desc); | 3001 static_cast<VideoContentDescription*>(media_desc); |
3006 // TODO: We will send resolution in SDP. For now use | 3002 // TODO: We will send resolution in SDP. For now use |
3007 // JsepSessionDescription::kMaxVideoCodecWidth and kMaxVideoCodecHeight. | 3003 // JsepSessionDescription::kMaxVideoCodecWidth and kMaxVideoCodecHeight. |
3008 UpdateCodec(payload_type, encoding_name, | 3004 UpdateCodec(payload_type, encoding_name, |
3009 JsepSessionDescription::kMaxVideoCodecWidth, | 3005 JsepSessionDescription::kMaxVideoCodecWidth, |
3010 JsepSessionDescription::kMaxVideoCodecHeight, | 3006 JsepSessionDescription::kMaxVideoCodecHeight, |
3011 JsepSessionDescription::kDefaultVideoCodecFramerate, | 3007 JsepSessionDescription::kDefaultVideoCodecFramerate, |
3012 preference, video_desc); | 3008 video_desc); |
3013 } else if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 3009 } else if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
3014 // RFC 4566 | 3010 // RFC 4566 |
3015 // For audio streams, <encoding parameters> indicates the number | 3011 // For audio streams, <encoding parameters> indicates the number |
3016 // of audio channels. This parameter is OPTIONAL and may be | 3012 // of audio channels. This parameter is OPTIONAL and may be |
3017 // omitted if the number of channels is one, provided that no | 3013 // omitted if the number of channels is one, provided that no |
3018 // additional parameters are needed. | 3014 // additional parameters are needed. |
3019 size_t channels = 1; | 3015 size_t channels = 1; |
3020 if (codec_params.size() == 3) { | 3016 if (codec_params.size() == 3) { |
3021 if (!GetValueFromString(line, codec_params[2], &channels, error)) { | 3017 if (!GetValueFromString(line, codec_params[2], &channels, error)) { |
3022 return false; | 3018 return false; |
3023 } | 3019 } |
3024 } | 3020 } |
3025 int bitrate = 0; | 3021 int bitrate = 0; |
3026 // The default behavior for ISAC (bitrate == 0) in webrtcvoiceengine.cc | 3022 // The default behavior for ISAC (bitrate == 0) in webrtcvoiceengine.cc |
3027 // (specifically FindWebRtcCodec) is bandwidth-adaptive variable bitrate. | 3023 // (specifically FindWebRtcCodec) is bandwidth-adaptive variable bitrate. |
3028 // The bandwidth adaptation doesn't always work well, so this code | 3024 // The bandwidth adaptation doesn't always work well, so this code |
3029 // sets a fixed target bitrate instead. | 3025 // sets a fixed target bitrate instead. |
3030 if (_stricmp(encoding_name.c_str(), kIsacCodecName) == 0) { | 3026 if (_stricmp(encoding_name.c_str(), kIsacCodecName) == 0) { |
3031 if (clock_rate <= 16000) { | 3027 if (clock_rate <= 16000) { |
3032 bitrate = kIsacWbDefaultRate; | 3028 bitrate = kIsacWbDefaultRate; |
3033 } else { | 3029 } else { |
3034 bitrate = kIsacSwbDefaultRate; | 3030 bitrate = kIsacSwbDefaultRate; |
3035 } | 3031 } |
3036 } | 3032 } |
3037 AudioContentDescription* audio_desc = | 3033 AudioContentDescription* audio_desc = |
3038 static_cast<AudioContentDescription*>(media_desc); | 3034 static_cast<AudioContentDescription*>(media_desc); |
3039 UpdateCodec(payload_type, encoding_name, clock_rate, bitrate, channels, | 3035 UpdateCodec(payload_type, encoding_name, clock_rate, bitrate, channels, |
3040 preference, audio_desc); | 3036 audio_desc); |
3041 } else if (media_type == cricket::MEDIA_TYPE_DATA) { | 3037 } else if (media_type == cricket::MEDIA_TYPE_DATA) { |
3042 DataContentDescription* data_desc = | 3038 DataContentDescription* data_desc = |
3043 static_cast<DataContentDescription*>(media_desc); | 3039 static_cast<DataContentDescription*>(media_desc); |
3044 data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name, | 3040 data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name)); |
3045 preference)); | |
3046 } | 3041 } |
3047 return true; | 3042 return true; |
3048 } | 3043 } |
3049 | 3044 |
3050 bool ParseFmtpParam(const std::string& line, std::string* parameter, | 3045 bool ParseFmtpParam(const std::string& line, std::string* parameter, |
3051 std::string* value, SdpParseError* error) { | 3046 std::string* value, SdpParseError* error) { |
3052 if (!rtc::tokenize_first(line, kSdpDelimiterEqual, parameter, value)) { | 3047 if (!rtc::tokenize_first(line, kSdpDelimiterEqual, parameter, value)) { |
3053 ParseFailed(line, "Unable to parse fmtp parameter. \'=\' missing.", error); | 3048 ParseFailed(line, "Unable to parse fmtp parameter. \'=\' missing.", error); |
3054 return false; | 3049 return false; |
3055 } | 3050 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3156 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( | 3151 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( |
3157 media_desc, payload_type, feedback_param); | 3152 media_desc, payload_type, feedback_param); |
3158 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | 3153 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
3159 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( | 3154 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( |
3160 media_desc, payload_type, feedback_param); | 3155 media_desc, payload_type, feedback_param); |
3161 } | 3156 } |
3162 return true; | 3157 return true; |
3163 } | 3158 } |
3164 | 3159 |
3165 } // namespace webrtc | 3160 } // namespace webrtc |
OLD | NEW |