pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 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 |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
pbos@webrtc.org | 16e03b7 | 2013-10-28 16:32:01 | [diff] [blame] | 11 | #include "webrtc/video/video_send_stream.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 12 | |
pbos@webrtc.org | dde16f1 | 2014-08-05 23:35:43 | [diff] [blame] | 13 | #include <algorithm> |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 14 | #include <sstream> |
henrik.lundin@webrtc.org | ba975e2 | 2013-10-23 11:04:57 | [diff] [blame] | 15 | #include <string> |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 16 | #include <vector> |
| 17 | |
| 18 | #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
pbos@webrtc.org | 6ae48c6 | 2014-06-06 10:49:19 | [diff] [blame] | 19 | #include "webrtc/system_wrappers/interface/logging.h" |
pbos@webrtc.org | 50fe359 | 2015-01-29 12:33:07 | [diff] [blame] | 20 | #include "webrtc/system_wrappers/interface/trace_event.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 21 | #include "webrtc/video_engine/include/vie_base.h" |
| 22 | #include "webrtc/video_engine/include/vie_capture.h" |
| 23 | #include "webrtc/video_engine/include/vie_codec.h" |
stefan@webrtc.org | 360e376 | 2013-08-22 09:29:56 | [diff] [blame] | 24 | #include "webrtc/video_engine/include/vie_external_codec.h" |
pbos@webrtc.org | fe1ef93 | 2013-10-21 10:34:43 | [diff] [blame] | 25 | #include "webrtc/video_engine/include/vie_image_process.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 26 | #include "webrtc/video_engine/include/vie_network.h" |
| 27 | #include "webrtc/video_engine/include/vie_rtp_rtcp.h" |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 28 | #include "webrtc/video_engine/vie_defines.h" |
pbos@webrtc.org | 16e03b7 | 2013-10-28 16:32:01 | [diff] [blame] | 29 | #include "webrtc/video_send_stream.h" |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 30 | |
| 31 | namespace webrtc { |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 32 | std::string |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 | [diff] [blame] | 33 | VideoSendStream::Config::EncoderSettings::ToString() const { |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 34 | std::stringstream ss; |
| 35 | ss << "{payload_name: " << payload_name; |
| 36 | ss << ", payload_type: " << payload_type; |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 37 | ss << ", encoder: " << (encoder != NULL ? "(VideoEncoder)" : "NULL"); |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 38 | ss << '}'; |
| 39 | return ss.str(); |
| 40 | } |
| 41 | |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 | [diff] [blame] | 42 | std::string VideoSendStream::Config::Rtp::Rtx::ToString() |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 43 | const { |
| 44 | std::stringstream ss; |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 45 | ss << "{ssrcs: ["; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 46 | for (size_t i = 0; i < ssrcs.size(); ++i) { |
| 47 | ss << ssrcs[i]; |
| 48 | if (i != ssrcs.size() - 1) |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 49 | ss << ", "; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 50 | } |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 51 | ss << ']'; |
andrew@webrtc.org | 8f27fcc | 2015-01-09 20:22:46 | [diff] [blame] | 52 | |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 53 | ss << ", payload_type: " << payload_type; |
| 54 | ss << '}'; |
| 55 | return ss.str(); |
| 56 | } |
| 57 | |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 | [diff] [blame] | 58 | std::string VideoSendStream::Config::Rtp::ToString() const { |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 59 | std::stringstream ss; |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 60 | ss << "{ssrcs: ["; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 61 | for (size_t i = 0; i < ssrcs.size(); ++i) { |
| 62 | ss << ssrcs[i]; |
| 63 | if (i != ssrcs.size() - 1) |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 64 | ss << ", "; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 65 | } |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 66 | ss << ']'; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 67 | ss << ", max_packet_size: " << max_packet_size; |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 68 | ss << ", extensions: ["; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 69 | for (size_t i = 0; i < extensions.size(); ++i) { |
| 70 | ss << extensions[i].ToString(); |
| 71 | if (i != extensions.size() - 1) |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 72 | ss << ", "; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 73 | } |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 74 | ss << ']'; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 75 | |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 76 | ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}'; |
| 77 | ss << ", fec: " << fec.ToString(); |
| 78 | ss << ", rtx: " << rtx.ToString(); |
| 79 | ss << ", c_name: " << c_name; |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 80 | ss << '}'; |
| 81 | return ss.str(); |
| 82 | } |
| 83 | |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 | [diff] [blame] | 84 | std::string VideoSendStream::Config::ToString() const { |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 85 | std::stringstream ss; |
| 86 | ss << "{encoder_settings: " << encoder_settings.ToString(); |
| 87 | ss << ", rtp: " << rtp.ToString(); |
pbos@webrtc.org | 32e8528 | 2015-01-15 10:09:39 | [diff] [blame] | 88 | ss << ", pre_encode_callback: " |
| 89 | << (pre_encode_callback != NULL ? "(I420FrameCallback)" : "NULL"); |
| 90 | ss << ", post_encode_callback: " |
| 91 | << (post_encode_callback != NULL ? "(EncodedFrameObserver)" : "NULL"); |
| 92 | ss << "local_renderer: " << (local_renderer != NULL ? "(VideoRenderer)" |
| 93 | : "NULL"); |
| 94 | ss << ", render_delay_ms: " << render_delay_ms; |
| 95 | ss << ", target_delay_ms: " << target_delay_ms; |
| 96 | ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on" |
| 97 | : "off"); |
pbos@webrtc.org | 1e92b0a | 2014-05-15 09:35:06 | [diff] [blame] | 98 | ss << '}'; |
| 99 | return ss.str(); |
| 100 | } |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 101 | |
pbos@webrtc.org | 024e4d5 | 2014-05-15 10:03:24 | [diff] [blame] | 102 | namespace internal { |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 103 | VideoSendStream::VideoSendStream( |
| 104 | newapi::Transport* transport, |
| 105 | CpuOveruseObserver* overuse_observer, |
| 106 | webrtc::VideoEngine* video_engine, |
| 107 | const VideoSendStream::Config& config, |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 108 | const VideoEncoderConfig& encoder_config, |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 109 | const std::map<uint32_t, RtpState>& suspended_ssrcs, |
| 110 | int base_channel, |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 111 | Call::Config::BitrateConfig bitrate_config) |
pbos@webrtc.org | 6488761 | 2013-11-14 08:58:14 | [diff] [blame] | 112 | : transport_adapter_(transport), |
sprang@webrtc.org | 4070935 | 2013-11-26 11:41:59 | [diff] [blame] | 113 | encoded_frame_proxy_(config.post_encode_callback), |
pbos@webrtc.org | 6488761 | 2013-11-14 08:58:14 | [diff] [blame] | 114 | config_(config), |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 115 | bitrate_config_(bitrate_config), |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 116 | suspended_ssrcs_(suspended_ssrcs), |
mflodman@webrtc.org | f3973e8 | 2013-12-13 09:40:45 | [diff] [blame] | 117 | external_codec_(NULL), |
pbos@webrtc.org | de1429e | 2014-04-28 13:00:21 | [diff] [blame] | 118 | channel_(-1), |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 119 | use_config_bitrate_(true), |
pbos@webrtc.org | 273a414 | 2014-12-01 15:23:21 | [diff] [blame] | 120 | stats_proxy_(Clock::GetRealTimeClock(), config) { |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 121 | // Duplicate assert checking of bitrate config. These should be checked in |
| 122 | // Call but are added here for verbosity. |
| 123 | assert(bitrate_config.min_bitrate_bps >= 0); |
| 124 | assert(bitrate_config.start_bitrate_bps >= bitrate_config.min_bitrate_bps); |
| 125 | if (bitrate_config.max_bitrate_bps != -1) |
| 126 | assert(bitrate_config.max_bitrate_bps >= bitrate_config.start_bitrate_bps); |
| 127 | |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 128 | video_engine_base_ = ViEBase::GetInterface(video_engine); |
pbos@webrtc.org | 40367f9 | 2015-02-13 08:00:06 | [diff] [blame] | 129 | video_engine_base_->CreateChannelWithoutDefaultEncoder(channel_, |
| 130 | base_channel); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 131 | assert(channel_ != -1); |
| 132 | |
| 133 | rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine); |
| 134 | assert(rtp_rtcp_ != NULL); |
| 135 | |
pbos@webrtc.org | 6488761 | 2013-11-14 08:58:14 | [diff] [blame] | 136 | assert(config_.rtp.ssrcs.size() > 0); |
pbos@webrtc.org | 2902328 | 2013-09-11 10:14:56 | [diff] [blame] | 137 | |
| 138 | for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { |
| 139 | const std::string& extension = config_.rtp.extensions[i].name; |
| 140 | int id = config_.rtp.extensions[i].id; |
pbos@webrtc.org | ce90eff | 2013-11-20 11:48:56 | [diff] [blame] | 141 | if (extension == RtpExtension::kTOffset) { |
pbos@webrtc.org | 2902328 | 2013-09-11 10:14:56 | [diff] [blame] | 142 | if (rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id) != 0) |
| 143 | abort(); |
pbos@webrtc.org | ce90eff | 2013-11-20 11:48:56 | [diff] [blame] | 144 | } else if (extension == RtpExtension::kAbsSendTime) { |
pbos@webrtc.org | 5c678ea | 2013-09-11 19:00:39 | [diff] [blame] | 145 | if (rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id) != 0) |
| 146 | abort(); |
pbos@webrtc.org | 2902328 | 2013-09-11 10:14:56 | [diff] [blame] | 147 | } else { |
| 148 | abort(); // Unsupported extension. |
| 149 | } |
| 150 | } |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 151 | |
mflodman@webrtc.org | 92c2793 | 2013-12-13 16:36:28 | [diff] [blame] | 152 | rtp_rtcp_->SetRembStatus(channel_, true, false); |
| 153 | |
pbos@webrtc.org | 0e63e76 | 2013-09-20 11:56:26 | [diff] [blame] | 154 | // Enable NACK, FEC or both. |
| 155 | if (config_.rtp.fec.red_payload_type != -1) { |
| 156 | assert(config_.rtp.fec.ulpfec_payload_type != -1); |
| 157 | if (config_.rtp.nack.rtp_history_ms > 0) { |
| 158 | rtp_rtcp_->SetHybridNACKFECStatus( |
| 159 | channel_, |
| 160 | true, |
| 161 | static_cast<unsigned char>(config_.rtp.fec.red_payload_type), |
| 162 | static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type)); |
| 163 | } else { |
| 164 | rtp_rtcp_->SetFECStatus( |
| 165 | channel_, |
| 166 | true, |
| 167 | static_cast<unsigned char>(config_.rtp.fec.red_payload_type), |
| 168 | static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type)); |
| 169 | } |
| 170 | } else { |
| 171 | rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0); |
| 172 | } |
| 173 | |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 174 | ConfigureSsrcs(); |
| 175 | |
pbos@webrtc.org | 013d994 | 2013-08-22 09:42:17 | [diff] [blame] | 176 | char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength]; |
| 177 | assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength); |
| 178 | strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1); |
| 179 | rtcp_cname[sizeof(rtcp_cname) - 1] = '\0'; |
| 180 | |
| 181 | rtp_rtcp_->SetRTCPCName(channel_, rtcp_cname); |
| 182 | |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 183 | capture_ = ViECapture::GetInterface(video_engine); |
| 184 | capture_->AllocateExternalCaptureDevice(capture_id_, external_capture_); |
| 185 | capture_->ConnectCaptureDevice(capture_id_, channel_); |
| 186 | |
| 187 | network_ = ViENetwork::GetInterface(video_engine); |
| 188 | assert(network_ != NULL); |
| 189 | |
pbos@webrtc.org | e75a1bf | 2013-09-18 11:52:42 | [diff] [blame] | 190 | network_->RegisterSendTransport(channel_, transport_adapter_); |
sprang@webrtc.org | 25fce9a | 2013-10-16 13:29:14 | [diff] [blame] | 191 | // 28 to match packet overhead in ModuleRtpRtcpImpl. |
pbos@webrtc.org | 16e03b7 | 2013-10-28 16:32:01 | [diff] [blame] | 192 | network_->SetMTU(channel_, |
| 193 | static_cast<unsigned int>(config_.rtp.max_packet_size + 28)); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 194 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 195 | assert(config.encoder_settings.encoder != NULL); |
| 196 | assert(config.encoder_settings.payload_type >= 0); |
| 197 | assert(config.encoder_settings.payload_type <= 127); |
| 198 | external_codec_ = ViEExternalCodec::GetInterface(video_engine); |
| 199 | if (external_codec_->RegisterExternalSendCodec( |
| 200 | channel_, |
| 201 | config.encoder_settings.payload_type, |
| 202 | config.encoder_settings.encoder, |
| 203 | false) != 0) { |
| 204 | abort(); |
stefan@webrtc.org | 360e376 | 2013-08-22 09:29:56 | [diff] [blame] | 205 | } |
| 206 | |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 207 | codec_ = ViECodec::GetInterface(video_engine); |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 208 | if (!ReconfigureVideoEncoder(encoder_config)) |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 209 | abort(); |
pbos@webrtc.org | fe1ef93 | 2013-10-21 10:34:43 | [diff] [blame] | 210 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 211 | if (overuse_observer) |
| 212 | video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer); |
pbos@webrtc.org | 3e6e271 | 2015-02-26 12:19:31 | [diff] [blame] | 213 | // Registered regardless of monitoring, used for stats. |
| 214 | video_engine_base_->RegisterCpuOveruseMetricsObserver(channel_, |
| 215 | &stats_proxy_); |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 216 | |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 217 | video_engine_base_->RegisterSendSideDelayObserver(channel_, &stats_proxy_); |
pbos@webrtc.org | 273a414 | 2014-12-01 15:23:21 | [diff] [blame] | 218 | video_engine_base_->RegisterSendStatisticsProxy(channel_, &stats_proxy_); |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 219 | |
pbos@webrtc.org | fe1ef93 | 2013-10-21 10:34:43 | [diff] [blame] | 220 | image_process_ = ViEImageProcess::GetInterface(video_engine); |
| 221 | image_process_->RegisterPreEncodeCallback(channel_, |
| 222 | config_.pre_encode_callback); |
sprang@webrtc.org | 4070935 | 2013-11-26 11:41:59 | [diff] [blame] | 223 | if (config_.post_encode_callback) { |
| 224 | image_process_->RegisterPostEncodeImageCallback(channel_, |
| 225 | &encoded_frame_proxy_); |
| 226 | } |
henrik.lundin@webrtc.org | ba975e2 | 2013-10-23 11:04:57 | [diff] [blame] | 227 | |
pbos@webrtc.org | 6ae48c6 | 2014-06-06 10:49:19 | [diff] [blame] | 228 | if (config_.suspend_below_min_bitrate) |
henrik.lundin@webrtc.org | ce8e093 | 2013-11-18 12:18:43 | [diff] [blame] | 229 | codec_->SuspendBelowMinBitrate(channel_); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 230 | |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 231 | rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_, |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 232 | &stats_proxy_); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 233 | rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_, |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 234 | &stats_proxy_); |
pbos@webrtc.org | 1d0fa5d | 2015-02-19 12:47:00 | [diff] [blame] | 235 | rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, &stats_proxy_); |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 236 | rtp_rtcp_->RegisterSendBitrateObserver(channel_, &stats_proxy_); |
| 237 | rtp_rtcp_->RegisterSendFrameCountObserver(channel_, &stats_proxy_); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 238 | |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 239 | codec_->RegisterEncoderObserver(channel_, stats_proxy_); |
| 240 | capture_->RegisterObserver(capture_id_, stats_proxy_); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | VideoSendStream::~VideoSendStream() { |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 244 | capture_->DeregisterObserver(capture_id_); |
| 245 | codec_->DeregisterEncoderObserver(channel_); |
| 246 | |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 247 | rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, &stats_proxy_); |
| 248 | rtp_rtcp_->DeregisterSendBitrateObserver(channel_, &stats_proxy_); |
pbos@webrtc.org | 1d0fa5d | 2015-02-19 12:47:00 | [diff] [blame] | 249 | rtp_rtcp_->RegisterRtcpPacketTypeCounterObserver(channel_, NULL); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 250 | rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_, |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 251 | &stats_proxy_); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 252 | rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_, |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 253 | &stats_proxy_); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 254 | |
pbos@webrtc.org | fe1ef93 | 2013-10-21 10:34:43 | [diff] [blame] | 255 | image_process_->DeRegisterPreEncodeCallback(channel_); |
| 256 | |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 257 | network_->DeregisterSendTransport(channel_); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 258 | |
| 259 | capture_->DisconnectCaptureDevice(channel_); |
| 260 | capture_->ReleaseCaptureDevice(capture_id_); |
| 261 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 262 | external_codec_->DeRegisterExternalSendCodec( |
| 263 | channel_, config_.encoder_settings.payload_type); |
stefan@webrtc.org | 360e376 | 2013-08-22 09:29:56 | [diff] [blame] | 264 | |
pbos@webrtc.org | fe1ef93 | 2013-10-21 10:34:43 | [diff] [blame] | 265 | video_engine_base_->DeleteChannel(channel_); |
| 266 | |
| 267 | image_process_->Release(); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 268 | video_engine_base_->Release(); |
| 269 | capture_->Release(); |
| 270 | codec_->Release(); |
stefan@webrtc.org | 360e376 | 2013-08-22 09:29:56 | [diff] [blame] | 271 | if (external_codec_) |
| 272 | external_codec_->Release(); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 273 | network_->Release(); |
| 274 | rtp_rtcp_->Release(); |
| 275 | } |
| 276 | |
pbos@webrtc.org | 724947b | 2013-12-11 16:26:16 | [diff] [blame] | 277 | void VideoSendStream::SwapFrame(I420VideoFrame* frame) { |
pbos@webrtc.org | 724947b | 2013-12-11 16:26:16 | [diff] [blame] | 278 | // TODO(pbos): Local rendering should not be done on the capture thread. |
| 279 | if (config_.local_renderer != NULL) |
pbos@webrtc.org | 1566ee2 | 2014-05-23 13:03:45 | [diff] [blame] | 280 | config_.local_renderer->RenderFrame(*frame, 0); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 281 | |
pbos@webrtc.org | 1566ee2 | 2014-05-23 13:03:45 | [diff] [blame] | 282 | external_capture_->SwapFrame(frame); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 283 | } |
| 284 | |
pbos@webrtc.org | 74fa489 | 2013-08-23 09:19:30 | [diff] [blame] | 285 | VideoSendStreamInput* VideoSendStream::Input() { return this; } |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 286 | |
pbos@webrtc.org | a5c8d2c | 2014-04-24 11:13:21 | [diff] [blame] | 287 | void VideoSendStream::Start() { |
sprang@webrtc.org | d9b9560 | 2014-01-27 13:03:02 | [diff] [blame] | 288 | transport_adapter_.Enable(); |
pbos@webrtc.org | f777cf2 | 2014-01-10 18:47:32 | [diff] [blame] | 289 | video_engine_base_->StartSend(channel_); |
| 290 | video_engine_base_->StartReceive(channel_); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 291 | } |
| 292 | |
pbos@webrtc.org | a5c8d2c | 2014-04-24 11:13:21 | [diff] [blame] | 293 | void VideoSendStream::Stop() { |
pbos@webrtc.org | f777cf2 | 2014-01-10 18:47:32 | [diff] [blame] | 294 | video_engine_base_->StopSend(channel_); |
| 295 | video_engine_base_->StopReceive(channel_); |
sprang@webrtc.org | d9b9560 | 2014-01-27 13:03:02 | [diff] [blame] | 296 | transport_adapter_.Disable(); |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 297 | } |
| 298 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 299 | bool VideoSendStream::ReconfigureVideoEncoder( |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 300 | const VideoEncoderConfig& config) { |
pbos@webrtc.org | 50fe359 | 2015-01-29 12:33:07 | [diff] [blame] | 301 | TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); |
pbos@webrtc.org | ad3b5a5 | 2014-10-24 09:23:21 | [diff] [blame] | 302 | LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 303 | const std::vector<VideoStream>& streams = config.streams; |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 304 | assert(!streams.empty()); |
| 305 | assert(config_.rtp.ssrcs.size() >= streams.size()); |
pbos@webrtc.org | 6488761 | 2013-11-14 08:58:14 | [diff] [blame] | 306 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 307 | VideoCodec video_codec; |
| 308 | memset(&video_codec, 0, sizeof(video_codec)); |
stefan@webrtc.org | 79c3359 | 2014-08-06 09:24:53 | [diff] [blame] | 309 | if (config_.encoder_settings.payload_name == "VP8") { |
| 310 | video_codec.codecType = kVideoCodecVP8; |
marpan@webrtc.org | 5b88317 | 2014-11-01 06:10:48 | [diff] [blame] | 311 | } else if (config_.encoder_settings.payload_name == "VP9") { |
| 312 | video_codec.codecType = kVideoCodecVP9; |
stefan@webrtc.org | 79c3359 | 2014-08-06 09:24:53 | [diff] [blame] | 313 | } else if (config_.encoder_settings.payload_name == "H264") { |
| 314 | video_codec.codecType = kVideoCodecH264; |
| 315 | } else { |
| 316 | video_codec.codecType = kVideoCodecGeneric; |
| 317 | } |
pbos@webrtc.org | b7ed779 | 2014-10-31 13:08:10 | [diff] [blame] | 318 | |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 319 | switch (config.content_type) { |
| 320 | case VideoEncoderConfig::kRealtimeVideo: |
| 321 | video_codec.mode = kRealtimeVideo; |
| 322 | break; |
| 323 | case VideoEncoderConfig::kScreenshare: |
| 324 | video_codec.mode = kScreensharing; |
pbos@webrtc.org | b7ed779 | 2014-10-31 13:08:10 | [diff] [blame] | 325 | if (config.streams.size() == 1 && |
| 326 | config.streams[0].temporal_layer_thresholds_bps.size() == 1) { |
| 327 | video_codec.targetBitrate = |
| 328 | config.streams[0].temporal_layer_thresholds_bps[0] / 1000; |
| 329 | } |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 330 | break; |
| 331 | } |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 332 | |
| 333 | if (video_codec.codecType == kVideoCodecVP8) { |
pbos@webrtc.org | 6cd6ba8 | 2014-09-18 12:42:28 | [diff] [blame] | 334 | video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); |
marpan@webrtc.org | 5b88317 | 2014-11-01 06:10:48 | [diff] [blame] | 335 | } else if (video_codec.codecType == kVideoCodecVP9) { |
| 336 | video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); |
stefan@webrtc.org | 79c3359 | 2014-08-06 09:24:53 | [diff] [blame] | 337 | } else if (video_codec.codecType == kVideoCodecH264) { |
pbos@webrtc.org | 6cd6ba8 | 2014-09-18 12:42:28 | [diff] [blame] | 338 | video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 339 | } |
| 340 | |
pbos@webrtc.org | 91f1752 | 2014-07-10 10:13:37 | [diff] [blame] | 341 | if (video_codec.codecType == kVideoCodecVP8) { |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 342 | if (config.encoder_specific_settings != NULL) { |
| 343 | video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( |
| 344 | config.encoder_specific_settings); |
pbos@webrtc.org | 91f1752 | 2014-07-10 10:13:37 | [diff] [blame] | 345 | } |
pbos@webrtc.org | 759982d | 2014-09-22 09:32:46 | [diff] [blame] | 346 | video_codec.codecSpecific.VP8.numberOfTemporalLayers = |
pbos@webrtc.org | b7ed779 | 2014-10-31 13:08:10 | [diff] [blame] | 347 | static_cast<unsigned char>( |
| 348 | streams.back().temporal_layer_thresholds_bps.size() + 1); |
pbos@webrtc.org | 91f1752 | 2014-07-10 10:13:37 | [diff] [blame] | 349 | } else { |
| 350 | // TODO(pbos): Support encoder_settings codec-agnostically. |
pbos@webrtc.org | bbe0a85 | 2014-09-19 12:30:25 | [diff] [blame] | 351 | assert(config.encoder_specific_settings == NULL); |
pbos@webrtc.org | 91f1752 | 2014-07-10 10:13:37 | [diff] [blame] | 352 | } |
| 353 | |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 354 | strncpy(video_codec.plName, |
| 355 | config_.encoder_settings.payload_name.c_str(), |
| 356 | kPayloadNameSize - 1); |
| 357 | video_codec.plName[kPayloadNameSize - 1] = '\0'; |
| 358 | video_codec.plType = config_.encoder_settings.payload_type; |
| 359 | video_codec.numberOfSimulcastStreams = |
| 360 | static_cast<unsigned char>(streams.size()); |
| 361 | video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; |
| 362 | assert(streams.size() <= kMaxSimulcastStreams); |
| 363 | for (size_t i = 0; i < streams.size(); ++i) { |
| 364 | SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; |
| 365 | assert(streams[i].width > 0); |
| 366 | assert(streams[i].height > 0); |
| 367 | assert(streams[i].max_framerate > 0); |
| 368 | // Different framerates not supported per stream at the moment. |
| 369 | assert(streams[i].max_framerate == streams[0].max_framerate); |
| 370 | assert(streams[i].min_bitrate_bps >= 0); |
| 371 | assert(streams[i].target_bitrate_bps >= streams[i].min_bitrate_bps); |
| 372 | assert(streams[i].max_bitrate_bps >= streams[i].target_bitrate_bps); |
| 373 | assert(streams[i].max_qp >= 0); |
| 374 | |
| 375 | sim_stream->width = static_cast<unsigned short>(streams[i].width); |
| 376 | sim_stream->height = static_cast<unsigned short>(streams[i].height); |
| 377 | sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; |
| 378 | sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; |
| 379 | sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; |
| 380 | sim_stream->qpMax = streams[i].max_qp; |
pbos@webrtc.org | b7ed779 | 2014-10-31 13:08:10 | [diff] [blame] | 381 | sim_stream->numberOfTemporalLayers = static_cast<unsigned char>( |
| 382 | streams[i].temporal_layer_thresholds_bps.size() + 1); |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 383 | |
| 384 | video_codec.width = std::max(video_codec.width, |
| 385 | static_cast<unsigned short>(streams[i].width)); |
| 386 | video_codec.height = std::max( |
| 387 | video_codec.height, static_cast<unsigned short>(streams[i].height)); |
| 388 | video_codec.minBitrate = |
| 389 | std::min(video_codec.minBitrate, |
| 390 | static_cast<unsigned int>(streams[i].min_bitrate_bps / 1000)); |
| 391 | video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; |
| 392 | video_codec.qpMax = std::max(video_codec.qpMax, |
| 393 | static_cast<unsigned int>(streams[i].max_qp)); |
| 394 | } |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 395 | // Clamp bitrates to the bitrate config. |
| 396 | if (video_codec.minBitrate < |
| 397 | static_cast<unsigned int>(bitrate_config_.min_bitrate_bps / 1000)) { |
| 398 | video_codec.minBitrate = bitrate_config_.min_bitrate_bps / 1000; |
| 399 | } |
| 400 | if (bitrate_config_.max_bitrate_bps != -1 && |
| 401 | video_codec.maxBitrate > |
| 402 | static_cast<unsigned int>(bitrate_config_.max_bitrate_bps / 1000)) { |
| 403 | video_codec.maxBitrate = bitrate_config_.max_bitrate_bps / 1000; |
| 404 | } |
pbos@webrtc.org | 32452b2 | 2014-10-22 12:15:24 | [diff] [blame] | 405 | unsigned int start_bitrate_bps; |
| 406 | if (codec_->GetCodecTargetBitrate(channel_, &start_bitrate_bps) != 0 || |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 407 | use_config_bitrate_) { |
| 408 | start_bitrate_bps = bitrate_config_.start_bitrate_bps; |
pbos@webrtc.org | 32452b2 | 2014-10-22 12:15:24 | [diff] [blame] | 409 | } |
mflodman@webrtc.org | eb16b81 | 2014-06-16 08:57:39 | [diff] [blame] | 410 | video_codec.startBitrate = |
pbos@webrtc.org | 32452b2 | 2014-10-22 12:15:24 | [diff] [blame] | 411 | static_cast<unsigned int>(start_bitrate_bps) / 1000; |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 412 | |
| 413 | if (video_codec.minBitrate < kViEMinCodecBitrate) |
| 414 | video_codec.minBitrate = kViEMinCodecBitrate; |
| 415 | if (video_codec.maxBitrate < kViEMinCodecBitrate) |
| 416 | video_codec.maxBitrate = kViEMinCodecBitrate; |
mflodman@webrtc.org | eb16b81 | 2014-06-16 08:57:39 | [diff] [blame] | 417 | if (video_codec.startBitrate < video_codec.minBitrate) |
| 418 | video_codec.startBitrate = video_codec.minBitrate; |
| 419 | if (video_codec.startBitrate > video_codec.maxBitrate) |
| 420 | video_codec.startBitrate = video_codec.maxBitrate; |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 421 | |
| 422 | if (video_codec.startBitrate < video_codec.minBitrate) |
| 423 | video_codec.startBitrate = video_codec.minBitrate; |
| 424 | if (video_codec.startBitrate > video_codec.maxBitrate) |
| 425 | video_codec.startBitrate = video_codec.maxBitrate; |
| 426 | |
pbos@webrtc.org | 6ae48c6 | 2014-06-06 10:49:19 | [diff] [blame] | 427 | assert(streams[0].max_framerate > 0); |
| 428 | video_codec.maxFramerate = streams[0].max_framerate; |
pbos@webrtc.org | f577ae9 | 2014-03-19 08:43:57 | [diff] [blame] | 429 | |
pbos@webrtc.org | 32452b2 | 2014-10-22 12:15:24 | [diff] [blame] | 430 | if (codec_->SetSendCodec(channel_, video_codec) != 0) |
| 431 | return false; |
| 432 | |
pbos@webrtc.org | ad3b5a5 | 2014-10-24 09:23:21 | [diff] [blame] | 433 | assert(config.min_transmit_bitrate_bps >= 0); |
| 434 | rtp_rtcp_->SetMinTransmitBitrate(channel_, |
| 435 | config.min_transmit_bitrate_bps / 1000); |
| 436 | |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 437 | encoder_config_ = config; |
| 438 | use_config_bitrate_ = false; |
pbos@webrtc.org | 32452b2 | 2014-10-22 12:15:24 | [diff] [blame] | 439 | return true; |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 440 | } |
| 441 | |
pbos@webrtc.org | bbb07e6 | 2013-08-05 12:01:36 | [diff] [blame] | 442 | bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
pkasting@chromium.org | 4591fbd | 2014-11-20 22:28:14 | [diff] [blame] | 443 | return network_->ReceivedRTCPPacket(channel_, packet, length) == 0; |
pbos@webrtc.org | bbb07e6 | 2013-08-05 12:01:36 | [diff] [blame] | 444 | } |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 445 | |
pbos@webrtc.org | 273a414 | 2014-12-01 15:23:21 | [diff] [blame] | 446 | VideoSendStream::Stats VideoSendStream::GetStats() { |
stefan@webrtc.org | 168f23f | 2014-07-11 13:44:02 | [diff] [blame] | 447 | return stats_proxy_.GetStats(); |
sprang@webrtc.org | ccd4284 | 2014-01-07 09:54:34 | [diff] [blame] | 448 | } |
| 449 | |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 450 | void VideoSendStream::ConfigureSsrcs() { |
pbos@webrtc.org | 1d0fa5d | 2015-02-19 12:47:00 | [diff] [blame] | 451 | rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.ssrcs.front()); |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 452 | for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| 453 | uint32_t ssrc = config_.rtp.ssrcs[i]; |
| 454 | rtp_rtcp_->SetLocalSSRC( |
| 455 | channel_, ssrc, kViEStreamTypeNormal, static_cast<unsigned char>(i)); |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 456 | RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| 457 | if (it != suspended_ssrcs_.end()) |
| 458 | rtp_rtcp_->SetRtpStateForSsrc(channel_, ssrc, it->second); |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 459 | } |
| 460 | |
| 461 | if (config_.rtp.rtx.ssrcs.empty()) { |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 462 | return; |
| 463 | } |
| 464 | |
| 465 | // Set up RTX. |
| 466 | assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size()); |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 467 | for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
| 468 | uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 469 | rtp_rtcp_->SetLocalSSRC(channel_, |
| 470 | config_.rtp.rtx.ssrcs[i], |
| 471 | kViEStreamTypeRtx, |
| 472 | static_cast<unsigned char>(i)); |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 473 | RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| 474 | if (it != suspended_ssrcs_.end()) |
| 475 | rtp_rtcp_->SetRtpStateForSsrc(channel_, ssrc, it->second); |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 476 | } |
| 477 | |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 478 | assert(config_.rtp.rtx.payload_type >= 0); |
andrew@webrtc.org | 8f27fcc | 2015-01-09 20:22:46 | [diff] [blame] | 479 | rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type); |
pbos@webrtc.org | be9d2a4 | 2014-06-30 13:19:09 | [diff] [blame] | 480 | } |
| 481 | |
pbos@webrtc.org | 2bb1bda | 2014-07-07 13:06:48 | [diff] [blame] | 482 | std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
| 483 | std::map<uint32_t, RtpState> rtp_states; |
| 484 | for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| 485 | uint32_t ssrc = config_.rtp.ssrcs[i]; |
| 486 | rtp_states[ssrc] = rtp_rtcp_->GetRtpStateForSsrc(channel_, ssrc); |
| 487 | } |
| 488 | |
| 489 | for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
| 490 | uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
| 491 | rtp_states[ssrc] = rtp_rtcp_->GetRtpStateForSsrc(channel_, ssrc); |
| 492 | } |
| 493 | |
| 494 | return rtp_states; |
| 495 | } |
| 496 | |
pbos@webrtc.org | 0087318 | 2014-11-25 14:03:34 | [diff] [blame] | 497 | void VideoSendStream::SetBitrateConfig( |
| 498 | const Call::Config::BitrateConfig& bitrate_config) { |
| 499 | int last_start_bitrate_bps = bitrate_config_.start_bitrate_bps; |
| 500 | bitrate_config_ = bitrate_config; |
| 501 | if (bitrate_config_.start_bitrate_bps <= 0) { |
| 502 | bitrate_config_.start_bitrate_bps = last_start_bitrate_bps; |
| 503 | } else { |
| 504 | // Override start bitrate with bitrate from config. |
| 505 | use_config_bitrate_ = true; |
| 506 | } |
| 507 | ReconfigureVideoEncoder(encoder_config_); |
| 508 | } |
| 509 | |
pbos@webrtc.org | 26c0c41 | 2014-09-03 16:17:12 | [diff] [blame] | 510 | void VideoSendStream::SignalNetworkState(Call::NetworkState state) { |
| 511 | // When network goes up, enable RTCP status before setting transmission state. |
| 512 | // When it goes down, disable RTCP afterwards. This ensures that any packets |
| 513 | // sent due to the network state changed will not be dropped. |
| 514 | if (state == Call::kNetworkUp) |
| 515 | rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585); |
| 516 | network_->SetNetworkTransmissionState(channel_, state == Call::kNetworkUp); |
| 517 | if (state == Call::kNetworkDown) |
| 518 | rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNone); |
| 519 | } |
| 520 | |
pkasting@chromium.org | 16825b1 | 2015-01-12 21:51:21 | [diff] [blame] | 521 | int64_t VideoSendStream::GetPacerQueuingDelayMs() const { |
| 522 | int64_t pacer_delay_ms = 0; |
stefan@webrtc.org | 0bae1fa | 2014-11-05 14:05:29 | [diff] [blame] | 523 | if (rtp_rtcp_->GetPacerQueuingDelayMs(channel_, &pacer_delay_ms) != 0) { |
| 524 | return 0; |
| 525 | } |
| 526 | return pacer_delay_ms; |
| 527 | } |
pbos@webrtc.org | 2b19f06 | 2014-12-11 13:26:09 | [diff] [blame] | 528 | |
pkasting@chromium.org | 16825b1 | 2015-01-12 21:51:21 | [diff] [blame] | 529 | int64_t VideoSendStream::GetRtt() const { |
pbos@webrtc.org | 2b19f06 | 2014-12-11 13:26:09 | [diff] [blame] | 530 | webrtc::RtcpStatistics rtcp_stats; |
pkasting@chromium.org | 16825b1 | 2015-01-12 21:51:21 | [diff] [blame] | 531 | int64_t rtt_ms; |
pbos@webrtc.org | 2b19f06 | 2014-12-11 13:26:09 | [diff] [blame] | 532 | if (rtp_rtcp_->GetSendChannelRtcpStatistics(channel_, rtcp_stats, rtt_ms) == |
| 533 | 0) { |
| 534 | return rtt_ms; |
| 535 | } |
| 536 | return -1; |
| 537 | } |
pbos@webrtc.org | 29d5839 | 2013-05-16 12:08:03 | [diff] [blame] | 538 | } // namespace internal |
| 539 | } // namespace webrtc |