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