Chromium Code Reviews| Index: webrtc/call/call.cc | 
| diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc | 
| index 20daba88dfee9f71e9e57ea42801c01b3945fbd2..b18695f62ba38b9de023e635923761d7c938a3c9 100644 | 
| --- a/webrtc/call/call.cc | 
| +++ b/webrtc/call/call.cc | 
| @@ -24,6 +24,7 @@ | 
| #include "webrtc/base/checks.h" | 
| #include "webrtc/base/constructormagic.h" | 
| #include "webrtc/base/logging.h" | 
| +#include "webrtc/base/optional.h" | 
| #include "webrtc/base/task_queue.h" | 
| #include "webrtc/base/thread_annotations.h" | 
| #include "webrtc/base/thread_checker.h" | 
| @@ -39,6 +40,8 @@ | 
| #include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h" | 
| #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | 
| #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 
| +#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" | 
| +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 
| #include "webrtc/modules/utility/include/process_thread.h" | 
| #include "webrtc/system_wrappers/include/clock.h" | 
| #include "webrtc/system_wrappers/include/cpu_info.h" | 
| @@ -154,6 +157,12 @@ class Call : public webrtc::Call, | 
| return nullptr; | 
| } | 
| + rtc::Optional<RtpPacketReceived> ParseRtpPacket( | 
| + const uint8_t* packet, | 
| + size_t length, | 
| + const PacketTime& packet_time, | 
| + const RtpHeaderExtensionMap* rtp_header_extensions); | 
| + | 
| void UpdateSendHistograms() EXCLUSIVE_LOCKS_REQUIRED(&bitrate_crit_); | 
| void UpdateReceiveHistograms(); | 
| void UpdateHistograms(); | 
| @@ -192,6 +201,14 @@ class Call : public webrtc::Call, | 
| std::map<std::string, AudioReceiveStream*> sync_stream_mapping_ | 
| GUARDED_BY(receive_crit_); | 
| + // Registered RTP header extensions for each stream. | 
| + // Note that RTP header extensions are negotiated per track ("m= line") in the | 
| + // SDP, but we have no notion of tracks at the Call level. We therefore store | 
| + // the RTP header extensions per SSRC instead, which leads to some storage | 
| + // overhead. | 
| + std::map<uint32_t, RtpHeaderExtensionMap> received_rtp_header_extensions_ | 
| + GUARDED_BY(receive_crit_); | 
| + | 
| std::unique_ptr<RWLockWrapper> send_crit_; | 
| // Audio and Video send streams are owned by the client that creates them. | 
| std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_); | 
| @@ -345,6 +362,26 @@ Call::~Call() { | 
| Trace::ReturnTrace(); | 
| } | 
| +rtc::Optional<RtpPacketReceived> Call::ParseRtpPacket( | 
| + const uint8_t* packet, | 
| + size_t length, | 
| + const PacketTime& packet_time, | 
| + const RtpHeaderExtensionMap* rtp_header_extensions) { | 
| + RtpPacketReceived parsed_packet(rtp_header_extensions); | 
| + if (!parsed_packet.Parse(packet, length)) | 
| + return rtc::Optional<RtpPacketReceived>(); | 
| + | 
| + int64_t arrival_time_ms; | 
| + if (packet_time.timestamp != -1) { | 
| + arrival_time_ms = (packet_time.timestamp + 500) / 1000; | 
| + } else { | 
| + arrival_time_ms = clock_->TimeInMilliseconds(); | 
| + } | 
| + parsed_packet.set_arrival_time_ms(arrival_time_ms); | 
| + | 
| + return rtc::Optional<RtpPacketReceived>(parsed_packet); | 
| +} | 
| + | 
| void Call::UpdateHistograms() { | 
| RTC_HISTOGRAM_COUNTS_100000( | 
| "WebRTC.Call.LifetimeInSeconds", | 
| @@ -481,10 +518,11 @@ webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream( | 
| RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); | 
| event_log_->LogAudioReceiveStreamConfig(config); | 
| AudioReceiveStream* receive_stream = new AudioReceiveStream( | 
| - &packet_router_, | 
| - // TODO(nisse): Used only when UseSendSideBwe(config) is true. | 
| - congestion_controller_->GetRemoteBitrateEstimator(true), config, | 
| - config_.audio_state, event_log_); | 
| + &packet_router_, congestion_controller_->GetRemoteBitrateEstimator( | 
| + CongestionController::UseSendSideBwe( | 
| 
 
brandtr
2016/12/12 13:51:08
Nisse: please check.
 
nisse-webrtc
2016/12/13 10:32:32
Maybe the TODO item was badly worded. The thing is
 
brandtr
2016/12/13 11:05:49
Got it, thanks. I've reverted this part of the pat
 
 | 
| + config.rtp.transport_cc, | 
| + RtpHeaderExtensionMap(config.rtp.extensions))), | 
| + config, config_.audio_state, event_log_); | 
| { | 
| WriteLockScoped write_lock(*receive_crit_); | 
| RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) == | 
| @@ -659,18 +697,37 @@ webrtc::FlexfecReceiveStream* Call::CreateFlexfecReceiveStream( | 
| const webrtc::FlexfecReceiveStream::Config& config) { | 
| TRACE_EVENT0("webrtc", "Call::CreateFlexfecReceiveStream"); | 
| RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); | 
| - FlexfecReceiveStream* receive_stream = new FlexfecReceiveStream(config, this); | 
| + | 
| + RtpHeaderExtensionMap rtp_header_extensions(config.rtp_header_extensions); | 
| + RecoveredPacketReceiver* recovered_packet_receiver = this; | 
| + RemoteBitrateEstimator* remote_bitrate_estimator = | 
| + congestion_controller_->GetRemoteBitrateEstimator( | 
| + CongestionController::UseSendSideBwe(config.transport_cc, | 
| + rtp_header_extensions)); | 
| + FlexfecReceiveStream* receive_stream = new FlexfecReceiveStream( | 
| + config, recovered_packet_receiver, remote_bitrate_estimator); | 
| { | 
| WriteLockScoped write_lock(*receive_crit_); | 
| + | 
| + RTC_DCHECK(flexfec_receive_streams_.find(receive_stream) == | 
| + flexfec_receive_streams_.end()); | 
| + flexfec_receive_streams_.insert(receive_stream); | 
| + | 
| for (auto ssrc : config.protected_media_ssrcs) | 
| flexfec_receive_ssrcs_media_.insert(std::make_pair(ssrc, receive_stream)); | 
| + | 
| RTC_DCHECK(flexfec_receive_ssrcs_protection_.find(config.remote_ssrc) == | 
| flexfec_receive_ssrcs_protection_.end()); | 
| flexfec_receive_ssrcs_protection_[config.remote_ssrc] = receive_stream; | 
| - flexfec_receive_streams_.insert(receive_stream); | 
| + | 
| + RTC_DCHECK(received_rtp_header_extensions_.find(config.remote_ssrc) == | 
| + received_rtp_header_extensions_.end()); | 
| + received_rtp_header_extensions_[config.remote_ssrc] = rtp_header_extensions; | 
| } | 
| + | 
| // TODO(brandtr): Store config in RtcEventLog here. | 
| + | 
| return receive_stream; | 
| } | 
| @@ -678,21 +735,21 @@ void Call::DestroyFlexfecReceiveStream( | 
| webrtc::FlexfecReceiveStream* receive_stream) { | 
| TRACE_EVENT0("webrtc", "Call::DestroyFlexfecReceiveStream"); | 
| RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); | 
| + | 
| RTC_DCHECK(receive_stream != nullptr); | 
| + | 
| // There exist no other derived classes of webrtc::FlexfecReceiveStream, | 
| // so this downcast is safe. | 
| FlexfecReceiveStream* receive_stream_impl = | 
| static_cast<FlexfecReceiveStream*>(receive_stream); | 
| + uint32_t ssrc = receive_stream_impl->GetConfig().remote_ssrc; | 
| + | 
| { | 
| WriteLockScoped write_lock(*receive_crit_); | 
| + | 
| + received_rtp_header_extensions_.erase(ssrc); | 
| + | 
| // Remove all SSRCs pointing to the FlexfecReceiveStream to be destroyed. | 
| - auto media_it = flexfec_receive_ssrcs_media_.begin(); | 
| - while (media_it != flexfec_receive_ssrcs_media_.end()) { | 
| - if (media_it->second == receive_stream_impl) | 
| - media_it = flexfec_receive_ssrcs_media_.erase(media_it); | 
| - else | 
| - ++media_it; | 
| - } | 
| auto prot_it = flexfec_receive_ssrcs_protection_.begin(); | 
| while (prot_it != flexfec_receive_ssrcs_protection_.end()) { | 
| if (prot_it->second == receive_stream_impl) | 
| @@ -700,8 +757,17 @@ void Call::DestroyFlexfecReceiveStream( | 
| else | 
| ++prot_it; | 
| } | 
| + auto media_it = flexfec_receive_ssrcs_media_.begin(); | 
| + while (media_it != flexfec_receive_ssrcs_media_.end()) { | 
| + if (media_it->second == receive_stream_impl) | 
| + media_it = flexfec_receive_ssrcs_media_.erase(media_it); | 
| + else | 
| + ++media_it; | 
| + } | 
| + | 
| flexfec_receive_streams_.erase(receive_stream_impl); | 
| } | 
| + | 
| delete receive_stream_impl; | 
| } | 
| @@ -1078,24 +1144,38 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, | 
| auto status = it->second->DeliverRtp(packet, length, packet_time) | 
| ? DELIVERY_OK | 
| : DELIVERY_PACKET_ERROR; | 
| - // Deliver media packets to FlexFEC subsystem. | 
| - auto it_bounds = flexfec_receive_ssrcs_media_.equal_range(ssrc); | 
| - for (auto it = it_bounds.first; it != it_bounds.second; ++it) | 
| - it->second->AddAndProcessReceivedPacket(packet, length); | 
| - if (status == DELIVERY_OK) | 
| - event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length); | 
| - return status; | 
| + // Deliver media packets to FlexFEC subsystem. RTP header extensions need | 
| + // not be parsed, as FlexFEC is oblivious to the semantic meaning of the | 
| + // packet contents beyond the 12 byte RTP base header. The BWE is fed | 
| + // information about these media packets from the regular media pipeline. | 
| + rtc::Optional<RtpPacketReceived> parsed_packet = | 
| + ParseRtpPacket(packet, length, packet_time, nullptr); | 
| + if (parsed_packet) { | 
| + auto it_bounds = flexfec_receive_ssrcs_media_.equal_range(ssrc); | 
| + for (auto it = it_bounds.first; it != it_bounds.second; ++it) | 
| + it->second->AddAndProcessReceivedPacket(*parsed_packet); | 
| + if (status == DELIVERY_OK) | 
| + event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length); | 
| + return status; | 
| + } | 
| } | 
| } | 
| if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | 
| auto it = flexfec_receive_ssrcs_protection_.find(ssrc); | 
| if (it != flexfec_receive_ssrcs_protection_.end()) { | 
| - auto status = it->second->AddAndProcessReceivedPacket(packet, length) | 
| - ? DELIVERY_OK | 
| - : DELIVERY_PACKET_ERROR; | 
| - if (status == DELIVERY_OK) | 
| - event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length); | 
| - return status; | 
| + const RtpHeaderExtensionMap& extensions = | 
| + received_rtp_header_extensions_[ssrc]; | 
| + rtc::Optional<RtpPacketReceived> parsed_packet = | 
| + ParseRtpPacket(packet, length, packet_time, &extensions); | 
| + if (parsed_packet) { | 
| + auto status = | 
| + it->second->AddAndProcessReceivedPacket(std::move(*parsed_packet)) | 
| + ? DELIVERY_OK | 
| + : DELIVERY_PACKET_ERROR; | 
| + if (status == DELIVERY_OK) | 
| + event_log_->LogRtpHeader(kIncomingPacket, media_type, packet, length); | 
| + return status; | 
| + } | 
| } | 
| } | 
| return DELIVERY_UNKNOWN_SSRC; |