OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 20 matching lines...) Expand all Loading... | |
31 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" | 31 #include "webrtc/media/engine/webrtcvideoencoderfactory.h" |
32 #include "webrtc/media/engine/webrtcvoiceengine.h" | 32 #include "webrtc/media/engine/webrtcvoiceengine.h" |
33 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" | 33 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" |
34 #include "webrtc/system_wrappers/include/field_trial.h" | 34 #include "webrtc/system_wrappers/include/field_trial.h" |
35 #include "webrtc/video_decoder.h" | 35 #include "webrtc/video_decoder.h" |
36 #include "webrtc/video_encoder.h" | 36 #include "webrtc/video_encoder.h" |
37 | 37 |
38 namespace cricket { | 38 namespace cricket { |
39 namespace { | 39 namespace { |
40 | 40 |
41 // Three things happen when the FlexFEC field trial is enabled: | |
42 // 1) FlexFEC is exposed in the default codec list, eventually showing up | |
43 // in the default SDP. | |
44 // 2) FlexFEC send parameters are set in the VideoSendStream config. | |
45 // 3) FlexFEC receive parameters are set in the FlexfecReceiveStream config, | |
46 // and the corresponding object is instantiated. | |
47 const char kFlexfecFieldTrialName[] = "WebRTC-FlexFEC-03"; | |
48 | |
49 bool IsFlexfecEnabled() { | |
50 return webrtc::field_trial::FindFullName(kFlexfecFieldTrialName) == "Enabled"; | |
51 } | |
52 | |
41 // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. | 53 // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. |
42 class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { | 54 class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { |
43 public: | 55 public: |
44 // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned | 56 // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned |
45 // by e.g. PeerConnectionFactory. | 57 // by e.g. PeerConnectionFactory. |
46 explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory) | 58 explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory) |
47 : factory_(factory) {} | 59 : factory_(factory) {} |
48 virtual ~EncoderFactoryAdapter() {} | 60 virtual ~EncoderFactoryAdapter() {} |
49 | 61 |
50 // Implement webrtc::VideoEncoderFactory. | 62 // Implement webrtc::VideoEncoderFactory. |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
632 AppendVideoCodecs(internal_codecs, &unified_codecs); | 644 AppendVideoCodecs(internal_codecs, &unified_codecs); |
633 | 645 |
634 if (external_encoder_factory != nullptr) { | 646 if (external_encoder_factory != nullptr) { |
635 const std::vector<VideoCodec>& external_codecs = | 647 const std::vector<VideoCodec>& external_codecs = |
636 external_encoder_factory->supported_codecs(); | 648 external_encoder_factory->supported_codecs(); |
637 AppendVideoCodecs(external_codecs, &unified_codecs); | 649 AppendVideoCodecs(external_codecs, &unified_codecs); |
638 LOG(LS_INFO) << "Codecs supported by the external encoder factory: " | 650 LOG(LS_INFO) << "Codecs supported by the external encoder factory: " |
639 << CodecVectorToString(external_codecs); | 651 << CodecVectorToString(external_codecs); |
640 } | 652 } |
641 | 653 |
654 // TODO(brandtr): Move this block of code to InternalEncoderFactory ctor | |
655 // when FlexFEC is no longer behind a field trial. Until then, we need | |
656 // to have this block here, since the singleton encoder factory does | |
657 // not respect the ScopedFieldTrials that we use in the tests. | |
brandtr
2016/11/17 17:28:58
magjed: Is this OK?
Further, checking the field t
magjed_webrtc
2016/11/18 14:28:00
This won't work because the payload won't be assig
brandtr
2016/11/21 08:52:03
I see, moving to the ctor. (Thanks for changing yo
| |
658 if (IsFlexfecEnabled()) { | |
659 cricket::VideoCodec flexfec_codec(kFlexfecCodecName); | |
660 // This value is currently arbitrarily set to 10 seconds. (The unit | |
661 // is microseconds.) This parameter MUST be present in the SDP, but | |
662 // we never use the actual value anywhere in our code however. | |
663 // TODO(brandtr): Consider honouring this value in the sender and receiver. | |
664 flexfec_codec.SetParam(kFlexfecFmtpRepairWindow, "10000000"); | |
665 unified_codecs.push_back(flexfec_codec); | |
666 LOG(LS_INFO) << "Codec added by field trial: " << flexfec_codec.ToString(); | |
667 } | |
668 | |
642 return unified_codecs; | 669 return unified_codecs; |
643 } | 670 } |
644 | 671 |
645 WebRtcVideoChannel2::WebRtcVideoChannel2( | 672 WebRtcVideoChannel2::WebRtcVideoChannel2( |
646 webrtc::Call* call, | 673 webrtc::Call* call, |
647 const MediaConfig& config, | 674 const MediaConfig& config, |
648 const VideoOptions& options, | 675 const VideoOptions& options, |
649 WebRtcVideoEncoderFactory* external_encoder_factory, | 676 WebRtcVideoEncoderFactory* external_encoder_factory, |
650 WebRtcVideoDecoderFactory* external_decoder_factory) | 677 WebRtcVideoDecoderFactory* external_decoder_factory) |
651 : VideoMediaChannel(config), | 678 : VideoMediaChannel(config), |
(...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1189 receive_streams_.erase(prev_stream); | 1216 receive_streams_.erase(prev_stream); |
1190 } | 1217 } |
1191 | 1218 |
1192 if (!ValidateReceiveSsrcAvailability(sp)) | 1219 if (!ValidateReceiveSsrcAvailability(sp)) |
1193 return false; | 1220 return false; |
1194 | 1221 |
1195 for (uint32_t used_ssrc : sp.ssrcs) | 1222 for (uint32_t used_ssrc : sp.ssrcs) |
1196 receive_ssrcs_.insert(used_ssrc); | 1223 receive_ssrcs_.insert(used_ssrc); |
1197 | 1224 |
1198 webrtc::VideoReceiveStream::Config config(this); | 1225 webrtc::VideoReceiveStream::Config config(this); |
1199 ConfigureReceiverRtp(&config, sp); | 1226 webrtc::FlexfecConfig flexfec_config; |
1227 ConfigureReceiverRtp(&config, &flexfec_config, sp); | |
1200 | 1228 |
1201 // Set up A/V sync group based on sync label. | 1229 // Set up A/V sync group based on sync label. |
1202 config.sync_group = sp.sync_label; | 1230 config.sync_group = sp.sync_label; |
1203 | 1231 |
1204 config.rtp.remb = send_codec_ ? HasRemb(send_codec_->codec) : false; | 1232 config.rtp.remb = send_codec_ ? HasRemb(send_codec_->codec) : false; |
1205 config.rtp.transport_cc = | 1233 config.rtp.transport_cc = |
1206 send_codec_ ? HasTransportCc(send_codec_->codec) : false; | 1234 send_codec_ ? HasTransportCc(send_codec_->codec) : false; |
1207 config.disable_prerenderer_smoothing = | 1235 config.disable_prerenderer_smoothing = |
1208 video_config_.disable_prerenderer_smoothing; | 1236 video_config_.disable_prerenderer_smoothing; |
1209 | 1237 |
1210 receive_streams_[ssrc] = new WebRtcVideoReceiveStream( | 1238 receive_streams_[ssrc] = new WebRtcVideoReceiveStream( |
1211 call_, sp, std::move(config), external_decoder_factory_, default_stream, | 1239 call_, sp, std::move(config), external_decoder_factory_, default_stream, |
1212 recv_codecs_); | 1240 recv_codecs_, flexfec_config); |
1213 | 1241 |
1214 return true; | 1242 return true; |
1215 } | 1243 } |
1216 | 1244 |
1217 void WebRtcVideoChannel2::ConfigureReceiverRtp( | 1245 void WebRtcVideoChannel2::ConfigureReceiverRtp( |
1218 webrtc::VideoReceiveStream::Config* config, | 1246 webrtc::VideoReceiveStream::Config* config, |
1247 webrtc::FlexfecConfig* flexfec_config, | |
1219 const StreamParams& sp) const { | 1248 const StreamParams& sp) const { |
1220 uint32_t ssrc = sp.first_ssrc(); | 1249 uint32_t ssrc = sp.first_ssrc(); |
1221 | 1250 |
1222 config->rtp.remote_ssrc = ssrc; | 1251 config->rtp.remote_ssrc = ssrc; |
1223 config->rtp.local_ssrc = rtcp_receiver_report_ssrc_; | 1252 config->rtp.local_ssrc = rtcp_receiver_report_ssrc_; |
1224 | 1253 |
1225 config->rtp.extensions = recv_rtp_extensions_; | 1254 config->rtp.extensions = recv_rtp_extensions_; |
1226 // Whether or not the receive stream sends reduced size RTCP is determined | 1255 // Whether or not the receive stream sends reduced size RTCP is determined |
1227 // by the send params. | 1256 // by the send params. |
1228 // TODO(deadbeef): Once we change "send_params" to "sender_params" and | 1257 // TODO(deadbeef): Once we change "send_params" to "sender_params" and |
(...skipping 18 matching lines...) Expand all Loading... | |
1247 for (size_t i = 0; i < recv_codecs_.size(); ++i) { | 1276 for (size_t i = 0; i < recv_codecs_.size(); ++i) { |
1248 uint32_t rtx_ssrc; | 1277 uint32_t rtx_ssrc; |
1249 if (recv_codecs_[i].rtx_payload_type != -1 && | 1278 if (recv_codecs_[i].rtx_payload_type != -1 && |
1250 sp.GetFidSsrc(ssrc, &rtx_ssrc)) { | 1279 sp.GetFidSsrc(ssrc, &rtx_ssrc)) { |
1251 webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx = | 1280 webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx = |
1252 config->rtp.rtx[recv_codecs_[i].codec.id]; | 1281 config->rtp.rtx[recv_codecs_[i].codec.id]; |
1253 rtx.ssrc = rtx_ssrc; | 1282 rtx.ssrc = rtx_ssrc; |
1254 rtx.payload_type = recv_codecs_[i].rtx_payload_type; | 1283 rtx.payload_type = recv_codecs_[i].rtx_payload_type; |
1255 } | 1284 } |
1256 } | 1285 } |
1286 | |
1287 // TODO(brandtr): This code needs to be generalized when we add support for | |
1288 // multistream protection. | |
1289 uint32_t flexfec_ssrc; | |
1290 if (sp.GetFecFrSsrc(ssrc, &flexfec_ssrc)) { | |
1291 flexfec_config->flexfec_ssrc = flexfec_ssrc; | |
1292 flexfec_config->protected_media_ssrcs = {ssrc}; | |
1293 } | |
1257 } | 1294 } |
1258 | 1295 |
1259 bool WebRtcVideoChannel2::RemoveRecvStream(uint32_t ssrc) { | 1296 bool WebRtcVideoChannel2::RemoveRecvStream(uint32_t ssrc) { |
1260 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; | 1297 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |
1261 if (ssrc == 0) { | 1298 if (ssrc == 0) { |
1262 LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; | 1299 LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; |
1263 return false; | 1300 return false; |
1264 } | 1301 } |
1265 | 1302 |
1266 rtc::CritScope stream_lock(&stream_crit_); | 1303 rtc::CritScope stream_lock(&stream_crit_); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1404 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) { | 1441 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) { |
1405 return; | 1442 return; |
1406 } | 1443 } |
1407 | 1444 |
1408 int payload_type = 0; | 1445 int payload_type = 0; |
1409 if (!GetRtpPayloadType(packet->cdata(), packet->size(), &payload_type)) { | 1446 if (!GetRtpPayloadType(packet->cdata(), packet->size(), &payload_type)) { |
1410 return; | 1447 return; |
1411 } | 1448 } |
1412 | 1449 |
1413 // See if this payload_type is registered as one that usually gets its own | 1450 // See if this payload_type is registered as one that usually gets its own |
1414 // SSRC (RTX) or at least is safe to drop either way (ULPFEC). If it is, and | 1451 // SSRC (RTX) or at least is safe to drop either way (FEC). If it is, and |
1415 // it wasn't handled above by DeliverPacket, that means we don't know what | 1452 // it wasn't handled above by DeliverPacket, that means we don't know what |
1416 // stream it associates with, and we shouldn't ever create an implicit channel | 1453 // stream it associates with, and we shouldn't ever create an implicit channel |
1417 // for these. | 1454 // for these. |
1418 for (auto& codec : recv_codecs_) { | 1455 for (auto& codec : recv_codecs_) { |
1419 if (payload_type == codec.rtx_payload_type || | 1456 if (payload_type == codec.rtx_payload_type || |
1420 payload_type == codec.ulpfec.red_rtx_payload_type || | 1457 payload_type == codec.ulpfec.red_rtx_payload_type || |
1421 payload_type == codec.ulpfec.ulpfec_payload_type) { | 1458 payload_type == codec.ulpfec.ulpfec_payload_type || |
1459 payload_type == codec.flexfec.flexfec_payload_type) { | |
1422 return; | 1460 return; |
1423 } | 1461 } |
1424 } | 1462 } |
1425 | 1463 |
1426 switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) { | 1464 switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) { |
1427 case UnsignalledSsrcHandler::kDropPacket: | 1465 case UnsignalledSsrcHandler::kDropPacket: |
1428 return; | 1466 return; |
1429 case UnsignalledSsrcHandler::kDeliverPacket: | 1467 case UnsignalledSsrcHandler::kDeliverPacket: |
1430 break; | 1468 break; |
1431 } | 1469 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1554 encoder_sink_(nullptr), | 1592 encoder_sink_(nullptr), |
1555 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1593 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
1556 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1594 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
1557 allocated_encoder_(nullptr, cricket::VideoCodec(), false), | 1595 allocated_encoder_(nullptr, cricket::VideoCodec(), false), |
1558 sending_(false), | 1596 sending_(false), |
1559 last_frame_timestamp_us_(0) { | 1597 last_frame_timestamp_us_(0) { |
1560 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1598 parameters_.config.rtp.max_packet_size = kVideoMtu; |
1561 parameters_.conference_mode = send_params.conference_mode; | 1599 parameters_.conference_mode = send_params.conference_mode; |
1562 | 1600 |
1563 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1601 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
1602 | |
1603 // RTX. | |
1564 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, | 1604 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
1565 ¶meters_.config.rtp.rtx.ssrcs); | 1605 ¶meters_.config.rtp.rtx.ssrcs); |
1606 | |
1607 // FlexFEC. | |
1608 // TODO(brandtr): This code needs to be generalized when we add support for | |
1609 // multistream protection. | |
1610 if (IsFlexfecEnabled()) { | |
1611 uint32_t flexfec_ssrc; | |
1612 bool flexfec_enabled = false; | |
1613 for (uint32_t primary_ssrc : parameters_.config.rtp.ssrcs) { | |
1614 if (sp.GetFecFrSsrc(primary_ssrc, &flexfec_ssrc)) { | |
1615 if (flexfec_enabled) { | |
1616 LOG(LS_INFO) << "Multiple FlexFEC streams proposed by remote, but " | |
1617 "our implementation only supports a single FlexFEC " | |
1618 "stream. Will not enable FlexFEC for proposed " | |
1619 "stream with SSRC: " | |
1620 << flexfec_ssrc << "."; | |
1621 continue; | |
1622 } | |
1623 | |
1624 flexfec_enabled = true; | |
1625 parameters_.config.rtp.flexfec.flexfec_ssrc = flexfec_ssrc; | |
1626 parameters_.config.rtp.flexfec.protected_media_ssrcs = {primary_ssrc}; | |
1627 } | |
1628 } | |
1629 } | |
1630 | |
1566 parameters_.config.rtp.c_name = sp.cname; | 1631 parameters_.config.rtp.c_name = sp.cname; |
1567 if (rtp_extensions) { | 1632 if (rtp_extensions) { |
1568 parameters_.config.rtp.extensions = *rtp_extensions; | 1633 parameters_.config.rtp.extensions = *rtp_extensions; |
1569 } | 1634 } |
1570 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size | 1635 parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size |
1571 ? webrtc::RtcpMode::kReducedSize | 1636 ? webrtc::RtcpMode::kReducedSize |
1572 : webrtc::RtcpMode::kCompound; | 1637 : webrtc::RtcpMode::kCompound; |
1573 if (codec_settings) { | 1638 if (codec_settings) { |
1574 SetCodec(*codec_settings); | 1639 SetCodec(*codec_settings); |
1575 } | 1640 } |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1737 parameters_.config.encoder_settings.encoder = new_encoder.encoder; | 1802 parameters_.config.encoder_settings.encoder = new_encoder.encoder; |
1738 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; | 1803 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; |
1739 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; | 1804 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; |
1740 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; | 1805 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; |
1741 if (new_encoder.external) { | 1806 if (new_encoder.external) { |
1742 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); | 1807 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); |
1743 parameters_.config.encoder_settings.internal_source = | 1808 parameters_.config.encoder_settings.internal_source = |
1744 external_encoder_factory_->EncoderTypeHasInternalSource(type); | 1809 external_encoder_factory_->EncoderTypeHasInternalSource(type); |
1745 } | 1810 } |
1746 parameters_.config.rtp.ulpfec = codec_settings.ulpfec; | 1811 parameters_.config.rtp.ulpfec = codec_settings.ulpfec; |
1812 parameters_.config.rtp.flexfec.flexfec_payload_type = | |
1813 codec_settings.flexfec.flexfec_payload_type; | |
1747 | 1814 |
1748 // Set RTX payload type if RTX is enabled. | 1815 // Set RTX payload type if RTX is enabled. |
1749 if (!parameters_.config.rtp.rtx.ssrcs.empty()) { | 1816 if (!parameters_.config.rtp.rtx.ssrcs.empty()) { |
1750 if (codec_settings.rtx_payload_type == -1) { | 1817 if (codec_settings.rtx_payload_type == -1) { |
1751 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 1818 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
1752 "payload type. Ignoring."; | 1819 "payload type. Ignoring."; |
1753 parameters_.config.rtp.rtx.ssrcs.clear(); | 1820 parameters_.config.rtp.rtx.ssrcs.clear(); |
1754 } else { | 1821 } else { |
1755 parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type; | 1822 parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type; |
1756 } | 1823 } |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2112 // Call stream_->Start() if necessary conditions are met. | 2179 // Call stream_->Start() if necessary conditions are met. |
2113 UpdateSendState(); | 2180 UpdateSendState(); |
2114 } | 2181 } |
2115 | 2182 |
2116 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( | 2183 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
2117 webrtc::Call* call, | 2184 webrtc::Call* call, |
2118 const StreamParams& sp, | 2185 const StreamParams& sp, |
2119 webrtc::VideoReceiveStream::Config config, | 2186 webrtc::VideoReceiveStream::Config config, |
2120 WebRtcVideoDecoderFactory* external_decoder_factory, | 2187 WebRtcVideoDecoderFactory* external_decoder_factory, |
2121 bool default_stream, | 2188 bool default_stream, |
2122 const std::vector<VideoCodecSettings>& recv_codecs) | 2189 const std::vector<VideoCodecSettings>& recv_codecs, |
2190 const webrtc::FlexfecConfig& flexfec_config) | |
2123 : call_(call), | 2191 : call_(call), |
2124 stream_params_(sp), | 2192 stream_params_(sp), |
2125 stream_(NULL), | 2193 stream_(NULL), |
2126 default_stream_(default_stream), | 2194 default_stream_(default_stream), |
2127 config_(std::move(config)), | 2195 config_(std::move(config)), |
2196 flexfec_config_(flexfec_config), | |
2197 flexfec_stream_(nullptr), | |
2128 external_decoder_factory_(external_decoder_factory), | 2198 external_decoder_factory_(external_decoder_factory), |
2129 sink_(NULL), | 2199 sink_(NULL), |
2130 first_frame_timestamp_(-1), | 2200 first_frame_timestamp_(-1), |
2131 estimated_remote_start_ntp_time_ms_(0) { | 2201 estimated_remote_start_ntp_time_ms_(0) { |
2132 config_.renderer = this; | 2202 config_.renderer = this; |
2133 std::vector<AllocatedDecoder> old_decoders; | 2203 std::vector<AllocatedDecoder> old_decoders; |
2134 ConfigureCodecs(recv_codecs, &old_decoders); | 2204 ConfigureCodecs(recv_codecs, &old_decoders); |
2135 RecreateWebRtcStream(); | 2205 RecreateWebRtcStream(); |
2136 RTC_DCHECK(old_decoders.empty()); | 2206 RTC_DCHECK(old_decoders.empty()); |
2137 } | 2207 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2246 webrtc::VideoReceiveStream::Decoder decoder; | 2316 webrtc::VideoReceiveStream::Decoder decoder; |
2247 decoder.decoder = allocated_decoder.decoder; | 2317 decoder.decoder = allocated_decoder.decoder; |
2248 decoder.payload_type = recv_codecs[i].codec.id; | 2318 decoder.payload_type = recv_codecs[i].codec.id; |
2249 decoder.payload_name = recv_codecs[i].codec.name; | 2319 decoder.payload_name = recv_codecs[i].codec.name; |
2250 ConfigureDecoderSpecifics(&decoder, recv_codecs[i].codec); | 2320 ConfigureDecoderSpecifics(&decoder, recv_codecs[i].codec); |
2251 config_.decoders.push_back(decoder); | 2321 config_.decoders.push_back(decoder); |
2252 } | 2322 } |
2253 | 2323 |
2254 // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. | 2324 // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. |
2255 config_.rtp.ulpfec = recv_codecs.front().ulpfec; | 2325 config_.rtp.ulpfec = recv_codecs.front().ulpfec; |
2326 flexfec_config_.flexfec_payload_type = | |
2327 recv_codecs.front().flexfec.flexfec_payload_type; | |
2256 config_.rtp.nack.rtp_history_ms = | 2328 config_.rtp.nack.rtp_history_ms = |
2257 HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; | 2329 HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; |
2258 } | 2330 } |
2259 | 2331 |
2260 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc( | 2332 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc( |
2261 uint32_t local_ssrc) { | 2333 uint32_t local_ssrc) { |
2262 // TODO(pbos): Consider turning this sanity check into a RTC_DCHECK. You | 2334 // TODO(pbos): Consider turning this sanity check into a RTC_DCHECK. You |
2263 // should not be able to create a sender with the same SSRC as a receiver, but | 2335 // should not be able to create a sender with the same SSRC as a receiver, but |
2264 // right now this can't be done due to unittests depending on receiving what | 2336 // right now this can't be done due to unittests depending on receiving what |
2265 // they are sending from the same MediaChannel. | 2337 // they are sending from the same MediaChannel. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2317 needs_recreation = true; | 2389 needs_recreation = true; |
2318 } | 2390 } |
2319 if (needs_recreation) { | 2391 if (needs_recreation) { |
2320 LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvParameters"; | 2392 LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvParameters"; |
2321 RecreateWebRtcStream(); | 2393 RecreateWebRtcStream(); |
2322 ClearDecoders(&old_decoders); | 2394 ClearDecoders(&old_decoders); |
2323 } | 2395 } |
2324 } | 2396 } |
2325 | 2397 |
2326 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { | 2398 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { |
2327 if (stream_ != NULL) { | 2399 if (flexfec_stream_) { |
2400 call_->DestroyFlexfecReceiveStream(flexfec_stream_); | |
2401 flexfec_stream_ = nullptr; | |
2402 } | |
2403 if (stream_) { | |
2328 call_->DestroyVideoReceiveStream(stream_); | 2404 call_->DestroyVideoReceiveStream(stream_); |
2329 } | 2405 } |
2330 stream_ = call_->CreateVideoReceiveStream(config_.Copy()); | 2406 stream_ = call_->CreateVideoReceiveStream(config_.Copy()); |
2331 stream_->Start(); | 2407 stream_->Start(); |
2408 if (IsFlexfecEnabled() && flexfec_config_.IsCompleteAndEnabled()) { | |
2409 flexfec_stream_ = call_->CreateFlexfecReceiveStream(flexfec_config_); | |
2410 flexfec_stream_->Start(); | |
2411 } | |
2332 } | 2412 } |
2333 | 2413 |
2334 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders( | 2414 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders( |
2335 std::vector<AllocatedDecoder>* allocated_decoders) { | 2415 std::vector<AllocatedDecoder>* allocated_decoders) { |
2336 for (size_t i = 0; i < allocated_decoders->size(); ++i) { | 2416 for (size_t i = 0; i < allocated_decoders->size(); ++i) { |
2337 if ((*allocated_decoders)[i].external) { | 2417 if ((*allocated_decoders)[i].external) { |
2338 external_decoder_factory_->DestroyVideoDecoder( | 2418 external_decoder_factory_->DestroyVideoDecoder( |
2339 (*allocated_decoders)[i].external_decoder); | 2419 (*allocated_decoders)[i].external_decoder); |
2340 } | 2420 } |
2341 delete (*allocated_decoders)[i].decoder; | 2421 delete (*allocated_decoders)[i].decoder; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2436 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); | 2516 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); |
2437 | 2517 |
2438 return info; | 2518 return info; |
2439 } | 2519 } |
2440 | 2520 |
2441 WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() | 2521 WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() |
2442 : rtx_payload_type(-1) {} | 2522 : rtx_payload_type(-1) {} |
2443 | 2523 |
2444 bool WebRtcVideoChannel2::VideoCodecSettings::operator==( | 2524 bool WebRtcVideoChannel2::VideoCodecSettings::operator==( |
2445 const WebRtcVideoChannel2::VideoCodecSettings& other) const { | 2525 const WebRtcVideoChannel2::VideoCodecSettings& other) const { |
2446 return codec == other.codec && | 2526 return codec == other.codec && ulpfec == other.ulpfec && |
2447 ulpfec.ulpfec_payload_type == other.ulpfec.ulpfec_payload_type && | 2527 flexfec == other.flexfec && rtx_payload_type == other.rtx_payload_type; |
2448 ulpfec.red_payload_type == other.ulpfec.red_payload_type && | |
2449 ulpfec.red_rtx_payload_type == other.ulpfec.red_rtx_payload_type && | |
2450 rtx_payload_type == other.rtx_payload_type; | |
2451 } | 2528 } |
2452 | 2529 |
2453 bool WebRtcVideoChannel2::VideoCodecSettings::operator!=( | 2530 bool WebRtcVideoChannel2::VideoCodecSettings::operator!=( |
2454 const WebRtcVideoChannel2::VideoCodecSettings& other) const { | 2531 const WebRtcVideoChannel2::VideoCodecSettings& other) const { |
2455 return !(*this == other); | 2532 return !(*this == other); |
2456 } | 2533 } |
2457 | 2534 |
2458 std::vector<WebRtcVideoChannel2::VideoCodecSettings> | 2535 std::vector<WebRtcVideoChannel2::VideoCodecSettings> |
2459 WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { | 2536 WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { |
2460 RTC_DCHECK(!codecs.empty()); | 2537 RTC_DCHECK(!codecs.empty()); |
2461 | 2538 |
2462 std::vector<VideoCodecSettings> video_codecs; | 2539 std::vector<VideoCodecSettings> video_codecs; |
2463 std::map<int, bool> payload_used; | 2540 std::map<int, bool> payload_used; |
2464 std::map<int, VideoCodec::CodecType> payload_codec_type; | 2541 std::map<int, VideoCodec::CodecType> payload_codec_type; |
2465 // |rtx_mapping| maps video payload type to rtx payload type. | 2542 // |rtx_mapping| maps video payload type to rtx payload type. |
2466 std::map<int, int> rtx_mapping; | 2543 std::map<int, int> rtx_mapping; |
2467 | 2544 |
2468 webrtc::UlpfecConfig ulpfec_config; | 2545 webrtc::UlpfecConfig ulpfec_config; |
2546 int flexfec_payload_type = -1; | |
2469 | 2547 |
2470 for (size_t i = 0; i < codecs.size(); ++i) { | 2548 for (size_t i = 0; i < codecs.size(); ++i) { |
2471 const VideoCodec& in_codec = codecs[i]; | 2549 const VideoCodec& in_codec = codecs[i]; |
2472 int payload_type = in_codec.id; | 2550 int payload_type = in_codec.id; |
2473 | 2551 |
2474 if (payload_used[payload_type]) { | 2552 if (payload_used[payload_type]) { |
2475 LOG(LS_ERROR) << "Payload type already registered: " | 2553 LOG(LS_ERROR) << "Payload type already registered: " |
2476 << in_codec.ToString(); | 2554 << in_codec.ToString(); |
2477 return std::vector<VideoCodecSettings>(); | 2555 return std::vector<VideoCodecSettings>(); |
2478 } | 2556 } |
2479 payload_used[payload_type] = true; | 2557 payload_used[payload_type] = true; |
2480 payload_codec_type[payload_type] = in_codec.GetCodecType(); | 2558 payload_codec_type[payload_type] = in_codec.GetCodecType(); |
2481 | 2559 |
2482 switch (in_codec.GetCodecType()) { | 2560 switch (in_codec.GetCodecType()) { |
2483 case VideoCodec::CODEC_RED: { | 2561 case VideoCodec::CODEC_RED: { |
2484 // RED payload type, should not have duplicates. | 2562 // RED payload type, should not have duplicates. |
2485 RTC_DCHECK(ulpfec_config.red_payload_type == -1); | 2563 RTC_DCHECK_EQ(-1, ulpfec_config.red_payload_type); |
2486 ulpfec_config.red_payload_type = in_codec.id; | 2564 ulpfec_config.red_payload_type = in_codec.id; |
2487 continue; | 2565 continue; |
2488 } | 2566 } |
2489 | 2567 |
2490 case VideoCodec::CODEC_ULPFEC: { | 2568 case VideoCodec::CODEC_ULPFEC: { |
2491 // ULPFEC payload type, should not have duplicates. | 2569 // ULPFEC payload type, should not have duplicates. |
2492 RTC_DCHECK(ulpfec_config.ulpfec_payload_type == -1); | 2570 RTC_DCHECK_EQ(-1, ulpfec_config.ulpfec_payload_type); |
2493 ulpfec_config.ulpfec_payload_type = in_codec.id; | 2571 ulpfec_config.ulpfec_payload_type = in_codec.id; |
2494 continue; | 2572 continue; |
2495 } | 2573 } |
2496 | 2574 |
2497 case VideoCodec::CODEC_FLEXFEC: { | 2575 case VideoCodec::CODEC_FLEXFEC: { |
2498 // TODO(brandtr): To be implemented. | 2576 // FlexFEC payload type, should not have duplicates. |
2577 RTC_DCHECK_EQ(-1, flexfec_payload_type); | |
2578 flexfec_payload_type = in_codec.id; | |
2499 continue; | 2579 continue; |
2500 } | 2580 } |
2501 | 2581 |
2502 case VideoCodec::CODEC_RTX: { | 2582 case VideoCodec::CODEC_RTX: { |
2503 int associated_payload_type; | 2583 int associated_payload_type; |
2504 if (!in_codec.GetParam(kCodecParamAssociatedPayloadType, | 2584 if (!in_codec.GetParam(kCodecParamAssociatedPayloadType, |
2505 &associated_payload_type) || | 2585 &associated_payload_type) || |
2506 !IsValidRtpPayloadType(associated_payload_type)) { | 2586 !IsValidRtpPayloadType(associated_payload_type)) { |
2507 LOG(LS_ERROR) | 2587 LOG(LS_ERROR) |
2508 << "RTX codec with invalid or no associated payload type: " | 2588 << "RTX codec with invalid or no associated payload type: " |
(...skipping 29 matching lines...) Expand all Loading... | |
2538 return std::vector<VideoCodecSettings>(); | 2618 return std::vector<VideoCodecSettings>(); |
2539 } | 2619 } |
2540 | 2620 |
2541 if (it->first == ulpfec_config.red_payload_type) { | 2621 if (it->first == ulpfec_config.red_payload_type) { |
2542 ulpfec_config.red_rtx_payload_type = it->second; | 2622 ulpfec_config.red_rtx_payload_type = it->second; |
2543 } | 2623 } |
2544 } | 2624 } |
2545 | 2625 |
2546 for (size_t i = 0; i < video_codecs.size(); ++i) { | 2626 for (size_t i = 0; i < video_codecs.size(); ++i) { |
2547 video_codecs[i].ulpfec = ulpfec_config; | 2627 video_codecs[i].ulpfec = ulpfec_config; |
2628 video_codecs[i].flexfec.flexfec_payload_type = flexfec_payload_type; | |
2548 if (rtx_mapping[video_codecs[i].codec.id] != 0 && | 2629 if (rtx_mapping[video_codecs[i].codec.id] != 0 && |
2549 rtx_mapping[video_codecs[i].codec.id] != | 2630 rtx_mapping[video_codecs[i].codec.id] != |
2550 ulpfec_config.red_payload_type) { | 2631 ulpfec_config.red_payload_type) { |
2551 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2632 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
2552 } | 2633 } |
2553 } | 2634 } |
2554 | 2635 |
2555 return video_codecs; | 2636 return video_codecs; |
2556 } | 2637 } |
2557 | 2638 |
2558 } // namespace cricket | 2639 } // namespace cricket |
OLD | NEW |