OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 #include "webrtc/video/video_send_stream.h" | 10 #include "webrtc/video/video_send_stream.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 namespace { | 37 namespace { |
38 | 38 |
39 std::vector<RtpRtcp*> CreateRtpRtcpModules( | 39 std::vector<RtpRtcp*> CreateRtpRtcpModules( |
40 Transport* outgoing_transport, | 40 Transport* outgoing_transport, |
41 RtcpIntraFrameObserver* intra_frame_callback, | 41 RtcpIntraFrameObserver* intra_frame_callback, |
42 RtcpBandwidthObserver* bandwidth_callback, | 42 RtcpBandwidthObserver* bandwidth_callback, |
43 TransportFeedbackObserver* transport_feedback_callback, | 43 TransportFeedbackObserver* transport_feedback_callback, |
44 RtcpRttStats* rtt_stats, | 44 RtcpRttStats* rtt_stats, |
45 RtpPacketSender* paced_sender, | 45 RtpPacketSender* paced_sender, |
46 TransportSequenceNumberAllocator* transport_sequence_number_allocator, | 46 TransportSequenceNumberAllocator* transport_sequence_number_allocator, |
| 47 FlexfecSender* flexfec_sender, |
47 SendStatisticsProxy* stats_proxy, | 48 SendStatisticsProxy* stats_proxy, |
48 SendDelayStats* send_delay_stats, | 49 SendDelayStats* send_delay_stats, |
49 RtcEventLog* event_log, | 50 RtcEventLog* event_log, |
50 RateLimiter* retransmission_rate_limiter, | 51 RateLimiter* retransmission_rate_limiter, |
51 size_t num_modules) { | 52 size_t num_modules) { |
52 RTC_DCHECK_GT(num_modules, 0u); | 53 RTC_DCHECK_GT(num_modules, 0u); |
53 RtpRtcp::Configuration configuration; | 54 RtpRtcp::Configuration configuration; |
54 ReceiveStatistics* null_receive_statistics = configuration.receive_statistics; | 55 ReceiveStatistics* null_receive_statistics = configuration.receive_statistics; |
55 configuration.audio = false; | 56 configuration.audio = false; |
56 configuration.receiver_only = false; | 57 configuration.receiver_only = false; |
| 58 configuration.flexfec_sender = flexfec_sender; |
57 configuration.receive_statistics = null_receive_statistics; | 59 configuration.receive_statistics = null_receive_statistics; |
58 configuration.outgoing_transport = outgoing_transport; | 60 configuration.outgoing_transport = outgoing_transport; |
59 configuration.intra_frame_callback = intra_frame_callback; | 61 configuration.intra_frame_callback = intra_frame_callback; |
60 configuration.bandwidth_callback = bandwidth_callback; | 62 configuration.bandwidth_callback = bandwidth_callback; |
61 configuration.transport_feedback_callback = transport_feedback_callback; | 63 configuration.transport_feedback_callback = transport_feedback_callback; |
62 configuration.rtt_stats = rtt_stats; | 64 configuration.rtt_stats = rtt_stats; |
63 configuration.rtcp_packet_type_counter_observer = stats_proxy; | 65 configuration.rtcp_packet_type_counter_observer = stats_proxy; |
64 configuration.paced_sender = paced_sender; | 66 configuration.paced_sender = paced_sender; |
65 configuration.transport_sequence_number_allocator = | 67 configuration.transport_sequence_number_allocator = |
66 transport_sequence_number_allocator; | 68 transport_sequence_number_allocator; |
67 configuration.send_bitrate_observer = stats_proxy; | 69 configuration.send_bitrate_observer = stats_proxy; |
68 configuration.send_frame_count_observer = stats_proxy; | 70 configuration.send_frame_count_observer = stats_proxy; |
69 configuration.send_side_delay_observer = stats_proxy; | 71 configuration.send_side_delay_observer = stats_proxy; |
70 configuration.send_packet_observer = send_delay_stats; | 72 configuration.send_packet_observer = send_delay_stats; |
71 configuration.event_log = event_log; | 73 configuration.event_log = event_log; |
72 configuration.retransmission_rate_limiter = retransmission_rate_limiter; | 74 configuration.retransmission_rate_limiter = retransmission_rate_limiter; |
73 | 75 |
74 std::vector<RtpRtcp*> modules; | 76 std::vector<RtpRtcp*> modules; |
75 for (size_t i = 0; i < num_modules; ++i) { | 77 for (size_t i = 0; i < num_modules; ++i) { |
76 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); | 78 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); |
77 rtp_rtcp->SetSendingStatus(false); | 79 rtp_rtcp->SetSendingStatus(false); |
78 rtp_rtcp->SetSendingMediaStatus(false); | 80 rtp_rtcp->SetSendingMediaStatus(false); |
79 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound); | 81 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound); |
80 modules.push_back(rtp_rtcp); | 82 modules.push_back(rtp_rtcp); |
81 } | 83 } |
82 return modules; | 84 return modules; |
83 } | 85 } |
84 | 86 |
| 87 // TODO(brandtr): Update this function when we support multistream protection. |
| 88 std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender( |
| 89 const VideoSendStream::Config& config) { |
| 90 if (config.rtp.flexfec.flexfec_payload_type < 0) { |
| 91 return nullptr; |
| 92 } |
| 93 RTC_DCHECK_GE(config.rtp.flexfec.flexfec_payload_type, 0); |
| 94 RTC_DCHECK_LE(config.rtp.flexfec.flexfec_payload_type, 127); |
| 95 if (config.rtp.flexfec.flexfec_ssrc == 0) { |
| 96 LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. " |
| 97 "Therefore disabling FlexFEC."; |
| 98 return nullptr; |
| 99 } |
| 100 if (config.rtp.flexfec.protected_media_ssrcs.empty()) { |
| 101 LOG(LS_WARNING) << "FlexFEC is enabled, but no protected media SSRC given. " |
| 102 "Therefore disabling FlexFEC."; |
| 103 return nullptr; |
| 104 } |
| 105 |
| 106 if (config.rtp.ssrcs.size() > 1) { |
| 107 LOG(LS_WARNING) << "Both FlexFEC and simulcast are enabled. This " |
| 108 "combination is however not supported by our current " |
| 109 "FlexFEC implementation. Therefore disabling FlexFEC."; |
| 110 return nullptr; |
| 111 } |
| 112 |
| 113 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) { |
| 114 LOG(LS_WARNING) |
| 115 << "The supplied FlexfecConfig contained multiple protected " |
| 116 "media streams, but our implementation currently only " |
| 117 "supports protecting a single media stream. " |
| 118 "To avoid confusion, disabling FlexFEC completely."; |
| 119 return nullptr; |
| 120 } |
| 121 |
| 122 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size()); |
| 123 return std::unique_ptr<FlexfecSender>(new FlexfecSender( |
| 124 config.rtp.flexfec.flexfec_payload_type, config.rtp.flexfec.flexfec_ssrc, |
| 125 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions, |
| 126 Clock::GetRealTimeClock())); |
| 127 } |
| 128 |
85 } // namespace | 129 } // namespace |
86 | 130 |
87 std::string | 131 std::string |
88 VideoSendStream::Config::EncoderSettings::ToString() const { | 132 VideoSendStream::Config::EncoderSettings::ToString() const { |
89 std::stringstream ss; | 133 std::stringstream ss; |
90 ss << "{payload_name: " << payload_name; | 134 ss << "{payload_name: " << payload_name; |
91 ss << ", payload_type: " << payload_type; | 135 ss << ", payload_type: " << payload_type; |
92 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr"); | 136 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr"); |
93 ss << '}'; | 137 ss << '}'; |
94 return ss.str(); | 138 return ss.str(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 ss << ", extensions: ["; | 170 ss << ", extensions: ["; |
127 for (size_t i = 0; i < extensions.size(); ++i) { | 171 for (size_t i = 0; i < extensions.size(); ++i) { |
128 ss << extensions[i].ToString(); | 172 ss << extensions[i].ToString(); |
129 if (i != extensions.size() - 1) | 173 if (i != extensions.size() - 1) |
130 ss << ", "; | 174 ss << ", "; |
131 } | 175 } |
132 ss << ']'; | 176 ss << ']'; |
133 | 177 |
134 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; | 178 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; |
135 ss << ", ulpfec: " << ulpfec.ToString(); | 179 ss << ", ulpfec: " << ulpfec.ToString(); |
| 180 ss << ", flexfec: " << flexfec.ToString(); |
136 ss << ", rtx: " << rtx.ToString(); | 181 ss << ", rtx: " << rtx.ToString(); |
137 ss << ", c_name: " << c_name; | 182 ss << ", c_name: " << c_name; |
138 ss << '}'; | 183 ss << '}'; |
139 return ss.str(); | 184 return ss.str(); |
140 } | 185 } |
141 | 186 |
142 std::string VideoSendStream::Config::ToString() const { | 187 std::string VideoSendStream::Config::ToString() const { |
143 std::stringstream ss; | 188 std::stringstream ss; |
144 ss << "{encoder_settings: " << encoder_settings.ToString(); | 189 ss << "{encoder_settings: " << encoder_settings.ToString(); |
145 ss << ", rtp: " << rtp.ToString(); | 190 ss << ", rtp: " << rtp.ToString(); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 | 363 |
319 rtc::CriticalSection encoder_activity_crit_sect_; | 364 rtc::CriticalSection encoder_activity_crit_sect_; |
320 CheckEncoderActivityTask* check_encoder_activity_task_ | 365 CheckEncoderActivityTask* check_encoder_activity_task_ |
321 GUARDED_BY(encoder_activity_crit_sect_); | 366 GUARDED_BY(encoder_activity_crit_sect_); |
322 | 367 |
323 CallStats* const call_stats_; | 368 CallStats* const call_stats_; |
324 CongestionController* const congestion_controller_; | 369 CongestionController* const congestion_controller_; |
325 BitrateAllocator* const bitrate_allocator_; | 370 BitrateAllocator* const bitrate_allocator_; |
326 VieRemb* const remb_; | 371 VieRemb* const remb_; |
327 | 372 |
| 373 // TODO(brandtr): Consider moving this to a new FlexfecSendStream class. |
| 374 std::unique_ptr<FlexfecSender> flexfec_sender_; |
| 375 |
328 rtc::CriticalSection ivf_writers_crit_; | 376 rtc::CriticalSection ivf_writers_crit_; |
329 std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY( | 377 std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY( |
330 ivf_writers_crit_); | 378 ivf_writers_crit_); |
331 | 379 |
332 int max_padding_bitrate_; | 380 int max_padding_bitrate_; |
333 int encoder_min_bitrate_bps_; | 381 int encoder_min_bitrate_bps_; |
334 uint32_t encoder_max_bitrate_bps_; | 382 uint32_t encoder_max_bitrate_bps_; |
335 uint32_t encoder_target_rate_bps_; | 383 uint32_t encoder_target_rate_bps_; |
336 | 384 |
337 ViEEncoder* const vie_encoder_; | 385 ViEEncoder* const vie_encoder_; |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 : stats_proxy_(stats_proxy), | 702 : stats_proxy_(stats_proxy), |
655 config_(config), | 703 config_(config), |
656 suspended_ssrcs_(std::move(suspended_ssrcs)), | 704 suspended_ssrcs_(std::move(suspended_ssrcs)), |
657 module_process_thread_(nullptr), | 705 module_process_thread_(nullptr), |
658 worker_queue_(worker_queue), | 706 worker_queue_(worker_queue), |
659 check_encoder_activity_task_(nullptr), | 707 check_encoder_activity_task_(nullptr), |
660 call_stats_(call_stats), | 708 call_stats_(call_stats), |
661 congestion_controller_(congestion_controller), | 709 congestion_controller_(congestion_controller), |
662 bitrate_allocator_(bitrate_allocator), | 710 bitrate_allocator_(bitrate_allocator), |
663 remb_(remb), | 711 remb_(remb), |
| 712 flexfec_sender_(MaybeCreateFlexfecSender(*config_)), |
664 max_padding_bitrate_(0), | 713 max_padding_bitrate_(0), |
665 encoder_min_bitrate_bps_(0), | 714 encoder_min_bitrate_bps_(0), |
666 encoder_max_bitrate_bps_(initial_encoder_max_bitrate), | 715 encoder_max_bitrate_bps_(initial_encoder_max_bitrate), |
667 encoder_target_rate_bps_(0), | 716 encoder_target_rate_bps_(0), |
668 vie_encoder_(vie_encoder), | 717 vie_encoder_(vie_encoder), |
669 encoder_feedback_(Clock::GetRealTimeClock(), | 718 encoder_feedback_(Clock::GetRealTimeClock(), |
670 config_->rtp.ssrcs, | 719 config_->rtp.ssrcs, |
671 vie_encoder), | 720 vie_encoder), |
672 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this), | 721 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this), |
673 bandwidth_observer_(congestion_controller_->GetBitrateController() | 722 bandwidth_observer_(congestion_controller_->GetBitrateController() |
674 ->CreateRtcpBandwidthObserver()), | 723 ->CreateRtcpBandwidthObserver()), |
675 rtp_rtcp_modules_(CreateRtpRtcpModules( | 724 rtp_rtcp_modules_(CreateRtpRtcpModules( |
676 config_->send_transport, | 725 config_->send_transport, |
677 &encoder_feedback_, | 726 &encoder_feedback_, |
678 bandwidth_observer_.get(), | 727 bandwidth_observer_.get(), |
679 congestion_controller_->GetTransportFeedbackObserver(), | 728 congestion_controller_->GetTransportFeedbackObserver(), |
680 call_stats_->rtcp_rtt_stats(), | 729 call_stats_->rtcp_rtt_stats(), |
681 congestion_controller_->pacer(), | 730 congestion_controller_->pacer(), |
682 congestion_controller_->packet_router(), | 731 congestion_controller_->packet_router(), |
| 732 flexfec_sender_.get(), |
683 stats_proxy_, | 733 stats_proxy_, |
684 send_delay_stats, | 734 send_delay_stats, |
685 event_log, | 735 event_log, |
686 congestion_controller_->GetRetransmissionRateLimiter(), | 736 congestion_controller_->GetRetransmissionRateLimiter(), |
687 config_->rtp.ssrcs.size())), | 737 config_->rtp.ssrcs.size())), |
688 payload_router_(rtp_rtcp_modules_, | 738 payload_router_(rtp_rtcp_modules_, |
689 config_->encoder_settings.payload_type), | 739 config_->encoder_settings.payload_type), |
690 weak_ptr_factory_(this) { | 740 weak_ptr_factory_(this) { |
691 RTC_DCHECK_RUN_ON(worker_queue_); | 741 RTC_DCHECK_RUN_ON(worker_queue_); |
692 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString(); | 742 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString(); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 RTC_DCHECK(ok); | 986 RTC_DCHECK(ok); |
937 } | 987 } |
938 } | 988 } |
939 | 989 |
940 return result; | 990 return result; |
941 } | 991 } |
942 | 992 |
943 void VideoSendStreamImpl::ConfigureProtection() { | 993 void VideoSendStreamImpl::ConfigureProtection() { |
944 RTC_DCHECK_RUN_ON(worker_queue_); | 994 RTC_DCHECK_RUN_ON(worker_queue_); |
945 | 995 |
| 996 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender. |
| 997 const bool flexfec_enabled = (flexfec_sender_ != nullptr); |
| 998 |
| 999 // Consistency of NACK and RED+ULPFEC parameters is checked in this function. |
946 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0; | 1000 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0; |
947 int red_payload_type = config_->rtp.ulpfec.red_payload_type; | 1001 int red_payload_type = config_->rtp.ulpfec.red_payload_type; |
948 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type; | 1002 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type; |
949 | 1003 |
950 // Shorthands. | 1004 // Shorthands. |
951 auto IsRedEnabled = [&]() { return red_payload_type >= 0; }; | 1005 auto IsRedEnabled = [&]() { return red_payload_type >= 0; }; |
| 1006 auto DisableRed = [&]() { red_payload_type = -1; }; |
952 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; }; | 1007 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; }; |
953 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; }; | 1008 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; }; |
954 | 1009 |
| 1010 // If enabled, FlexFEC takes priority over RED+ULPFEC. |
| 1011 if (flexfec_enabled) { |
| 1012 // We can safely disable RED here, because if the remote supports FlexFEC, |
| 1013 // we know that it has a receiver without the RED/RTX workaround. |
| 1014 // See http://crbug.com/webrtc/6650 for more information. |
| 1015 if (IsRedEnabled()) { |
| 1016 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED."; |
| 1017 DisableRed(); |
| 1018 } |
| 1019 if (IsUlpfecEnabled()) { |
| 1020 LOG(LS_INFO) |
| 1021 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC."; |
| 1022 DisableUlpfec(); |
| 1023 } |
| 1024 } |
| 1025 |
955 // Payload types without picture ID cannot determine that a stream is complete | 1026 // Payload types without picture ID cannot determine that a stream is complete |
956 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance) | 1027 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance) |
957 // is a waste of bandwidth since FEC packets still have to be transmitted. | 1028 // is a waste of bandwidth since FEC packets still have to be transmitted. |
958 // Note that this is not the case with FlexFEC. | 1029 // Note that this is not the case with FlexFEC. |
959 if (nack_enabled && IsUlpfecEnabled() && | 1030 if (nack_enabled && IsUlpfecEnabled() && |
960 !PayloadTypeSupportsSkippingFecPackets( | 1031 !PayloadTypeSupportsSkippingFecPackets( |
961 config_->encoder_settings.payload_name)) { | 1032 config_->encoder_settings.payload_name)) { |
962 LOG(LS_WARNING) | 1033 LOG(LS_WARNING) |
963 << "Transmitting payload type without picture ID using " | 1034 << "Transmitting payload type without picture ID using " |
964 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets " | 1035 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets " |
(...skipping 27 matching lines...) Expand all Loading... |
992 // Set NACK. | 1063 // Set NACK. |
993 rtp_rtcp->SetStorePacketsStatus( | 1064 rtp_rtcp->SetStorePacketsStatus( |
994 nack_enabled || congestion_controller_->pacer(), | 1065 nack_enabled || congestion_controller_->pacer(), |
995 kMinSendSidePacketHistorySize); | 1066 kMinSendSidePacketHistorySize); |
996 // Set RED/ULPFEC information. | 1067 // Set RED/ULPFEC information. |
997 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 1068 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
998 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type); | 1069 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type); |
999 } | 1070 } |
1000 } | 1071 } |
1001 | 1072 |
1002 protection_bitrate_calculator_.SetProtectionMethod(IsUlpfecEnabled(), | 1073 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic, |
1003 nack_enabled); | 1074 // so enable that logic if either of those FEC schemes are enabled. |
| 1075 protection_bitrate_calculator_.SetProtectionMethod( |
| 1076 flexfec_enabled || IsUlpfecEnabled(), nack_enabled); |
1004 } | 1077 } |
1005 | 1078 |
1006 void VideoSendStreamImpl::ConfigureSsrcs() { | 1079 void VideoSendStreamImpl::ConfigureSsrcs() { |
1007 RTC_DCHECK_RUN_ON(worker_queue_); | 1080 RTC_DCHECK_RUN_ON(worker_queue_); |
1008 // Configure regular SSRCs. | 1081 // Configure regular SSRCs. |
1009 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) { | 1082 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) { |
1010 uint32_t ssrc = config_->rtp.ssrcs[i]; | 1083 uint32_t ssrc = config_->rtp.ssrcs[i]; |
1011 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; | 1084 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
1012 rtp_rtcp->SetSSRC(ssrc); | 1085 rtp_rtcp->SetSSRC(ssrc); |
1013 | 1086 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 } | 1212 } |
1140 | 1213 |
1141 void VideoSendStreamImpl::SetTransportOverhead( | 1214 void VideoSendStreamImpl::SetTransportOverhead( |
1142 int transport_overhead_per_packet) { | 1215 int transport_overhead_per_packet) { |
1143 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) | 1216 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
1144 rtp_rtcp->SetTransportOverhead(transport_overhead_per_packet); | 1217 rtp_rtcp->SetTransportOverhead(transport_overhead_per_packet); |
1145 } | 1218 } |
1146 | 1219 |
1147 } // namespace internal | 1220 } // namespace internal |
1148 } // namespace webrtc | 1221 } // namespace webrtc |
OLD | NEW |