 Chromium Code Reviews
 Chromium Code Reviews Issue 2511703002:
  Wire up FlexFEC in VideoEngine2.  (Closed)
    
  
    Issue 2511703002:
  Wire up FlexFEC in VideoEngine2.  (Closed) 
  | 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 |