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 11 #include "webrtc/video/video_send_stream.h" 12 13 #include <algorithm> 14 #include <sstream> 15 #include <string> 16 #include <vector> 17 18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 19 #include "webrtc/system_wrappers/interface/logging.h" 20 #include "webrtc/video_engine/include/vie_base.h" 21 #include "webrtc/video_engine/include/vie_capture.h" 22 #include "webrtc/video_engine/include/vie_codec.h" 23 #include "webrtc/video_engine/include/vie_external_codec.h" 24 #include "webrtc/video_engine/include/vie_image_process.h" 25 #include "webrtc/video_engine/include/vie_network.h" 26 #include "webrtc/video_engine/include/vie_rtp_rtcp.h" 27 #include "webrtc/video_engine/vie_defines.h" 28 #include "webrtc/video_send_stream.h" 29 30 namespace webrtc { 31 std::string 32 VideoSendStream::Config::EncoderSettings::ToString() const { 33 std::stringstream ss; 34 ss << "{payload_name: " << payload_name; 35 ss << ", payload_type: " << payload_type; 36 if (encoder != NULL) 37 ss << ", encoder: " << (encoder != NULL ? "(encoder)" : "NULL"); 38 ss << '}'; 39 return ss.str(); 40 } 41 42 std::string VideoSendStream::Config::Rtp::Rtx::ToString() 43 const { 44 std::stringstream ss; 45 ss << "{ssrcs: {"; 46 for (size_t i = 0; i < ssrcs.size(); ++i) { 47 ss << ssrcs[i]; 48 if (i != ssrcs.size() - 1) 49 ss << "}, {"; 50 } 51 ss << '}'; 52 53 ss << ", payload_type: " << payload_type; 54 ss << '}'; 55 return ss.str(); 56 } 57 58 std::string VideoSendStream::Config::Rtp::ToString() const { 59 std::stringstream ss; 60 ss << "{ssrcs: {"; 61 for (size_t i = 0; i < ssrcs.size(); ++i) { 62 ss << ssrcs[i]; 63 if (i != ssrcs.size() - 1) 64 ss << "}, {"; 65 } 66 ss << '}'; 67 68 ss << ", max_packet_size: " << max_packet_size; 69 if (min_transmit_bitrate_bps != 0) 70 ss << ", min_transmit_bitrate_bps: " << min_transmit_bitrate_bps; 71 72 ss << ", extensions: {"; 73 for (size_t i = 0; i < extensions.size(); ++i) { 74 ss << extensions[i].ToString(); 75 if (i != extensions.size() - 1) 76 ss << "}, {"; 77 } 78 ss << '}'; 79 80 if (nack.rtp_history_ms != 0) 81 ss << ", nack.rtp_history_ms: " << nack.rtp_history_ms; 82 if (fec.ulpfec_payload_type != -1 || fec.red_payload_type != -1) 83 ss << ", fec: " << fec.ToString(); 84 if (rtx.payload_type != 0 || !rtx.ssrcs.empty()) 85 ss << ", rtx: " << rtx.ToString(); 86 if (c_name != "") 87 ss << ", c_name: " << c_name; 88 ss << '}'; 89 return ss.str(); 90 } 91 92 std::string VideoSendStream::Config::ToString() const { 93 std::stringstream ss; 94 ss << "{encoder_settings: " << encoder_settings.ToString(); 95 ss << ", rtp: " << rtp.ToString(); 96 if (pre_encode_callback != NULL) 97 ss << ", (pre_encode_callback)"; 98 if (post_encode_callback != NULL) 99 ss << ", (post_encode_callback)"; 100 if (local_renderer != NULL) { 101 ss << ", (local_renderer, render_delay_ms: " << render_delay_ms << ")"; 102 } 103 if (target_delay_ms > 0) 104 ss << ", target_delay_ms: " << target_delay_ms; 105 if (suspend_below_min_bitrate) 106 ss << ", suspend_below_min_bitrate: on"; 107 ss << '}'; 108 return ss.str(); 109 } 110 111 namespace internal { 112 VideoSendStream::VideoSendStream( 113 newapi::Transport* transport, 114 CpuOveruseObserver* overuse_observer, 115 webrtc::VideoEngine* video_engine, 116 const VideoSendStream::Config& config, 117 const VideoEncoderConfig& encoder_config, 118 const std::map<uint32_t, RtpState>& suspended_ssrcs, 119 int base_channel, 120 int start_bitrate_bps) 121 : transport_adapter_(transport), 122 encoded_frame_proxy_(config.post_encode_callback), 123 config_(config), 124 start_bitrate_bps_(start_bitrate_bps), 125 suspended_ssrcs_(suspended_ssrcs), 126 external_codec_(NULL), 127 channel_(-1), 128 stats_proxy_(config) { 129 video_engine_base_ = ViEBase::GetInterface(video_engine); 130 video_engine_base_->CreateChannel(channel_, base_channel); 131 assert(channel_ != -1); 132 assert(start_bitrate_bps_ > 0); 133 134 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine); 135 assert(rtp_rtcp_ != NULL); 136 137 assert(config_.rtp.ssrcs.size() > 0); 138 139 assert(config_.rtp.min_transmit_bitrate_bps >= 0); 140 rtp_rtcp_->SetMinTransmitBitrate(channel_, 141 config_.rtp.min_transmit_bitrate_bps / 1000); 142 143 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { 144 const std::string& extension = config_.rtp.extensions[i].name; 145 int id = config_.rtp.extensions[i].id; 146 if (extension == RtpExtension::kTOffset) { 147 if (rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id) != 0) 148 abort(); 149 } else if (extension == RtpExtension::kAbsSendTime) { 150 if (rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id) != 0) 151 abort(); 152 } else { 153 abort(); // Unsupported extension. 154 } 155 } 156 157 rtp_rtcp_->SetRembStatus(channel_, true, false); 158 159 // Enable NACK, FEC or both. 160 if (config_.rtp.fec.red_payload_type != -1) { 161 assert(config_.rtp.fec.ulpfec_payload_type != -1); 162 if (config_.rtp.nack.rtp_history_ms > 0) { 163 rtp_rtcp_->SetHybridNACKFECStatus( 164 channel_, 165 true, 166 static_cast<unsigned char>(config_.rtp.fec.red_payload_type), 167 static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type)); 168 } else { 169 rtp_rtcp_->SetFECStatus( 170 channel_, 171 true, 172 static_cast<unsigned char>(config_.rtp.fec.red_payload_type), 173 static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type)); 174 } 175 } else { 176 rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0); 177 } 178 179 ConfigureSsrcs(); 180 181 char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength]; 182 assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength); 183 strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1); 184 rtcp_cname[sizeof(rtcp_cname) - 1] = '\0'; 185 186 rtp_rtcp_->SetRTCPCName(channel_, rtcp_cname); 187 188 capture_ = ViECapture::GetInterface(video_engine); 189 capture_->AllocateExternalCaptureDevice(capture_id_, external_capture_); 190 capture_->ConnectCaptureDevice(capture_id_, channel_); 191 192 network_ = ViENetwork::GetInterface(video_engine); 193 assert(network_ != NULL); 194 195 network_->RegisterSendTransport(channel_, transport_adapter_); 196 // 28 to match packet overhead in ModuleRtpRtcpImpl. 197 network_->SetMTU(channel_, 198 static_cast<unsigned int>(config_.rtp.max_packet_size + 28)); 199 200 assert(config.encoder_settings.encoder != NULL); 201 assert(config.encoder_settings.payload_type >= 0); 202 assert(config.encoder_settings.payload_type <= 127); 203 external_codec_ = ViEExternalCodec::GetInterface(video_engine); 204 if (external_codec_->RegisterExternalSendCodec( 205 channel_, 206 config.encoder_settings.payload_type, 207 config.encoder_settings.encoder, 208 false) != 0) { 209 abort(); 210 } 211 212 codec_ = ViECodec::GetInterface(video_engine); 213 if (!ReconfigureVideoEncoder(encoder_config)) 214 abort(); 215 216 if (overuse_observer) 217 video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer); 218 219 video_engine_base_->RegisterSendSideDelayObserver(channel_, &stats_proxy_); 220 221 image_process_ = ViEImageProcess::GetInterface(video_engine); 222 image_process_->RegisterPreEncodeCallback(channel_, 223 config_.pre_encode_callback); 224 if (config_.post_encode_callback) { 225 image_process_->RegisterPostEncodeImageCallback(channel_, 226 &encoded_frame_proxy_); 227 } 228 229 if (config_.suspend_below_min_bitrate) 230 codec_->SuspendBelowMinBitrate(channel_); 231 232 rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_, 233 &stats_proxy_); 234 rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_, 235 &stats_proxy_); 236 rtp_rtcp_->RegisterSendBitrateObserver(channel_, &stats_proxy_); 237 rtp_rtcp_->RegisterSendFrameCountObserver(channel_, &stats_proxy_); 238 239 codec_->RegisterEncoderObserver(channel_, stats_proxy_); 240 capture_->RegisterObserver(capture_id_, stats_proxy_); 241 } 242 243 VideoSendStream::~VideoSendStream() { 244 capture_->DeregisterObserver(capture_id_); 245 codec_->DeregisterEncoderObserver(channel_); 246 247 rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, &stats_proxy_); 248 rtp_rtcp_->DeregisterSendBitrateObserver(channel_, &stats_proxy_); 249 rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_, 250 &stats_proxy_); 251 rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_, 252 &stats_proxy_); 253 254 image_process_->DeRegisterPreEncodeCallback(channel_); 255 256 network_->DeregisterSendTransport(channel_); 257 258 capture_->DisconnectCaptureDevice(channel_); 259 capture_->ReleaseCaptureDevice(capture_id_); 260 261 external_codec_->DeRegisterExternalSendCodec( 262 channel_, config_.encoder_settings.payload_type); 263 264 video_engine_base_->DeleteChannel(channel_); 265 266 image_process_->Release(); 267 video_engine_base_->Release(); 268 capture_->Release(); 269 codec_->Release(); 270 if (external_codec_) 271 external_codec_->Release(); 272 network_->Release(); 273 rtp_rtcp_->Release(); 274 } 275 276 void VideoSendStream::SwapFrame(I420VideoFrame* frame) { 277 // TODO(pbos): Local rendering should not be done on the capture thread. 278 if (config_.local_renderer != NULL) 279 config_.local_renderer->RenderFrame(*frame, 0); 280 281 external_capture_->SwapFrame(frame); 282 } 283 284 VideoSendStreamInput* VideoSendStream::Input() { return this; } 285 286 void VideoSendStream::Start() { 287 transport_adapter_.Enable(); 288 video_engine_base_->StartSend(channel_); 289 video_engine_base_->StartReceive(channel_); 290 } 291 292 void VideoSendStream::Stop() { 293 video_engine_base_->StopSend(channel_); 294 video_engine_base_->StopReceive(channel_); 295 transport_adapter_.Disable(); 296 } 297 298 bool VideoSendStream::ReconfigureVideoEncoder( 299 const VideoEncoderConfig& config) { 300 const std::vector<VideoStream>& streams = config.streams; 301 assert(!streams.empty()); 302 assert(config_.rtp.ssrcs.size() >= streams.size()); 303 304 VideoCodec video_codec; 305 memset(&video_codec, 0, sizeof(video_codec)); 306 if (config_.encoder_settings.payload_name == "VP8") { 307 video_codec.codecType = kVideoCodecVP8; 308 } else if (config_.encoder_settings.payload_name == "H264") { 309 video_codec.codecType = kVideoCodecH264; 310 } else { 311 video_codec.codecType = kVideoCodecGeneric; 312 } 313 switch (config.content_type) { 314 case VideoEncoderConfig::kRealtimeVideo: 315 video_codec.mode = kRealtimeVideo; 316 break; 317 case VideoEncoderConfig::kScreenshare: 318 video_codec.mode = kScreensharing; 319 break; 320 } 321 322 if (video_codec.codecType == kVideoCodecVP8) { 323 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); 324 } else if (video_codec.codecType == kVideoCodecH264) { 325 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); 326 } 327 328 if (video_codec.codecType == kVideoCodecVP8) { 329 if (config.encoder_specific_settings != NULL) { 330 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( 331 config.encoder_specific_settings); 332 } 333 video_codec.codecSpecific.VP8.numberOfTemporalLayers = 334 static_cast<unsigned char>(streams.back().temporal_layers.size()); 335 } else { 336 // TODO(pbos): Support encoder_settings codec-agnostically. 337 assert(config.encoder_specific_settings == NULL); 338 } 339 340 strncpy(video_codec.plName, 341 config_.encoder_settings.payload_name.c_str(), 342 kPayloadNameSize - 1); 343 video_codec.plName[kPayloadNameSize - 1] = '\0'; 344 video_codec.plType = config_.encoder_settings.payload_type; 345 video_codec.numberOfSimulcastStreams = 346 static_cast<unsigned char>(streams.size()); 347 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000; 348 assert(streams.size() <= kMaxSimulcastStreams); 349 for (size_t i = 0; i < streams.size(); ++i) { 350 SimulcastStream* sim_stream = &video_codec.simulcastStream[i]; 351 assert(streams[i].width > 0); 352 assert(streams[i].height > 0); 353 assert(streams[i].max_framerate > 0); 354 // Different framerates not supported per stream at the moment. 355 assert(streams[i].max_framerate == streams[0].max_framerate); 356 assert(streams[i].min_bitrate_bps >= 0); 357 assert(streams[i].target_bitrate_bps >= streams[i].min_bitrate_bps); 358 assert(streams[i].max_bitrate_bps >= streams[i].target_bitrate_bps); 359 assert(streams[i].max_qp >= 0); 360 361 sim_stream->width = static_cast<unsigned short>(streams[i].width); 362 sim_stream->height = static_cast<unsigned short>(streams[i].height); 363 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000; 364 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000; 365 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000; 366 sim_stream->qpMax = streams[i].max_qp; 367 sim_stream->numberOfTemporalLayers = 368 static_cast<unsigned char>(streams[i].temporal_layers.size()); 369 370 video_codec.width = std::max(video_codec.width, 371 static_cast<unsigned short>(streams[i].width)); 372 video_codec.height = std::max( 373 video_codec.height, static_cast<unsigned short>(streams[i].height)); 374 video_codec.minBitrate = 375 std::min(video_codec.minBitrate, 376 static_cast<unsigned int>(streams[i].min_bitrate_bps / 1000)); 377 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000; 378 video_codec.qpMax = std::max(video_codec.qpMax, 379 static_cast<unsigned int>(streams[i].max_qp)); 380 } 381 video_codec.startBitrate = 382 static_cast<unsigned int>(start_bitrate_bps_) / 1000; 383 384 if (video_codec.minBitrate < kViEMinCodecBitrate) 385 video_codec.minBitrate = kViEMinCodecBitrate; 386 if (video_codec.maxBitrate < kViEMinCodecBitrate) 387 video_codec.maxBitrate = kViEMinCodecBitrate; 388 if (video_codec.startBitrate < video_codec.minBitrate) 389 video_codec.startBitrate = video_codec.minBitrate; 390 if (video_codec.startBitrate > video_codec.maxBitrate) 391 video_codec.startBitrate = video_codec.maxBitrate; 392 393 if (video_codec.startBitrate < video_codec.minBitrate) 394 video_codec.startBitrate = video_codec.minBitrate; 395 if (video_codec.startBitrate > video_codec.maxBitrate) 396 video_codec.startBitrate = video_codec.maxBitrate; 397 398 assert(streams[0].max_framerate > 0); 399 video_codec.maxFramerate = streams[0].max_framerate; 400 401 return codec_->SetSendCodec(channel_, video_codec) == 0; 402 } 403 404 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { 405 return network_->ReceivedRTCPPacket( 406 channel_, packet, static_cast<int>(length)) == 0; 407 } 408 409 VideoSendStream::Stats VideoSendStream::GetStats() const { 410 return stats_proxy_.GetStats(); 411 } 412 413 void VideoSendStream::ConfigureSsrcs() { 414 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { 415 uint32_t ssrc = config_.rtp.ssrcs[i]; 416 rtp_rtcp_->SetLocalSSRC( 417 channel_, ssrc, kViEStreamTypeNormal, static_cast<unsigned char>(i)); 418 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); 419 if (it != suspended_ssrcs_.end()) 420 rtp_rtcp_->SetRtpStateForSsrc(channel_, ssrc, it->second); 421 } 422 423 if (config_.rtp.rtx.ssrcs.empty()) { 424 assert(!config_.rtp.rtx.pad_with_redundant_payloads); 425 return; 426 } 427 428 // Set up RTX. 429 assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size()); 430 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { 431 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; 432 rtp_rtcp_->SetLocalSSRC(channel_, 433 config_.rtp.rtx.ssrcs[i], 434 kViEStreamTypeRtx, 435 static_cast<unsigned char>(i)); 436 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); 437 if (it != suspended_ssrcs_.end()) 438 rtp_rtcp_->SetRtpStateForSsrc(channel_, ssrc, it->second); 439 } 440 441 if (config_.rtp.rtx.pad_with_redundant_payloads) { 442 rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true); 443 } 444 445 assert(config_.rtp.rtx.payload_type >= 0); 446 rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type); 447 } 448 449 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { 450 std::map<uint32_t, RtpState> rtp_states; 451 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { 452 uint32_t ssrc = config_.rtp.ssrcs[i]; 453 rtp_states[ssrc] = rtp_rtcp_->GetRtpStateForSsrc(channel_, ssrc); 454 } 455 456 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { 457 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; 458 rtp_states[ssrc] = rtp_rtcp_->GetRtpStateForSsrc(channel_, ssrc); 459 } 460 461 return rtp_states; 462 } 463 464 void VideoSendStream::SignalNetworkState(Call::NetworkState state) { 465 // When network goes up, enable RTCP status before setting transmission state. 466 // When it goes down, disable RTCP afterwards. This ensures that any packets 467 // sent due to the network state changed will not be dropped. 468 if (state == Call::kNetworkUp) 469 rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585); 470 network_->SetNetworkTransmissionState(channel_, state == Call::kNetworkUp); 471 if (state == Call::kNetworkDown) 472 rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNone); 473 } 474 475 } // namespace internal 476 } // namespace webrtc 477