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/modules/video_coding/codecs/vp8/vp8_impl.h" 12 13 #include <stdlib.h> 14 #include <string.h> 15 #include <time.h> 16 #include <algorithm> 17 18 // NOTE(ajm): Path provided by gyp. 19 #include "libyuv/scale.h" // NOLINT 20 #include "libyuv/convert.h" // NOLINT 21 22 #include "webrtc/base/checks.h" 23 #include "webrtc/base/trace_event.h" 24 #include "webrtc/common.h" 25 #include "webrtc/common_types.h" 26 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 27 #include "webrtc/modules/include/module_common_types.h" 28 #include "webrtc/modules/video_coding/include/video_codec_interface.h" 29 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 30 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" 31 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" 32 #include "webrtc/system_wrappers/include/tick_util.h" 33 34 namespace webrtc { 35 namespace { 36 37 enum { kVp8ErrorPropagationTh = 30 }; 38 enum { kVp832ByteAlign = 32 }; 39 40 // VP8 denoiser states. 41 enum denoiserState { 42 kDenoiserOff, 43 kDenoiserOnYOnly, 44 kDenoiserOnYUV, 45 kDenoiserOnYUVAggressive, 46 // Adaptive mode defaults to kDenoiserOnYUV on key frame, but may switch 47 // to kDenoiserOnYUVAggressive based on a computed noise metric. 48 kDenoiserOnAdaptive 49 }; 50 51 // Greatest common divisior 52 int GCD(int a, int b) { 53 int c = a % b; 54 while (c != 0) { 55 a = b; 56 b = c; 57 c = a % b; 58 } 59 return b; 60 } 61 62 std::vector<int> GetStreamBitratesKbps(const VideoCodec& codec, 63 int bitrate_to_allocate_kbps) { 64 if (codec.numberOfSimulcastStreams <= 1) { 65 return std::vector<int>(1, bitrate_to_allocate_kbps); 66 } 67 68 std::vector<int> bitrates_kbps(codec.numberOfSimulcastStreams); 69 // Allocate min -> target bitrates as long as we have bitrate to spend. 70 size_t last_active_stream = 0; 71 for (size_t i = 0; i < static_cast<size_t>(codec.numberOfSimulcastStreams) && 72 bitrate_to_allocate_kbps >= 73 static_cast<int>(codec.simulcastStream[i].minBitrate); 74 ++i) { 75 last_active_stream = i; 76 int allocated_bitrate_kbps = 77 std::min(static_cast<int>(codec.simulcastStream[i].targetBitrate), 78 bitrate_to_allocate_kbps); 79 bitrates_kbps[i] = allocated_bitrate_kbps; 80 bitrate_to_allocate_kbps -= allocated_bitrate_kbps; 81 } 82 83 // Spend additional bits on the highest-quality active layer, up to max 84 // bitrate. 85 // TODO(pbos): Consider spending additional bits on last_active_stream-1 down 86 // to 0 and not just the top layer when we have additional bitrate to spend. 87 int allocated_bitrate_kbps = std::min( 88 static_cast<int>(codec.simulcastStream[last_active_stream].maxBitrate - 89 bitrates_kbps[last_active_stream]), 90 bitrate_to_allocate_kbps); 91 bitrates_kbps[last_active_stream] += allocated_bitrate_kbps; 92 bitrate_to_allocate_kbps -= allocated_bitrate_kbps; 93 94 // Make sure we can always send something. Suspending below min bitrate is 95 // controlled outside the codec implementation and is not overriden by this. 96 if (bitrates_kbps[0] < static_cast<int>(codec.simulcastStream[0].minBitrate)) 97 bitrates_kbps[0] = static_cast<int>(codec.simulcastStream[0].minBitrate); 98 99 return bitrates_kbps; 100 } 101 102 uint32_t SumStreamMaxBitrate(int streams, const VideoCodec& codec) { 103 uint32_t bitrate_sum = 0; 104 for (int i = 0; i < streams; ++i) { 105 bitrate_sum += codec.simulcastStream[i].maxBitrate; 106 } 107 return bitrate_sum; 108 } 109 110 int NumberOfStreams(const VideoCodec& codec) { 111 int streams = 112 codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams; 113 uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec); 114 if (simulcast_max_bitrate == 0) { 115 streams = 1; 116 } 117 return streams; 118 } 119 120 bool ValidSimulcastResolutions(const VideoCodec& codec, int num_streams) { 121 if (codec.width != codec.simulcastStream[num_streams - 1].width || 122 codec.height != codec.simulcastStream[num_streams - 1].height) { 123 return false; 124 } 125 for (int i = 0; i < num_streams; ++i) { 126 if (codec.width * codec.simulcastStream[i].height != 127 codec.height * codec.simulcastStream[i].width) { 128 return false; 129 } 130 } 131 return true; 132 } 133 134 int NumStreamsDisabled(const std::vector<bool>& streams) { 135 int num_disabled = 0; 136 for (bool stream : streams) { 137 if (!stream) 138 ++num_disabled; 139 } 140 return num_disabled; 141 } 142 } // namespace 143 144 const float kTl1MaxTimeToDropFrames = 20.0f; 145 146 VP8EncoderImpl::VP8EncoderImpl() 147 : encoded_complete_callback_(NULL), 148 inited_(false), 149 timestamp_(0), 150 feedback_mode_(false), 151 qp_max_(56), // Setting for max quantizer. 152 cpu_speed_default_(-6), 153 rc_max_intra_target_(0), 154 token_partitions_(VP8_ONE_TOKENPARTITION), 155 down_scale_requested_(false), 156 down_scale_bitrate_(0), 157 tl0_frame_dropper_(), 158 tl1_frame_dropper_(kTl1MaxTimeToDropFrames), 159 key_frame_request_(kMaxSimulcastStreams, false), 160 quality_scaler_enabled_(false) { 161 uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); 162 srand(seed); 163 164 picture_id_.reserve(kMaxSimulcastStreams); 165 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); 166 temporal_layers_.reserve(kMaxSimulcastStreams); 167 raw_images_.reserve(kMaxSimulcastStreams); 168 encoded_images_.reserve(kMaxSimulcastStreams); 169 send_stream_.reserve(kMaxSimulcastStreams); 170 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. 171 encoders_.reserve(kMaxSimulcastStreams); 172 configurations_.reserve(kMaxSimulcastStreams); 173 downsampling_factors_.reserve(kMaxSimulcastStreams); 174 } 175 176 VP8EncoderImpl::~VP8EncoderImpl() { 177 Release(); 178 } 179 180 int VP8EncoderImpl::Release() { 181 int ret_val = WEBRTC_VIDEO_CODEC_OK; 182 183 while (!encoded_images_.empty()) { 184 EncodedImage& image = encoded_images_.back(); 185 delete[] image._buffer; 186 encoded_images_.pop_back(); 187 } 188 while (!encoders_.empty()) { 189 vpx_codec_ctx_t& encoder = encoders_.back(); 190 if (vpx_codec_destroy(&encoder)) { 191 ret_val = WEBRTC_VIDEO_CODEC_MEMORY; 192 } 193 encoders_.pop_back(); 194 } 195 configurations_.clear(); 196 send_stream_.clear(); 197 cpu_speed_.clear(); 198 while (!raw_images_.empty()) { 199 vpx_img_free(&raw_images_.back()); 200 raw_images_.pop_back(); 201 } 202 while (!temporal_layers_.empty()) { 203 delete temporal_layers_.back(); 204 temporal_layers_.pop_back(); 205 } 206 inited_ = false; 207 return ret_val; 208 } 209 210 int VP8EncoderImpl::SetRates(uint32_t new_bitrate_kbit, 211 uint32_t new_framerate) { 212 if (!inited_) { 213 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 214 } 215 if (encoders_[0].err) { 216 return WEBRTC_VIDEO_CODEC_ERROR; 217 } 218 if (new_framerate < 1) { 219 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 220 } 221 if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { 222 new_bitrate_kbit = codec_.maxBitrate; 223 } 224 if (new_bitrate_kbit < codec_.minBitrate) { 225 new_bitrate_kbit = codec_.minBitrate; 226 } 227 if (codec_.numberOfSimulcastStreams > 0 && 228 new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) { 229 new_bitrate_kbit = codec_.simulcastStream[0].minBitrate; 230 } 231 codec_.maxFramerate = new_framerate; 232 233 if (encoders_.size() == 1) { 234 // 1:1. 235 // Calculate a rough limit for when to trigger a potental down scale. 236 uint32_t k_pixels_per_frame = codec_.width * codec_.height / 1000; 237 // TODO(pwestin): we currently lack CAMA, this is a temporary fix to work 238 // around the current limitations. 239 // Only trigger keyframes if we are allowed to scale down. 240 if (configurations_[0].rc_resize_allowed) { 241 if (!down_scale_requested_) { 242 if (k_pixels_per_frame > new_bitrate_kbit) { 243 down_scale_requested_ = true; 244 down_scale_bitrate_ = new_bitrate_kbit; 245 key_frame_request_[0] = true; 246 } 247 } else { 248 if (new_bitrate_kbit > (2 * down_scale_bitrate_) || 249 new_bitrate_kbit < (down_scale_bitrate_ / 2)) { 250 down_scale_requested_ = false; 251 } 252 } 253 } 254 } else { 255 // If we have more than 1 stream, reduce the qp_max for the low resolution 256 // stream if frame rate is not too low. The trade-off with lower qp_max is 257 // possibly more dropped frames, so we only do this if the frame rate is 258 // above some threshold (base temporal layer is down to 1/4 for 3 layers). 259 // We may want to condition this on bitrate later. 260 if (new_framerate > 20) { 261 configurations_[encoders_.size() - 1].rc_max_quantizer = 45; 262 } else { 263 // Go back to default value set in InitEncode. 264 configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; 265 } 266 } 267 268 std::vector<int> stream_bitrates = 269 GetStreamBitratesKbps(codec_, new_bitrate_kbit); 270 size_t stream_idx = encoders_.size() - 1; 271 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { 272 if (encoders_.size() > 1) 273 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 274 275 unsigned int target_bitrate = stream_bitrates[stream_idx]; 276 unsigned int max_bitrate = codec_.maxBitrate; 277 int framerate = new_framerate; 278 // TODO(holmer): This is a temporary hack for screensharing, where we 279 // interpret the startBitrate as the encoder target bitrate. This is 280 // to allow for a different max bitrate, so if the codec can't meet 281 // the target we still allow it to overshoot up to the max before dropping 282 // frames. This hack should be improved. 283 if (codec_.targetBitrate > 0 && 284 (codec_.codecSpecific.VP8.numberOfTemporalLayers == 2 || 285 codec_.simulcastStream[0].numberOfTemporalLayers == 2)) { 286 int tl0_bitrate = std::min(codec_.targetBitrate, target_bitrate); 287 max_bitrate = std::min(codec_.maxBitrate, target_bitrate); 288 target_bitrate = tl0_bitrate; 289 } 290 configurations_[i].rc_target_bitrate = target_bitrate; 291 temporal_layers_[stream_idx]->ConfigureBitrates( 292 target_bitrate, max_bitrate, framerate, &configurations_[i]); 293 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { 294 return WEBRTC_VIDEO_CODEC_ERROR; 295 } 296 } 297 quality_scaler_.ReportFramerate(new_framerate); 298 return WEBRTC_VIDEO_CODEC_OK; 299 } 300 301 const char* VP8EncoderImpl::ImplementationName() const { 302 return "libvpx"; 303 } 304 305 void VP8EncoderImpl::SetStreamState(bool send_stream, 306 int stream_idx) { 307 if (send_stream && !send_stream_[stream_idx]) { 308 // Need a key frame if we have not sent this stream before. 309 key_frame_request_[stream_idx] = true; 310 } 311 send_stream_[stream_idx] = send_stream; 312 } 313 314 void VP8EncoderImpl::SetupTemporalLayers(int num_streams, 315 int num_temporal_layers, 316 const VideoCodec& codec) { 317 const Config default_options; 318 const TemporalLayers::Factory& tl_factory = 319 (codec.extra_options ? codec.extra_options : &default_options) 320 ->Get<TemporalLayers::Factory>(); 321 if (num_streams == 1) { 322 if (codec.mode == kScreensharing) { 323 // Special mode when screensharing on a single stream. 324 temporal_layers_.push_back( 325 new ScreenshareLayers(num_temporal_layers, rand())); 326 } else { 327 temporal_layers_.push_back( 328 tl_factory.Create(num_temporal_layers, rand())); 329 } 330 } else { 331 for (int i = 0; i < num_streams; ++i) { 332 // TODO(andresp): crash if layers is invalid. 333 int layers = codec.simulcastStream[i].numberOfTemporalLayers; 334 if (layers < 1) 335 layers = 1; 336 temporal_layers_.push_back(tl_factory.Create(layers, rand())); 337 } 338 } 339 } 340 341 int VP8EncoderImpl::InitEncode(const VideoCodec* inst, 342 int number_of_cores, 343 size_t /*maxPayloadSize */) { 344 if (inst == NULL) { 345 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 346 } 347 if (inst->maxFramerate < 1) { 348 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 349 } 350 // allow zero to represent an unspecified maxBitRate 351 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { 352 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 353 } 354 if (inst->width <= 1 || inst->height <= 1) { 355 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 356 } 357 if (number_of_cores < 1) { 358 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 359 } 360 if (inst->codecSpecific.VP8.feedbackModeOn && 361 inst->numberOfSimulcastStreams > 1) { 362 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 363 } 364 if (inst->codecSpecific.VP8.automaticResizeOn && 365 inst->numberOfSimulcastStreams > 1) { 366 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 367 } 368 int retVal = Release(); 369 if (retVal < 0) { 370 return retVal; 371 } 372 373 int number_of_streams = NumberOfStreams(*inst); 374 bool doing_simulcast = (number_of_streams > 1); 375 376 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { 377 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 378 } 379 380 int num_temporal_layers = 381 doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers 382 : inst->codecSpecific.VP8.numberOfTemporalLayers; 383 384 // TODO(andresp): crash if num temporal layers is bananas. 385 if (num_temporal_layers < 1) 386 num_temporal_layers = 1; 387 SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); 388 389 feedback_mode_ = inst->codecSpecific.VP8.feedbackModeOn; 390 391 timestamp_ = 0; 392 codec_ = *inst; 393 394 // Code expects simulcastStream resolutions to be correct, make sure they are 395 // filled even when there are no simulcast layers. 396 if (codec_.numberOfSimulcastStreams == 0) { 397 codec_.simulcastStream[0].width = codec_.width; 398 codec_.simulcastStream[0].height = codec_.height; 399 } 400 401 picture_id_.resize(number_of_streams); 402 last_key_frame_picture_id_.resize(number_of_streams); 403 encoded_images_.resize(number_of_streams); 404 encoders_.resize(number_of_streams); 405 configurations_.resize(number_of_streams); 406 downsampling_factors_.resize(number_of_streams); 407 raw_images_.resize(number_of_streams); 408 send_stream_.resize(number_of_streams); 409 send_stream_[0] = true; // For non-simulcast case. 410 cpu_speed_.resize(number_of_streams); 411 std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); 412 413 int idx = number_of_streams - 1; 414 for (int i = 0; i < (number_of_streams - 1); ++i, --idx) { 415 int gcd = GCD(inst->simulcastStream[idx].width, 416 inst->simulcastStream[idx - 1].width); 417 downsampling_factors_[i].num = inst->simulcastStream[idx].width / gcd; 418 downsampling_factors_[i].den = inst->simulcastStream[idx - 1].width / gcd; 419 send_stream_[i] = false; 420 } 421 if (number_of_streams > 1) { 422 send_stream_[number_of_streams - 1] = false; 423 downsampling_factors_[number_of_streams - 1].num = 1; 424 downsampling_factors_[number_of_streams - 1].den = 1; 425 } 426 for (int i = 0; i < number_of_streams; ++i) { 427 // Random start, 16 bits is enough. 428 picture_id_[i] = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT 429 last_key_frame_picture_id_[i] = -1; 430 // allocate memory for encoded image 431 if (encoded_images_[i]._buffer != NULL) { 432 delete[] encoded_images_[i]._buffer; 433 } 434 encoded_images_[i]._size = 435 CalcBufferSize(kI420, codec_.width, codec_.height); 436 encoded_images_[i]._buffer = new uint8_t[encoded_images_[i]._size]; 437 encoded_images_[i]._completeFrame = true; 438 } 439 // populate encoder configuration with default values 440 if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &configurations_[0], 441 0)) { 442 return WEBRTC_VIDEO_CODEC_ERROR; 443 } 444 // setting the time base of the codec 445 configurations_[0].g_timebase.num = 1; 446 configurations_[0].g_timebase.den = 90000; 447 configurations_[0].g_lag_in_frames = 0; // 0- no frame lagging 448 449 // Set the error resilience mode according to user settings. 450 switch (inst->codecSpecific.VP8.resilience) { 451 case kResilienceOff: 452 // TODO(marpan): We should set keep error resilience off for this mode, 453 // independent of temporal layer settings, and make sure we set 454 // |codecSpecific.VP8.resilience| = |kResilientStream| at higher level 455 // code if we want to get error resilience on. 456 configurations_[0].g_error_resilient = 1; 457 break; 458 case kResilientStream: 459 configurations_[0].g_error_resilient = 1; // TODO(holmer): Replace with 460 // VPX_ERROR_RESILIENT_DEFAULT when we 461 // drop support for libvpx 9.6.0. 462 break; 463 case kResilientFrames: 464 #ifdef INDEPENDENT_PARTITIONS 465 configurations_[0] - g_error_resilient = 466 VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS; 467 break; 468 #else 469 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; // Not supported 470 #endif 471 } 472 473 // rate control settings 474 configurations_[0].rc_dropframe_thresh = 475 inst->codecSpecific.VP8.frameDroppingOn ? 30 : 0; 476 configurations_[0].rc_end_usage = VPX_CBR; 477 configurations_[0].g_pass = VPX_RC_ONE_PASS; 478 // TODO(hellner): investigate why the following two lines produce 479 // automaticResizeOn value of 3 when running 480 // WebRtcVideoMediaChannelTest.GetStatsMultipleSendStreams inside the talk 481 // framework. 482 // configurations_[0].rc_resize_allowed = 483 // inst->codecSpecific.VP8.automaticResizeOn ? 1 : 0; 484 configurations_[0].rc_resize_allowed = 0; 485 // Handle resizing outside of libvpx when doing single-stream. 486 if (inst->codecSpecific.VP8.automaticResizeOn && number_of_streams > 1) { 487 configurations_[0].rc_resize_allowed = 1; 488 } 489 configurations_[0].rc_min_quantizer = 2; 490 if (inst->qpMax >= configurations_[0].rc_min_quantizer) { 491 qp_max_ = inst->qpMax; 492 } 493 configurations_[0].rc_max_quantizer = qp_max_; 494 configurations_[0].rc_undershoot_pct = 100; 495 configurations_[0].rc_overshoot_pct = 15; 496 configurations_[0].rc_buf_initial_sz = 500; 497 configurations_[0].rc_buf_optimal_sz = 600; 498 configurations_[0].rc_buf_sz = 1000; 499 500 // Set the maximum target size of any key-frame. 501 rc_max_intra_target_ = MaxIntraTarget(configurations_[0].rc_buf_optimal_sz); 502 503 if (feedback_mode_) { 504 // Disable periodic key frames if we get feedback from the decoder 505 // through SLI and RPSI. 506 configurations_[0].kf_mode = VPX_KF_DISABLED; 507 } else if (inst->codecSpecific.VP8.keyFrameInterval > 0) { 508 configurations_[0].kf_mode = VPX_KF_AUTO; 509 configurations_[0].kf_max_dist = inst->codecSpecific.VP8.keyFrameInterval; 510 } else { 511 configurations_[0].kf_mode = VPX_KF_DISABLED; 512 } 513 514 // Allow the user to set the complexity for the base stream. 515 switch (inst->codecSpecific.VP8.complexity) { 516 case kComplexityHigh: 517 cpu_speed_[0] = -5; 518 break; 519 case kComplexityHigher: 520 cpu_speed_[0] = -4; 521 break; 522 case kComplexityMax: 523 cpu_speed_[0] = -3; 524 break; 525 default: 526 cpu_speed_[0] = -6; 527 break; 528 } 529 cpu_speed_default_ = cpu_speed_[0]; 530 // Set encoding complexity (cpu_speed) based on resolution and/or platform. 531 cpu_speed_[0] = SetCpuSpeed(inst->width, inst->height); 532 for (int i = 1; i < number_of_streams; ++i) { 533 cpu_speed_[i] = 534 SetCpuSpeed(inst->simulcastStream[number_of_streams - 1 - i].width, 535 inst->simulcastStream[number_of_streams - 1 - i].height); 536 } 537 configurations_[0].g_w = inst->width; 538 configurations_[0].g_h = inst->height; 539 540 // Determine number of threads based on the image size and #cores. 541 // TODO(fbarchard): Consider number of Simulcast layers. 542 configurations_[0].g_threads = NumberOfThreads( 543 configurations_[0].g_w, configurations_[0].g_h, number_of_cores); 544 545 // Creating a wrapper to the image - setting image data to NULL. 546 // Actual pointer will be set in encode. Setting align to 1, as it 547 // is meaningless (no memory allocation is done here). 548 vpx_img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width, inst->height, 1, 549 NULL); 550 551 if (encoders_.size() == 1) { 552 configurations_[0].rc_target_bitrate = inst->startBitrate; 553 temporal_layers_[0]->ConfigureBitrates(inst->startBitrate, inst->maxBitrate, 554 inst->maxFramerate, 555 &configurations_[0]); 556 } else { 557 // Note the order we use is different from webm, we have lowest resolution 558 // at position 0 and they have highest resolution at position 0. 559 int stream_idx = encoders_.size() - 1; 560 std::vector<int> stream_bitrates = 561 GetStreamBitratesKbps(codec_, inst->startBitrate); 562 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 563 configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx]; 564 temporal_layers_[stream_idx]->ConfigureBitrates( 565 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, 566 &configurations_[0]); 567 --stream_idx; 568 for (size_t i = 1; i < encoders_.size(); ++i, --stream_idx) { 569 memcpy(&configurations_[i], &configurations_[0], 570 sizeof(configurations_[0])); 571 572 configurations_[i].g_w = inst->simulcastStream[stream_idx].width; 573 configurations_[i].g_h = inst->simulcastStream[stream_idx].height; 574 575 // Use 1 thread for lower resolutions. 576 configurations_[i].g_threads = 1; 577 578 // Setting alignment to 32 - as that ensures at least 16 for all 579 // planes (32 for Y, 16 for U,V). Libvpx sets the requested stride for 580 // the y plane, but only half of it to the u and v planes. 581 vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, 582 inst->simulcastStream[stream_idx].width, 583 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); 584 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); 585 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; 586 temporal_layers_[stream_idx]->ConfigureBitrates( 587 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, 588 &configurations_[i]); 589 } 590 } 591 592 rps_.Init(); 593 // Disable both high-QP limits and framedropping. Both are handled by libvpx 594 // internally. 595 const int kDisabledBadQpThreshold = 64; 596 quality_scaler_.Init(codec_.qpMax / QualityScaler::kDefaultLowQpDenominator, 597 kDisabledBadQpThreshold, false); 598 quality_scaler_.ReportFramerate(codec_.maxFramerate); 599 600 // Only apply scaling to improve for single-layer streams. The scaling metrics 601 // use frame drops as a signal and is only applicable when we drop frames. 602 quality_scaler_enabled_ = encoders_.size() == 1 && 603 configurations_[0].rc_dropframe_thresh > 0 && 604 codec_.codecSpecific.VP8.automaticResizeOn; 605 606 return InitAndSetControlSettings(); 607 } 608 609 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { 610 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) 611 // On mobile platform, always set to -12 to leverage between cpu usage 612 // and video quality. 613 return -12; 614 #else 615 // For non-ARM, increase encoding complexity (i.e., use lower speed setting) 616 // if resolution is below CIF. Otherwise, keep the default/user setting 617 // (|cpu_speed_default_|) set on InitEncode via codecSpecific.VP8.complexity. 618 if (width * height < 352 * 288) 619 return (cpu_speed_default_ < -4) ? -4 : cpu_speed_default_; 620 else 621 return cpu_speed_default_; 622 #endif 623 } 624 625 int VP8EncoderImpl::NumberOfThreads(int width, int height, int cpus) { 626 if (width * height >= 1920 * 1080 && cpus > 8) { 627 return 8; // 8 threads for 1080p on high perf machines. 628 } else if (width * height > 1280 * 960 && cpus >= 6) { 629 // 3 threads for 1080p. 630 return 3; 631 } else if (width * height > 640 * 480 && cpus >= 3) { 632 // 2 threads for qHD/HD. 633 return 2; 634 } else { 635 // 1 thread for VGA or less. 636 return 1; 637 } 638 } 639 640 int VP8EncoderImpl::InitAndSetControlSettings() { 641 vpx_codec_flags_t flags = 0; 642 flags |= VPX_CODEC_USE_OUTPUT_PARTITION; 643 644 if (encoders_.size() > 1) { 645 int error = vpx_codec_enc_init_multi(&encoders_[0], vpx_codec_vp8_cx(), 646 &configurations_[0], encoders_.size(), 647 flags, &downsampling_factors_[0]); 648 if (error) { 649 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 650 } 651 } else { 652 if (vpx_codec_enc_init(&encoders_[0], vpx_codec_vp8_cx(), 653 &configurations_[0], flags)) { 654 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 655 } 656 } 657 // Enable denoising for the highest resolution stream, and for 658 // the second highest resolution if we are doing more than 2 659 // spatial layers/streams. 660 // TODO(holmer): Investigate possibility of adding a libvpx API 661 // for getting the denoised frame from the encoder and using that 662 // when encoding lower resolution streams. Would it work with the 663 // multi-res encoding feature? 664 denoiserState denoiser_state = kDenoiserOnYOnly; 665 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) 666 denoiser_state = kDenoiserOnYOnly; 667 #else 668 denoiser_state = kDenoiserOnAdaptive; 669 #endif 670 vpx_codec_control( 671 &encoders_[0], VP8E_SET_NOISE_SENSITIVITY, 672 codec_.codecSpecific.VP8.denoisingOn ? denoiser_state : kDenoiserOff); 673 if (encoders_.size() > 2) { 674 vpx_codec_control( 675 &encoders_[1], VP8E_SET_NOISE_SENSITIVITY, 676 codec_.codecSpecific.VP8.denoisingOn ? denoiser_state : kDenoiserOff); 677 } 678 for (size_t i = 0; i < encoders_.size(); ++i) { 679 // Allow more screen content to be detected as static. 680 vpx_codec_control(&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD, 681 codec_.mode == kScreensharing ? 300 : 1); 682 vpx_codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]); 683 vpx_codec_control(&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS, 684 static_cast<vp8e_token_partitions>(token_partitions_)); 685 vpx_codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 686 rc_max_intra_target_); 687 // VP8E_SET_SCREEN_CONTENT_MODE 2 = screen content with more aggressive 688 // rate control (drop frames on large target bitrate overshoot) 689 vpx_codec_control(&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE, 690 codec_.mode == kScreensharing ? 2 : 0); 691 } 692 inited_ = true; 693 return WEBRTC_VIDEO_CODEC_OK; 694 } 695 696 uint32_t VP8EncoderImpl::MaxIntraTarget(uint32_t optimalBuffersize) { 697 // Set max to the optimal buffer level (normalized by target BR), 698 // and scaled by a scalePar. 699 // Max target size = scalePar * optimalBufferSize * targetBR[Kbps]. 700 // This values is presented in percentage of perFrameBw: 701 // perFrameBw = targetBR[Kbps] * 1000 / frameRate. 702 // The target in % is as follows: 703 704 float scalePar = 0.5; 705 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; 706 707 // Don't go below 3 times the per frame bandwidth. 708 const uint32_t minIntraTh = 300; 709 return (targetPct < minIntraTh) ? minIntraTh : targetPct; 710 } 711 712 int VP8EncoderImpl::Encode(const VideoFrame& frame, 713 const CodecSpecificInfo* codec_specific_info, 714 const std::vector<FrameType>* frame_types) { 715 if (!inited_) 716 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 717 if (frame.IsZeroSize()) 718 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 719 if (encoded_complete_callback_ == NULL) 720 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 721 722 if (quality_scaler_enabled_) 723 quality_scaler_.OnEncodeFrame(frame); 724 const VideoFrame& input_image = 725 quality_scaler_enabled_ ? quality_scaler_.GetScaledFrame(frame) : frame; 726 727 if (quality_scaler_enabled_ && (input_image.width() != codec_.width || 728 input_image.height() != codec_.height)) { 729 int ret = UpdateCodecFrameSize(input_image); 730 if (ret < 0) 731 return ret; 732 } 733 734 // Since we are extracting raw pointers from |input_image| to 735 // |raw_images_[0]|, the resolution of these frames must match. Note that 736 // |input_image| might be scaled from |frame|. In that case, the resolution of 737 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. 738 RTC_DCHECK_EQ(input_image.width(), static_cast<int>(raw_images_[0].d_w)); 739 RTC_DCHECK_EQ(input_image.height(), static_cast<int>(raw_images_[0].d_h)); 740 741 // Image in vpx_image_t format. 742 // Input image is const. VP8's raw image is not defined as const. 743 raw_images_[0].planes[VPX_PLANE_Y] = 744 const_cast<uint8_t*>(input_image.buffer(kYPlane)); 745 raw_images_[0].planes[VPX_PLANE_U] = 746 const_cast<uint8_t*>(input_image.buffer(kUPlane)); 747 raw_images_[0].planes[VPX_PLANE_V] = 748 const_cast<uint8_t*>(input_image.buffer(kVPlane)); 749 750 raw_images_[0].stride[VPX_PLANE_Y] = input_image.stride(kYPlane); 751 raw_images_[0].stride[VPX_PLANE_U] = input_image.stride(kUPlane); 752 raw_images_[0].stride[VPX_PLANE_V] = input_image.stride(kVPlane); 753 754 for (size_t i = 1; i < encoders_.size(); ++i) { 755 // Scale the image down a number of times by downsampling factor 756 libyuv::I420Scale( 757 raw_images_[i - 1].planes[VPX_PLANE_Y], 758 raw_images_[i - 1].stride[VPX_PLANE_Y], 759 raw_images_[i - 1].planes[VPX_PLANE_U], 760 raw_images_[i - 1].stride[VPX_PLANE_U], 761 raw_images_[i - 1].planes[VPX_PLANE_V], 762 raw_images_[i - 1].stride[VPX_PLANE_V], raw_images_[i - 1].d_w, 763 raw_images_[i - 1].d_h, raw_images_[i].planes[VPX_PLANE_Y], 764 raw_images_[i].stride[VPX_PLANE_Y], raw_images_[i].planes[VPX_PLANE_U], 765 raw_images_[i].stride[VPX_PLANE_U], raw_images_[i].planes[VPX_PLANE_V], 766 raw_images_[i].stride[VPX_PLANE_V], raw_images_[i].d_w, 767 raw_images_[i].d_h, libyuv::kFilterBilinear); 768 } 769 vpx_enc_frame_flags_t flags[kMaxSimulcastStreams]; 770 for (size_t i = 0; i < encoders_.size(); ++i) { 771 int ret = temporal_layers_[i]->EncodeFlags(input_image.timestamp()); 772 if (ret < 0) { 773 // Drop this frame. 774 return WEBRTC_VIDEO_CODEC_OK; 775 } 776 flags[i] = ret; 777 } 778 bool send_key_frame = false; 779 for (size_t i = 0; i < key_frame_request_.size() && i < send_stream_.size(); 780 ++i) { 781 if (key_frame_request_[i] && send_stream_[i]) { 782 send_key_frame = true; 783 break; 784 } 785 } 786 if (!send_key_frame && frame_types) { 787 for (size_t i = 0; i < frame_types->size() && i < send_stream_.size(); 788 ++i) { 789 if ((*frame_types)[i] == kVideoFrameKey && send_stream_[i]) { 790 send_key_frame = true; 791 break; 792 } 793 } 794 } 795 // The flag modification below (due to forced key frame, RPS, etc.,) for now 796 // will be the same for all encoders/spatial layers. 797 // TODO(marpan/holmer): Allow for key frame request to be set per encoder. 798 bool only_predict_from_key_frame = false; 799 if (send_key_frame) { 800 // Adapt the size of the key frame when in screenshare with 1 temporal 801 // layer. 802 if (encoders_.size() == 1 && codec_.mode == kScreensharing && 803 codec_.codecSpecific.VP8.numberOfTemporalLayers <= 1) { 804 const uint32_t forceKeyFrameIntraTh = 100; 805 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 806 forceKeyFrameIntraTh); 807 } 808 // Key frame request from caller. 809 // Will update both golden and alt-ref. 810 for (size_t i = 0; i < encoders_.size(); ++i) { 811 flags[i] = VPX_EFLAG_FORCE_KF; 812 } 813 std::fill(key_frame_request_.begin(), key_frame_request_.end(), false); 814 } else if (codec_specific_info && 815 codec_specific_info->codecType == kVideoCodecVP8) { 816 if (feedback_mode_) { 817 // Handle RPSI and SLI messages and set up the appropriate encode flags. 818 bool sendRefresh = false; 819 if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { 820 rps_.ReceivedRPSI(codec_specific_info->codecSpecific.VP8.pictureIdRPSI); 821 } 822 if (codec_specific_info->codecSpecific.VP8.hasReceivedSLI) { 823 sendRefresh = rps_.ReceivedSLI(input_image.timestamp()); 824 } 825 for (size_t i = 0; i < encoders_.size(); ++i) { 826 flags[i] = rps_.EncodeFlags(picture_id_[i], sendRefresh, 827 input_image.timestamp()); 828 } 829 } else { 830 if (codec_specific_info->codecSpecific.VP8.hasReceivedRPSI) { 831 // Is this our last key frame? If not ignore. 832 // |picture_id_| is defined per spatial stream/layer, so check that 833 // |RPSI| matches the last key frame from any of the spatial streams. 834 // If so, then all spatial streams for this encoding will predict from 835 // its long-term reference (last key frame). 836 int RPSI = codec_specific_info->codecSpecific.VP8.pictureIdRPSI; 837 for (size_t i = 0; i < encoders_.size(); ++i) { 838 if (last_key_frame_picture_id_[i] == RPSI) { 839 // Request for a long term reference frame. 840 // Note 1: overwrites any temporal settings. 841 // Note 2: VP8_EFLAG_NO_UPD_ENTROPY is not needed as that flag is 842 // set by error_resilient mode. 843 for (size_t j = 0; j < encoders_.size(); ++j) { 844 flags[j] = VP8_EFLAG_NO_UPD_ARF; 845 flags[j] |= VP8_EFLAG_NO_REF_GF; 846 flags[j] |= VP8_EFLAG_NO_REF_LAST; 847 } 848 only_predict_from_key_frame = true; 849 break; 850 } 851 } 852 } 853 } 854 } 855 // Set the encoder frame flags and temporal layer_id for each spatial stream. 856 // Note that |temporal_layers_| are defined starting from lowest resolution at 857 // position 0 to highest resolution at position |encoders_.size() - 1|, 858 // whereas |encoder_| is from highest to lowest resolution. 859 size_t stream_idx = encoders_.size() - 1; 860 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { 861 // Allow the layers adapter to temporarily modify the configuration. This 862 // change isn't stored in configurations_ so change will be discarded at 863 // the next update. 864 vpx_codec_enc_cfg_t temp_config; 865 memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t)); 866 if (temporal_layers_[stream_idx]->UpdateConfiguration(&temp_config)) { 867 if (vpx_codec_enc_config_set(&encoders_[i], &temp_config)) 868 return WEBRTC_VIDEO_CODEC_ERROR; 869 } 870 871 vpx_codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS, flags[stream_idx]); 872 vpx_codec_control(&encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID, 873 temporal_layers_[stream_idx]->CurrentLayerId()); 874 } 875 // TODO(holmer): Ideally the duration should be the timestamp diff of this 876 // frame and the next frame to be encoded, which we don't have. Instead we 877 // would like to use the duration of the previous frame. Unfortunately the 878 // rate control seems to be off with that setup. Using the average input 879 // frame rate to calculate an average duration for now. 880 assert(codec_.maxFramerate > 0); 881 uint32_t duration = 90000 / codec_.maxFramerate; 882 883 // Note we must pass 0 for |flags| field in encode call below since they are 884 // set above in |vpx_codec_control| function for each encoder/spatial layer. 885 int error = vpx_codec_encode(&encoders_[0], &raw_images_[0], timestamp_, 886 duration, 0, VPX_DL_REALTIME); 887 // Reset specific intra frame thresholds, following the key frame. 888 if (send_key_frame) { 889 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, 890 rc_max_intra_target_); 891 } 892 if (error) 893 return WEBRTC_VIDEO_CODEC_ERROR; 894 timestamp_ += duration; 895 return GetEncodedPartitions(input_image, only_predict_from_key_frame); 896 } 897 898 // TODO(pbos): Make sure this works for properly for >1 encoders. 899 int VP8EncoderImpl::UpdateCodecFrameSize(const VideoFrame& input_image) { 900 codec_.width = input_image.width(); 901 codec_.height = input_image.height(); 902 if (codec_.numberOfSimulcastStreams <= 1) { 903 // For now scaling is only used for single-layer streams. 904 codec_.simulcastStream[0].width = input_image.width(); 905 codec_.simulcastStream[0].height = input_image.height(); 906 } 907 // Update the cpu_speed setting for resolution change. 908 vpx_codec_control(&(encoders_[0]), VP8E_SET_CPUUSED, 909 SetCpuSpeed(codec_.width, codec_.height)); 910 raw_images_[0].w = codec_.width; 911 raw_images_[0].h = codec_.height; 912 raw_images_[0].d_w = codec_.width; 913 raw_images_[0].d_h = codec_.height; 914 vpx_img_set_rect(&raw_images_[0], 0, 0, codec_.width, codec_.height); 915 916 // Update encoder context for new frame size. 917 // Change of frame size will automatically trigger a key frame. 918 configurations_[0].g_w = codec_.width; 919 configurations_[0].g_h = codec_.height; 920 if (vpx_codec_enc_config_set(&encoders_[0], &configurations_[0])) { 921 return WEBRTC_VIDEO_CODEC_ERROR; 922 } 923 return WEBRTC_VIDEO_CODEC_OK; 924 } 925 926 void VP8EncoderImpl::PopulateCodecSpecific( 927 CodecSpecificInfo* codec_specific, 928 const vpx_codec_cx_pkt_t& pkt, 929 int stream_idx, 930 uint32_t timestamp, 931 bool only_predicting_from_key_frame) { 932 assert(codec_specific != NULL); 933 codec_specific->codecType = kVideoCodecVP8; 934 CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); 935 vp8Info->pictureId = picture_id_[stream_idx]; 936 if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) { 937 last_key_frame_picture_id_[stream_idx] = picture_id_[stream_idx]; 938 } 939 vp8Info->simulcastIdx = stream_idx; 940 vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this 941 vp8Info->nonReference = 942 (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) ? true : false; 943 bool base_layer_sync_point = (pkt.data.frame.flags & VPX_FRAME_IS_KEY) || 944 only_predicting_from_key_frame; 945 temporal_layers_[stream_idx]->PopulateCodecSpecific(base_layer_sync_point, 946 vp8Info, timestamp); 947 // Prepare next. 948 picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; 949 } 950 951 int VP8EncoderImpl::GetEncodedPartitions(const VideoFrame& input_image, 952 bool only_predicting_from_key_frame) { 953 int bw_resolutions_disabled = 954 (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; 955 956 int stream_idx = static_cast<int>(encoders_.size()) - 1; 957 int result = WEBRTC_VIDEO_CODEC_OK; 958 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); 959 ++encoder_idx, --stream_idx) { 960 vpx_codec_iter_t iter = NULL; 961 int part_idx = 0; 962 encoded_images_[encoder_idx]._length = 0; 963 encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; 964 RTPFragmentationHeader frag_info; 965 // token_partitions_ is number of bits used. 966 frag_info.VerifyAndAllocateFragmentationHeader((1 << token_partitions_) + 967 1); 968 CodecSpecificInfo codec_specific; 969 const vpx_codec_cx_pkt_t* pkt = NULL; 970 while ((pkt = vpx_codec_get_cx_data(&encoders_[encoder_idx], &iter)) != 971 NULL) { 972 switch (pkt->kind) { 973 case VPX_CODEC_CX_FRAME_PKT: { 974 uint32_t length = encoded_images_[encoder_idx]._length; 975 memcpy(&encoded_images_[encoder_idx]._buffer[length], 976 pkt->data.frame.buf, pkt->data.frame.sz); 977 frag_info.fragmentationOffset[part_idx] = length; 978 frag_info.fragmentationLength[part_idx] = pkt->data.frame.sz; 979 frag_info.fragmentationPlType[part_idx] = 0; // not known here 980 frag_info.fragmentationTimeDiff[part_idx] = 0; 981 encoded_images_[encoder_idx]._length += pkt->data.frame.sz; 982 assert(length <= encoded_images_[encoder_idx]._size); 983 ++part_idx; 984 break; 985 } 986 default: 987 break; 988 } 989 // End of frame 990 if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) { 991 // check if encoded frame is a key frame 992 if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { 993 encoded_images_[encoder_idx]._frameType = kVideoFrameKey; 994 rps_.EncodedKeyFrame(picture_id_[stream_idx]); 995 } 996 PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, 997 input_image.timestamp(), 998 only_predicting_from_key_frame); 999 break; 1000 } 1001 } 1002 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); 1003 encoded_images_[encoder_idx].capture_time_ms_ = 1004 input_image.render_time_ms(); 1005 1006 int qp = -1; 1007 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER_64, &qp); 1008 temporal_layers_[stream_idx]->FrameEncoded( 1009 encoded_images_[encoder_idx]._length, 1010 encoded_images_[encoder_idx]._timeStamp, qp); 1011 if (send_stream_[stream_idx]) { 1012 if (encoded_images_[encoder_idx]._length > 0) { 1013 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, 1014 encoded_images_[encoder_idx]._length); 1015 encoded_images_[encoder_idx]._encodedHeight = 1016 codec_.simulcastStream[stream_idx].height; 1017 encoded_images_[encoder_idx]._encodedWidth = 1018 codec_.simulcastStream[stream_idx].width; 1019 encoded_images_[encoder_idx] 1020 .adapt_reason_.quality_resolution_downscales = 1021 quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1; 1022 // Report once per frame (lowest stream always sent). 1023 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = 1024 (stream_idx == 0) ? bw_resolutions_disabled : -1; 1025 encoded_complete_callback_->Encoded(encoded_images_[encoder_idx], 1026 &codec_specific, &frag_info); 1027 } else if (codec_.mode == kScreensharing) { 1028 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; 1029 } 1030 } 1031 } 1032 if (encoders_.size() == 1 && send_stream_[0]) { 1033 if (encoded_images_[0]._length > 0) { 1034 int qp; 1035 vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER_64, &qp); 1036 quality_scaler_.ReportQP(qp); 1037 } else { 1038 quality_scaler_.ReportDroppedFrame(); 1039 } 1040 } 1041 return result; 1042 } 1043 1044 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { 1045 rps_.SetRtt(rtt); 1046 return WEBRTC_VIDEO_CODEC_OK; 1047 } 1048 1049 int VP8EncoderImpl::RegisterEncodeCompleteCallback( 1050 EncodedImageCallback* callback) { 1051 encoded_complete_callback_ = callback; 1052 return WEBRTC_VIDEO_CODEC_OK; 1053 } 1054 1055 VP8DecoderImpl::VP8DecoderImpl() 1056 : decode_complete_callback_(NULL), 1057 inited_(false), 1058 feedback_mode_(false), 1059 decoder_(NULL), 1060 last_keyframe_(), 1061 image_format_(VPX_IMG_FMT_NONE), 1062 ref_frame_(NULL), 1063 propagation_cnt_(-1), 1064 last_frame_width_(0), 1065 last_frame_height_(0), 1066 key_frame_required_(true) {} 1067 1068 VP8DecoderImpl::~VP8DecoderImpl() { 1069 inited_ = true; // in order to do the actual release 1070 Release(); 1071 } 1072 1073 int VP8DecoderImpl::Reset() { 1074 if (!inited_) { 1075 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 1076 } 1077 InitDecode(&codec_, 1); 1078 propagation_cnt_ = -1; 1079 return WEBRTC_VIDEO_CODEC_OK; 1080 } 1081 1082 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { 1083 int ret_val = Release(); 1084 if (ret_val < 0) { 1085 return ret_val; 1086 } 1087 if (decoder_ == NULL) { 1088 decoder_ = new vpx_codec_ctx_t; 1089 } 1090 if (inst && inst->codecType == kVideoCodecVP8) { 1091 feedback_mode_ = inst->codecSpecific.VP8.feedbackModeOn; 1092 } 1093 vpx_codec_dec_cfg_t cfg; 1094 // Setting number of threads to a constant value (1) 1095 cfg.threads = 1; 1096 cfg.h = cfg.w = 0; // set after decode 1097 1098 vpx_codec_flags_t flags = 0; 1099 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) 1100 flags = VPX_CODEC_USE_POSTPROC; 1101 #ifdef INDEPENDENT_PARTITIONS 1102 flags |= VPX_CODEC_USE_INPUT_PARTITION; 1103 #endif 1104 #endif 1105 1106 if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) { 1107 return WEBRTC_VIDEO_CODEC_MEMORY; 1108 } 1109 1110 // Save VideoCodec instance for later; mainly for duplicating the decoder. 1111 if (&codec_ != inst) 1112 codec_ = *inst; 1113 propagation_cnt_ = -1; 1114 1115 inited_ = true; 1116 1117 // Always start with a complete key frame. 1118 key_frame_required_ = true; 1119 return WEBRTC_VIDEO_CODEC_OK; 1120 } 1121 1122 int VP8DecoderImpl::Decode(const EncodedImage& input_image, 1123 bool missing_frames, 1124 const RTPFragmentationHeader* fragmentation, 1125 const CodecSpecificInfo* codec_specific_info, 1126 int64_t /*render_time_ms*/) { 1127 if (!inited_) { 1128 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 1129 } 1130 if (decode_complete_callback_ == NULL) { 1131 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 1132 } 1133 if (input_image._buffer == NULL && input_image._length > 0) { 1134 // Reset to avoid requesting key frames too often. 1135 if (propagation_cnt_ > 0) 1136 propagation_cnt_ = 0; 1137 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 1138 } 1139 1140 #ifdef INDEPENDENT_PARTITIONS 1141 if (fragmentation == NULL) { 1142 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 1143 } 1144 #endif 1145 1146 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) 1147 vp8_postproc_cfg_t ppcfg; 1148 // MFQE enabled to reduce key frame popping. 1149 ppcfg.post_proc_flag = VP8_MFQE | VP8_DEBLOCK; 1150 // For VGA resolutions and lower, enable the demacroblocker postproc. 1151 if (last_frame_width_ * last_frame_height_ <= 640 * 360) { 1152 ppcfg.post_proc_flag |= VP8_DEMACROBLOCK; 1153 } 1154 // Strength of deblocking filter. Valid range:[0,16] 1155 ppcfg.deblocking_level = 3; 1156 vpx_codec_control(decoder_, VP8_SET_POSTPROC, &ppcfg); 1157 #endif 1158 1159 // Always start with a complete key frame. 1160 if (key_frame_required_) { 1161 if (input_image._frameType != kVideoFrameKey) 1162 return WEBRTC_VIDEO_CODEC_ERROR; 1163 // We have a key frame - is it complete? 1164 if (input_image._completeFrame) { 1165 key_frame_required_ = false; 1166 } else { 1167 return WEBRTC_VIDEO_CODEC_ERROR; 1168 } 1169 } 1170 // Restrict error propagation using key frame requests. Disabled when 1171 // the feedback mode is enabled (RPS). 1172 // Reset on a key frame refresh. 1173 if (!feedback_mode_) { 1174 if (input_image._frameType == kVideoFrameKey && 1175 input_image._completeFrame) { 1176 propagation_cnt_ = -1; 1177 // Start count on first loss. 1178 } else if ((!input_image._completeFrame || missing_frames) && 1179 propagation_cnt_ == -1) { 1180 propagation_cnt_ = 0; 1181 } 1182 if (propagation_cnt_ >= 0) { 1183 propagation_cnt_++; 1184 } 1185 } 1186 1187 vpx_codec_iter_t iter = NULL; 1188 vpx_image_t* img; 1189 int ret; 1190 1191 // Check for missing frames. 1192 if (missing_frames) { 1193 // Call decoder with zero data length to signal missing frames. 1194 if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) { 1195 // Reset to avoid requesting key frames too often. 1196 if (propagation_cnt_ > 0) 1197 propagation_cnt_ = 0; 1198 return WEBRTC_VIDEO_CODEC_ERROR; 1199 } 1200 img = vpx_codec_get_frame(decoder_, &iter); 1201 iter = NULL; 1202 } 1203 1204 #ifdef INDEPENDENT_PARTITIONS 1205 if (DecodePartitions(inputImage, fragmentation)) { 1206 // Reset to avoid requesting key frames too often. 1207 if (propagation_cnt_ > 0) { 1208 propagation_cnt_ = 0; 1209 } 1210 return WEBRTC_VIDEO_CODEC_ERROR; 1211 } 1212 #else 1213 uint8_t* buffer = input_image._buffer; 1214 if (input_image._length == 0) { 1215 buffer = NULL; // Triggers full frame concealment. 1216 } 1217 if (vpx_codec_decode(decoder_, buffer, input_image._length, 0, 1218 VPX_DL_REALTIME)) { 1219 // Reset to avoid requesting key frames too often. 1220 if (propagation_cnt_ > 0) { 1221 propagation_cnt_ = 0; 1222 } 1223 return WEBRTC_VIDEO_CODEC_ERROR; 1224 } 1225 #endif 1226 1227 // Store encoded frame if key frame. (Used in Copy method.) 1228 if (input_image._frameType == kVideoFrameKey && input_image._buffer != NULL) { 1229 const uint32_t bytes_to_copy = input_image._length; 1230 if (last_keyframe_._size < bytes_to_copy) { 1231 delete[] last_keyframe_._buffer; 1232 last_keyframe_._buffer = NULL; 1233 last_keyframe_._size = 0; 1234 } 1235 uint8_t* temp_buffer = last_keyframe_._buffer; // Save buffer ptr. 1236 uint32_t temp_size = last_keyframe_._size; // Save size. 1237 last_keyframe_ = input_image; // Shallow copy. 1238 last_keyframe_._buffer = temp_buffer; // Restore buffer ptr. 1239 last_keyframe_._size = temp_size; // Restore buffer size. 1240 if (!last_keyframe_._buffer) { 1241 // Allocate memory. 1242 last_keyframe_._size = bytes_to_copy; 1243 last_keyframe_._buffer = new uint8_t[last_keyframe_._size]; 1244 } 1245 // Copy encoded frame. 1246 memcpy(last_keyframe_._buffer, input_image._buffer, bytes_to_copy); 1247 last_keyframe_._length = bytes_to_copy; 1248 } 1249 1250 img = vpx_codec_get_frame(decoder_, &iter); 1251 ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_); 1252 if (ret != 0) { 1253 // Reset to avoid requesting key frames too often. 1254 if (ret < 0 && propagation_cnt_ > 0) 1255 propagation_cnt_ = 0; 1256 return ret; 1257 } 1258 if (feedback_mode_) { 1259 // Whenever we receive an incomplete key frame all reference buffers will 1260 // be corrupt. If that happens we must request new key frames until we 1261 // decode a complete key frame. 1262 if (input_image._frameType == kVideoFrameKey && !input_image._completeFrame) 1263 return WEBRTC_VIDEO_CODEC_ERROR; 1264 // Check for reference updates and last reference buffer corruption and 1265 // signal successful reference propagation or frame corruption to the 1266 // encoder. 1267 int reference_updates = 0; 1268 if (vpx_codec_control(decoder_, VP8D_GET_LAST_REF_UPDATES, 1269 &reference_updates)) { 1270 // Reset to avoid requesting key frames too often. 1271 if (propagation_cnt_ > 0) { 1272 propagation_cnt_ = 0; 1273 } 1274 return WEBRTC_VIDEO_CODEC_ERROR; 1275 } 1276 int corrupted = 0; 1277 if (vpx_codec_control(decoder_, VP8D_GET_FRAME_CORRUPTED, &corrupted)) { 1278 // Reset to avoid requesting key frames too often. 1279 if (propagation_cnt_ > 0) 1280 propagation_cnt_ = 0; 1281 return WEBRTC_VIDEO_CODEC_ERROR; 1282 } 1283 int16_t picture_id = -1; 1284 if (codec_specific_info) { 1285 picture_id = codec_specific_info->codecSpecific.VP8.pictureId; 1286 } 1287 if (picture_id > -1) { 1288 if (((reference_updates & VP8_GOLD_FRAME) || 1289 (reference_updates & VP8_ALTR_FRAME)) && 1290 !corrupted) { 1291 decode_complete_callback_->ReceivedDecodedReferenceFrame(picture_id); 1292 } 1293 decode_complete_callback_->ReceivedDecodedFrame(picture_id); 1294 } 1295 if (corrupted) { 1296 // we can decode but with artifacts 1297 return WEBRTC_VIDEO_CODEC_REQUEST_SLI; 1298 } 1299 } 1300 // Check Vs. threshold 1301 if (propagation_cnt_ > kVp8ErrorPropagationTh) { 1302 // Reset to avoid requesting key frames too often. 1303 propagation_cnt_ = 0; 1304 return WEBRTC_VIDEO_CODEC_ERROR; 1305 } 1306 return WEBRTC_VIDEO_CODEC_OK; 1307 } 1308 1309 int VP8DecoderImpl::DecodePartitions( 1310 const EncodedImage& input_image, 1311 const RTPFragmentationHeader* fragmentation) { 1312 for (int i = 0; i < fragmentation->fragmentationVectorSize; ++i) { 1313 const uint8_t* partition = 1314 input_image._buffer + fragmentation->fragmentationOffset[i]; 1315 const uint32_t partition_length = fragmentation->fragmentationLength[i]; 1316 if (vpx_codec_decode(decoder_, partition, partition_length, 0, 1317 VPX_DL_REALTIME)) { 1318 return WEBRTC_VIDEO_CODEC_ERROR; 1319 } 1320 } 1321 // Signal end of frame data. If there was no frame data this will trigger 1322 // a full frame concealment. 1323 if (vpx_codec_decode(decoder_, NULL, 0, 0, VPX_DL_REALTIME)) 1324 return WEBRTC_VIDEO_CODEC_ERROR; 1325 return WEBRTC_VIDEO_CODEC_OK; 1326 } 1327 1328 int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img, 1329 uint32_t timestamp, 1330 int64_t ntp_time_ms) { 1331 if (img == NULL) { 1332 // Decoder OK and NULL image => No show frame 1333 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; 1334 } 1335 last_frame_width_ = img->d_w; 1336 last_frame_height_ = img->d_h; 1337 // Allocate memory for decoded image. 1338 VideoFrame decoded_image(buffer_pool_.CreateBuffer(img->d_w, img->d_h), 1339 timestamp, 0, kVideoRotation_0); 1340 libyuv::I420Copy(img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y], 1341 img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U], 1342 img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], 1343 decoded_image.buffer(kYPlane), decoded_image.stride(kYPlane), 1344 decoded_image.buffer(kUPlane), decoded_image.stride(kUPlane), 1345 decoded_image.buffer(kVPlane), decoded_image.stride(kVPlane), 1346 img->d_w, img->d_h); 1347 decoded_image.set_ntp_time_ms(ntp_time_ms); 1348 int ret = decode_complete_callback_->Decoded(decoded_image); 1349 if (ret != 0) 1350 return ret; 1351 1352 // Remember image format for later 1353 image_format_ = img->fmt; 1354 return WEBRTC_VIDEO_CODEC_OK; 1355 } 1356 1357 int VP8DecoderImpl::RegisterDecodeCompleteCallback( 1358 DecodedImageCallback* callback) { 1359 decode_complete_callback_ = callback; 1360 return WEBRTC_VIDEO_CODEC_OK; 1361 } 1362 1363 int VP8DecoderImpl::Release() { 1364 if (last_keyframe_._buffer != NULL) { 1365 delete[] last_keyframe_._buffer; 1366 last_keyframe_._buffer = NULL; 1367 } 1368 if (decoder_ != NULL) { 1369 if (vpx_codec_destroy(decoder_)) { 1370 return WEBRTC_VIDEO_CODEC_MEMORY; 1371 } 1372 delete decoder_; 1373 decoder_ = NULL; 1374 } 1375 if (ref_frame_ != NULL) { 1376 vpx_img_free(&ref_frame_->img); 1377 delete ref_frame_; 1378 ref_frame_ = NULL; 1379 } 1380 buffer_pool_.Release(); 1381 inited_ = false; 1382 return WEBRTC_VIDEO_CODEC_OK; 1383 } 1384 1385 const char* VP8DecoderImpl::ImplementationName() const { 1386 return "libvpx"; 1387 } 1388 1389 int VP8DecoderImpl::CopyReference(VP8DecoderImpl* copy) { 1390 // The type of frame to copy should be set in ref_frame_->frame_type 1391 // before the call to this function. 1392 if (vpx_codec_control(decoder_, VP8_COPY_REFERENCE, ref_frame_) != 1393 VPX_CODEC_OK) { 1394 return -1; 1395 } 1396 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != 1397 VPX_CODEC_OK) { 1398 return -1; 1399 } 1400 return 0; 1401 } 1402 1403 } // namespace webrtc 1404