1 /* 2 * Copyright (c) 2012 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_engine/vie_codec_impl.h" 12 13 #include <list> 14 15 #include "webrtc/engine_configurations.h" 16 #include "webrtc/modules/video_coding/main/interface/video_coding.h" 17 #include "webrtc/system_wrappers/interface/logging.h" 18 #include "webrtc/video_engine/include/vie_errors.h" 19 #include "webrtc/video_engine/vie_capturer.h" 20 #include "webrtc/video_engine/vie_channel.h" 21 #include "webrtc/video_engine/vie_channel_manager.h" 22 #include "webrtc/video_engine/vie_defines.h" 23 #include "webrtc/video_engine/vie_encoder.h" 24 #include "webrtc/video_engine/vie_impl.h" 25 #include "webrtc/video_engine/vie_input_manager.h" 26 #include "webrtc/video_engine/vie_shared_data.h" 27 28 namespace webrtc { 29 30 static void LogCodec(const VideoCodec& codec) { 31 LOG(LS_INFO) << "CodecType " << codec.codecType 32 << ", pl_type " << static_cast<int>(codec.plType) 33 << ", resolution " << codec.width 34 << " x " << codec.height 35 << ", start br " << codec.startBitrate 36 << ", min br " << codec.minBitrate 37 << ", max br " << codec.maxBitrate 38 << ", max fps " << static_cast<int>(codec.maxFramerate) 39 << ", max qp " << codec.qpMax 40 << ", number of streams " 41 << static_cast<int>(codec.numberOfSimulcastStreams); 42 if (codec.codecType == kVideoCodecVP8) { 43 LOG(LS_INFO) << "VP8 specific settings"; 44 LOG(LS_INFO) << "pictureLossIndicationOn " 45 << codec.codecSpecific.VP8.pictureLossIndicationOn 46 << ", feedbackModeOn " 47 << codec.codecSpecific.VP8.feedbackModeOn 48 << ", complexity " 49 << codec.codecSpecific.VP8.complexity 50 << ", resilience " 51 << codec.codecSpecific.VP8.resilience 52 << ", numberOfTemporalLayers " 53 << static_cast<int>( 54 codec.codecSpecific.VP8.numberOfTemporalLayers) 55 << ", keyFrameinterval " 56 << codec.codecSpecific.VP8.keyFrameInterval; 57 for (int idx = 0; idx < codec.numberOfSimulcastStreams; ++idx) { 58 LOG(LS_INFO) << "Stream " << codec.simulcastStream[idx].width 59 << " x " << codec.simulcastStream[idx].height; 60 LOG(LS_INFO) << "Temporal layers " 61 << static_cast<int>( 62 codec.simulcastStream[idx].numberOfTemporalLayers) 63 << ", min br " 64 << codec.simulcastStream[idx].minBitrate 65 << ", target br " 66 << codec.simulcastStream[idx].targetBitrate 67 << ", max br " 68 << codec.simulcastStream[idx].maxBitrate 69 << ", qp max " 70 << codec.simulcastStream[idx].qpMax; 71 } 72 } else if (codec.codecType == kVideoCodecH264) { 73 LOG(LS_INFO) << "H264 specific settings"; 74 LOG(LS_INFO) << "profile: " 75 << codec.codecSpecific.H264.profile 76 << ", framedropping: " 77 << codec.codecSpecific.H264.frameDroppingOn 78 << ", keyFrameInterval: " 79 << codec.codecSpecific.H264.keyFrameInterval 80 << ", spslen: " 81 << codec.codecSpecific.H264.spsLen 82 << ", ppslen: " 83 << codec.codecSpecific.H264.ppsLen; 84 } 85 } 86 87 88 ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) { 89 #ifdef WEBRTC_VIDEO_ENGINE_CODEC_API 90 if (!video_engine) { 91 return NULL; 92 } 93 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine); 94 ViECodecImpl* vie_codec_impl = vie_impl; 95 // Increase ref count. 96 (*vie_codec_impl)++; 97 return vie_codec_impl; 98 #else 99 return NULL; 100 #endif 101 } 102 103 int ViECodecImpl::Release() { 104 LOG(LS_INFO) << "ViECodec::Release."; 105 // Decrease ref count. 106 (*this)--; 107 108 int32_t ref_count = GetCount(); 109 if (ref_count < 0) { 110 LOG(LS_WARNING) << "ViECodec released too many times."; 111 shared_data_->SetLastError(kViEAPIDoesNotExist); 112 return -1; 113 } 114 return ref_count; 115 } 116 117 ViECodecImpl::ViECodecImpl(ViESharedData* shared_data) 118 : shared_data_(shared_data) { 119 } 120 121 ViECodecImpl::~ViECodecImpl() { 122 } 123 124 int ViECodecImpl::NumberOfCodecs() const { 125 // +2 because of FEC(RED and ULPFEC) 126 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2)); 127 } 128 129 int ViECodecImpl::GetCodec(const unsigned char list_number, 130 VideoCodec& video_codec) const { 131 if (list_number == VideoCodingModule::NumberOfCodecs()) { 132 memset(&video_codec, 0, sizeof(VideoCodec)); 133 strcpy(video_codec.plName, "red"); 134 video_codec.codecType = kVideoCodecRED; 135 video_codec.plType = VCM_RED_PAYLOAD_TYPE; 136 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) { 137 memset(&video_codec, 0, sizeof(VideoCodec)); 138 strcpy(video_codec.plName, "ulpfec"); 139 video_codec.codecType = kVideoCodecULPFEC; 140 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE; 141 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) { 142 shared_data_->SetLastError(kViECodecInvalidArgument); 143 return -1; 144 } 145 return 0; 146 } 147 148 int ViECodecImpl::SetSendCodec(const int video_channel, 149 const VideoCodec& video_codec) { 150 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel; 151 LogCodec(video_codec); 152 if (!CodecValid(video_codec)) { 153 // Error logged. 154 shared_data_->SetLastError(kViECodecInvalidCodec); 155 return -1; 156 } 157 158 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 159 ViEChannel* vie_channel = cs.Channel(video_channel); 160 if (!vie_channel) { 161 shared_data_->SetLastError(kViECodecInvalidChannelId); 162 return -1; 163 } 164 165 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 166 assert(vie_encoder); 167 if (vie_encoder->Owner() != video_channel) { 168 LOG_F(LS_ERROR) << "Receive only channel."; 169 shared_data_->SetLastError(kViECodecReceiveOnlyChannel); 170 return -1; 171 } 172 // Set a max_bitrate if the user hasn't set one. 173 VideoCodec video_codec_internal; 174 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec)); 175 if (video_codec_internal.maxBitrate == 0) { 176 // Max is one bit per pixel. 177 video_codec_internal.maxBitrate = (video_codec_internal.width * 178 video_codec_internal.height * 179 video_codec_internal.maxFramerate) 180 / 1000; 181 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate; 182 } 183 184 if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) { 185 video_codec_internal.startBitrate = video_codec_internal.minBitrate; 186 } 187 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) { 188 video_codec_internal.startBitrate = video_codec_internal.maxBitrate; 189 } 190 191 VideoCodec encoder; 192 vie_encoder->GetEncoder(&encoder); 193 194 // Make sure to generate a new SSRC if the codec type and/or resolution has 195 // changed. This won't have any effect if the user has set an SSRC. 196 bool new_rtp_stream = false; 197 if (encoder.codecType != video_codec_internal.codecType) { 198 new_rtp_stream = true; 199 } 200 201 ViEInputManagerScoped is(*(shared_data_->input_manager())); 202 203 // Stop the media flow while reconfiguring. 204 vie_encoder->Pause(); 205 206 if (vie_encoder->SetEncoder(video_codec_internal) != 0) { 207 shared_data_->SetLastError(kViECodecUnknownError); 208 return -1; 209 } 210 211 // Give the channel(s) the new information. 212 ChannelList channels; 213 cs.ChannelsUsingViEEncoder(video_channel, &channels); 214 for (ChannelList::iterator it = channels.begin(); it != channels.end(); 215 ++it) { 216 bool ret = true; 217 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) { 218 ret = false; 219 } 220 if (!ret) { 221 shared_data_->SetLastError(kViECodecUnknownError); 222 return -1; 223 } 224 } 225 226 // TODO(mflodman) Break out this part in GetLocalSsrcList(). 227 // Update all SSRCs to ViEEncoder. 228 std::list<unsigned int> ssrcs; 229 if (video_codec_internal.numberOfSimulcastStreams == 0) { 230 unsigned int ssrc = 0; 231 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) { 232 LOG_F(LS_ERROR) << "Could not get ssrc."; 233 } 234 ssrcs.push_back(ssrc); 235 } else { 236 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams; 237 ++idx) { 238 unsigned int ssrc = 0; 239 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) { 240 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx; 241 } 242 ssrcs.push_back(ssrc); 243 } 244 } 245 vie_encoder->SetSsrcs(ssrcs); 246 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs); 247 248 // Update the protection mode, we might be switching NACK/FEC. 249 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled()); 250 251 // Get new best format for frame provider. 252 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder); 253 if (frame_provider) { 254 frame_provider->FrameCallbackChanged(); 255 } 256 // Restart the media flow 257 if (new_rtp_stream) { 258 // Stream settings changed, make sure we get a key frame. 259 vie_encoder->SendKeyFrame(); 260 } 261 vie_encoder->Restart(); 262 return 0; 263 } 264 265 int ViECodecImpl::GetSendCodec(const int video_channel, 266 VideoCodec& video_codec) const { 267 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 268 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 269 if (!vie_encoder) { 270 shared_data_->SetLastError(kViECodecInvalidChannelId); 271 return -1; 272 } 273 return vie_encoder->GetEncoder(&video_codec); 274 } 275 276 int ViECodecImpl::SetReceiveCodec(const int video_channel, 277 const VideoCodec& video_codec) { 278 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel; 279 LOG(LS_INFO) << "Codec type " << video_codec.codecType 280 << ", payload type " << video_codec.plType; 281 282 if (CodecValid(video_codec) == false) { 283 shared_data_->SetLastError(kViECodecInvalidCodec); 284 return -1; 285 } 286 287 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 288 ViEChannel* vie_channel = cs.Channel(video_channel); 289 if (!vie_channel) { 290 shared_data_->SetLastError(kViECodecInvalidChannelId); 291 return -1; 292 } 293 294 if (vie_channel->SetReceiveCodec(video_codec) != 0) { 295 shared_data_->SetLastError(kViECodecUnknownError); 296 return -1; 297 } 298 return 0; 299 } 300 301 int ViECodecImpl::GetReceiveCodec(const int video_channel, 302 VideoCodec& video_codec) const { 303 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 304 ViEChannel* vie_channel = cs.Channel(video_channel); 305 if (!vie_channel) { 306 shared_data_->SetLastError(kViECodecInvalidChannelId); 307 return -1; 308 } 309 310 if (vie_channel->GetReceiveCodec(&video_codec) != 0) { 311 shared_data_->SetLastError(kViECodecUnknownError); 312 return -1; 313 } 314 return 0; 315 } 316 317 int ViECodecImpl::GetCodecConfigParameters( 318 const int video_channel, 319 unsigned char config_parameters[kConfigParameterSize], 320 unsigned char& config_parameters_size) const { 321 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel; 322 323 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 324 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 325 if (!vie_encoder) { 326 shared_data_->SetLastError(kViECodecInvalidChannelId); 327 return -1; 328 } 329 330 if (vie_encoder->GetCodecConfigParameters(config_parameters, 331 config_parameters_size) != 0) { 332 shared_data_->SetLastError(kViECodecUnknownError); 333 return -1; 334 } 335 return 0; 336 } 337 338 int ViECodecImpl::SetImageScaleStatus(const int video_channel, 339 const bool enable) { 340 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel 341 << ", enable: " << enable; 342 343 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 344 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 345 if (!vie_encoder) { 346 shared_data_->SetLastError(kViECodecInvalidChannelId); 347 return -1; 348 } 349 350 if (vie_encoder->ScaleInputImage(enable) != 0) { 351 shared_data_->SetLastError(kViECodecUnknownError); 352 return -1; 353 } 354 return 0; 355 } 356 357 int ViECodecImpl::GetSendCodecStastistics(const int video_channel, 358 unsigned int& key_frames, 359 unsigned int& delta_frames) const { 360 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 361 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 362 if (!vie_encoder) { 363 shared_data_->SetLastError(kViECodecInvalidChannelId); 364 return -1; 365 } 366 367 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) { 368 shared_data_->SetLastError(kViECodecUnknownError); 369 return -1; 370 } 371 return 0; 372 } 373 374 int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel, 375 unsigned int& key_frames, 376 unsigned int& delta_frames) const { 377 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 378 ViEChannel* vie_channel = cs.Channel(video_channel); 379 if (!vie_channel) { 380 shared_data_->SetLastError(kViECodecInvalidChannelId); 381 return -1; 382 } 383 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) { 384 shared_data_->SetLastError(kViECodecUnknownError); 385 return -1; 386 } 387 return 0; 388 } 389 390 int ViECodecImpl::GetReceiveSideDelay(const int video_channel, 391 int* delay_ms) const { 392 assert(delay_ms != NULL); 393 394 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 395 ViEChannel* vie_channel = cs.Channel(video_channel); 396 if (!vie_channel) { 397 shared_data_->SetLastError(kViECodecInvalidChannelId); 398 return -1; 399 } 400 *delay_ms = vie_channel->ReceiveDelay(); 401 if (*delay_ms < 0) { 402 return -1; 403 } 404 return 0; 405 } 406 407 408 int ViECodecImpl::GetCodecTargetBitrate(const int video_channel, 409 unsigned int* bitrate) const { 410 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 411 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 412 if (!vie_encoder) { 413 shared_data_->SetLastError(kViECodecInvalidChannelId); 414 return -1; 415 } 416 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate)); 417 } 418 419 int ViECodecImpl::GetNumDiscardedPackets(int video_channel) const { 420 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 421 ViEChannel* vie_channel = cs.Channel(video_channel); 422 if (!vie_channel) { 423 shared_data_->SetLastError(kViECodecInvalidChannelId); 424 return -1; 425 } 426 return static_cast<int>(vie_channel->DiscardedPackets()); 427 } 428 429 int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel, 430 const bool enable) { 431 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel 432 << ", enable " << enable; 433 434 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 435 ViEChannel* vie_channel = cs.Channel(video_channel); 436 if (!vie_channel) { 437 shared_data_->SetLastError(kViECodecInvalidChannelId); 438 return -1; 439 } 440 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) { 441 shared_data_->SetLastError(kViECodecUnknownError); 442 return -1; 443 } 444 return 0; 445 } 446 447 int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel, 448 const bool enable, 449 const bool only_key_frames) { 450 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel 451 << "enable, " << enable 452 << ", only key frames " << only_key_frames; 453 454 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 455 ViEChannel* vie_channel = cs.Channel(video_channel); 456 if (!vie_channel) { 457 shared_data_->SetLastError(kViECodecInvalidChannelId); 458 return -1; 459 } 460 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) { 461 shared_data_->SetLastError(kViECodecUnknownError); 462 return -1; 463 } 464 return 0; 465 } 466 467 int ViECodecImpl::RegisterEncoderObserver(const int video_channel, 468 ViEEncoderObserver& observer) { 469 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel; 470 471 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 472 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 473 if (!vie_encoder) { 474 shared_data_->SetLastError(kViECodecInvalidChannelId); 475 return -1; 476 } 477 if (vie_encoder->RegisterCodecObserver(&observer) != 0) { 478 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered); 479 return -1; 480 } 481 return 0; 482 } 483 484 int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) { 485 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel; 486 487 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 488 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 489 if (!vie_encoder) { 490 shared_data_->SetLastError(kViECodecInvalidChannelId); 491 return -1; 492 } 493 if (vie_encoder->RegisterCodecObserver(NULL) != 0) { 494 shared_data_->SetLastError(kViECodecObserverNotRegistered); 495 return -1; 496 } 497 return 0; 498 } 499 500 int ViECodecImpl::RegisterDecoderObserver(const int video_channel, 501 ViEDecoderObserver& observer) { 502 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel; 503 504 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 505 ViEChannel* vie_channel = cs.Channel(video_channel); 506 if (!vie_channel) { 507 shared_data_->SetLastError(kViECodecInvalidChannelId); 508 return -1; 509 } 510 if (vie_channel->RegisterCodecObserver(&observer) != 0) { 511 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered); 512 return -1; 513 } 514 return 0; 515 } 516 517 int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) { 518 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel; 519 520 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 521 ViEChannel* vie_channel = cs.Channel(video_channel); 522 if (!vie_channel) { 523 shared_data_->SetLastError(kViECodecInvalidChannelId); 524 return -1; 525 } 526 if (vie_channel->RegisterCodecObserver(NULL) != 0) { 527 shared_data_->SetLastError(kViECodecObserverNotRegistered); 528 return -1; 529 } 530 return 0; 531 } 532 533 int ViECodecImpl::SendKeyFrame(const int video_channel) { 534 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel; 535 536 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 537 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 538 if (!vie_encoder) { 539 shared_data_->SetLastError(kViECodecInvalidChannelId); 540 return -1; 541 } 542 if (vie_encoder->SendKeyFrame() != 0) { 543 shared_data_->SetLastError(kViECodecUnknownError); 544 return -1; 545 } 546 return 0; 547 } 548 549 int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel, 550 const bool wait) { 551 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel 552 << ", wait " << wait; 553 554 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 555 ViEChannel* vie_channel = cs.Channel(video_channel); 556 if (!vie_channel) { 557 shared_data_->SetLastError(kViECodecInvalidChannelId); 558 return -1; 559 } 560 if (vie_channel->WaitForKeyFrame(wait) != 0) { 561 shared_data_->SetLastError(kViECodecUnknownError); 562 return -1; 563 } 564 return 0; 565 } 566 567 int ViECodecImpl::StartDebugRecording(int video_channel, 568 const char* file_name_utf8) { 569 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel; 570 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 571 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 572 if (!vie_encoder) { 573 return -1; 574 } 575 return vie_encoder->StartDebugRecording(file_name_utf8); 576 } 577 578 int ViECodecImpl::StopDebugRecording(int video_channel) { 579 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel; 580 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 581 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 582 if (!vie_encoder) { 583 return -1; 584 } 585 return vie_encoder->StopDebugRecording(); 586 } 587 588 void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) { 589 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel; 590 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 591 ViEEncoder* vie_encoder = cs.Encoder(video_channel); 592 if (!vie_encoder) { 593 return; 594 } 595 vie_encoder->SuspendBelowMinBitrate(); 596 ViEChannel* vie_channel = cs.Channel(video_channel); 597 if (!vie_channel) { 598 return; 599 } 600 // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no 601 // padding will be sent when the video is suspended so the video will be 602 // unable to recover. 603 vie_channel->SetTransmissionSmoothingStatus(true); 604 } 605 606 bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms, 607 int* max_delay_ms) const { 608 ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); 609 ViEChannel* vie_channel = cs.Channel(video_channel); 610 if (!vie_channel) { 611 shared_data_->SetLastError(kViECodecInvalidChannelId); 612 return false; 613 } 614 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms); 615 } 616 617 bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) { 618 // Check pl_name matches codec_type. 619 if (video_codec.codecType == kVideoCodecRED) { 620 #if defined(WIN32) 621 if (_strnicmp(video_codec.plName, "red", 3) == 0) { 622 #else 623 if (strncasecmp(video_codec.plName, "red", 3) == 0) { 624 #endif 625 // We only care about the type and name for red. 626 return true; 627 } 628 LOG_F(LS_ERROR) << "Invalid RED configuration."; 629 return false; 630 } else if (video_codec.codecType == kVideoCodecULPFEC) { 631 #if defined(WIN32) 632 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) { 633 #else 634 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) { 635 #endif 636 // We only care about the type and name for ULPFEC. 637 return true; 638 } 639 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration."; 640 return false; 641 } else if ((video_codec.codecType == kVideoCodecVP8 && 642 strncmp(video_codec.plName, "VP8", 4) == 0) || 643 (video_codec.codecType == kVideoCodecI420 && 644 strncmp(video_codec.plName, "I420", 4) == 0) || 645 (video_codec.codecType == kVideoCodecH264 && 646 strncmp(video_codec.plName, "H264", 4) == 0)) { 647 // OK. 648 } else if (video_codec.codecType != kVideoCodecGeneric) { 649 LOG(LS_ERROR) << "Codec type and name mismatch."; 650 return false; 651 } 652 653 if (video_codec.plType == 0 || video_codec.plType > 127) { 654 LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType; 655 return false; 656 } 657 658 if (video_codec.width > kViEMaxCodecWidth || 659 video_codec.height > kViEMaxCodecHeight) { 660 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width 661 << " x " << video_codec.height; 662 return false; 663 } 664 665 if (video_codec.startBitrate < kViEMinCodecBitrate) { 666 LOG(LS_ERROR) << "Invalid start bitrate."; 667 return false; 668 } 669 if (video_codec.minBitrate < kViEMinCodecBitrate) { 670 LOG(LS_ERROR) << "Invalid min bitrate."; 671 return false; 672 } 673 return true; 674 } 675 676 } // namespace webrtc 677