| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 * | 9 * |
| 10 */ | 10 */ |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 // Allow zero to represent an unspecified maxBitRate | 235 // Allow zero to represent an unspecified maxBitRate |
| 236 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { | 236 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { |
| 237 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 237 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 238 } | 238 } |
| 239 if (inst->width < 1 || inst->height < 1) { | 239 if (inst->width < 1 || inst->height < 1) { |
| 240 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 240 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 241 } | 241 } |
| 242 if (number_of_cores < 1) { | 242 if (number_of_cores < 1) { |
| 243 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 243 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 244 } | 244 } |
| 245 if (inst->codecSpecific.VP9.numberOfTemporalLayers > 3) { | 245 if (inst->VP9().numberOfTemporalLayers > 3) { |
| 246 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 246 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 247 } | 247 } |
| 248 // libvpx currently supports only one or two spatial layers. | 248 // libvpx currently supports only one or two spatial layers. |
| 249 if (inst->codecSpecific.VP9.numberOfSpatialLayers > 2) { | 249 if (inst->VP9().numberOfSpatialLayers > 2) { |
| 250 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 250 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 251 } | 251 } |
| 252 | 252 |
| 253 int ret_val = Release(); | 253 int ret_val = Release(); |
| 254 if (ret_val < 0) { | 254 if (ret_val < 0) { |
| 255 return ret_val; | 255 return ret_val; |
| 256 } | 256 } |
| 257 if (encoder_ == NULL) { | 257 if (encoder_ == NULL) { |
| 258 encoder_ = new vpx_codec_ctx_t; | 258 encoder_ = new vpx_codec_ctx_t; |
| 259 } | 259 } |
| 260 if (config_ == NULL) { | 260 if (config_ == NULL) { |
| 261 config_ = new vpx_codec_enc_cfg_t; | 261 config_ = new vpx_codec_enc_cfg_t; |
| 262 } | 262 } |
| 263 timestamp_ = 0; | 263 timestamp_ = 0; |
| 264 if (&codec_ != inst) { | 264 if (&codec_ != inst) { |
| 265 codec_ = *inst; | 265 codec_ = *inst; |
| 266 } | 266 } |
| 267 | 267 |
| 268 num_spatial_layers_ = inst->codecSpecific.VP9.numberOfSpatialLayers; | 268 num_spatial_layers_ = inst->VP9().numberOfSpatialLayers; |
| 269 num_temporal_layers_ = inst->codecSpecific.VP9.numberOfTemporalLayers; | 269 num_temporal_layers_ = inst->VP9().numberOfTemporalLayers; |
| 270 if (num_temporal_layers_ == 0) | 270 if (num_temporal_layers_ == 0) |
| 271 num_temporal_layers_ = 1; | 271 num_temporal_layers_ = 1; |
| 272 | 272 |
| 273 // Random start 16 bits is enough. | 273 // Random start 16 bits is enough. |
| 274 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT | 274 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT |
| 275 // Allocate memory for encoded image | 275 // Allocate memory for encoded image |
| 276 if (encoded_image_._buffer != NULL) { | 276 if (encoded_image_._buffer != NULL) { |
| 277 delete[] encoded_image_._buffer; | 277 delete[] encoded_image_._buffer; |
| 278 } | 278 } |
| 279 encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); | 279 encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 291 config_->g_w = codec_.width; | 291 config_->g_w = codec_.width; |
| 292 config_->g_h = codec_.height; | 292 config_->g_h = codec_.height; |
| 293 config_->rc_target_bitrate = inst->startBitrate; // in kbit/s | 293 config_->rc_target_bitrate = inst->startBitrate; // in kbit/s |
| 294 config_->g_error_resilient = 1; | 294 config_->g_error_resilient = 1; |
| 295 // Setting the time base of the codec. | 295 // Setting the time base of the codec. |
| 296 config_->g_timebase.num = 1; | 296 config_->g_timebase.num = 1; |
| 297 config_->g_timebase.den = 90000; | 297 config_->g_timebase.den = 90000; |
| 298 config_->g_lag_in_frames = 0; // 0- no frame lagging | 298 config_->g_lag_in_frames = 0; // 0- no frame lagging |
| 299 config_->g_threads = 1; | 299 config_->g_threads = 1; |
| 300 // Rate control settings. | 300 // Rate control settings. |
| 301 config_->rc_dropframe_thresh = | 301 config_->rc_dropframe_thresh = inst->VP9().frameDroppingOn ? 30 : 0; |
| 302 inst->codecSpecific.VP9.frameDroppingOn ? 30 : 0; | |
| 303 config_->rc_end_usage = VPX_CBR; | 302 config_->rc_end_usage = VPX_CBR; |
| 304 config_->g_pass = VPX_RC_ONE_PASS; | 303 config_->g_pass = VPX_RC_ONE_PASS; |
| 305 config_->rc_min_quantizer = 2; | 304 config_->rc_min_quantizer = 2; |
| 306 config_->rc_max_quantizer = 52; | 305 config_->rc_max_quantizer = 52; |
| 307 config_->rc_undershoot_pct = 50; | 306 config_->rc_undershoot_pct = 50; |
| 308 config_->rc_overshoot_pct = 50; | 307 config_->rc_overshoot_pct = 50; |
| 309 config_->rc_buf_initial_sz = 500; | 308 config_->rc_buf_initial_sz = 500; |
| 310 config_->rc_buf_optimal_sz = 600; | 309 config_->rc_buf_optimal_sz = 600; |
| 311 config_->rc_buf_sz = 1000; | 310 config_->rc_buf_sz = 1000; |
| 312 // Set the maximum target size of any key-frame. | 311 // Set the maximum target size of any key-frame. |
| 313 rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz); | 312 rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz); |
| 314 if (inst->codecSpecific.VP9.keyFrameInterval > 0) { | 313 if (inst->VP9().keyFrameInterval > 0) { |
| 315 config_->kf_mode = VPX_KF_AUTO; | 314 config_->kf_mode = VPX_KF_AUTO; |
| 316 config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval; | 315 config_->kf_max_dist = inst->VP9().keyFrameInterval; |
| 317 // Needs to be set (in svc mode) to get correct periodic key frame interval | 316 // Needs to be set (in svc mode) to get correct periodic key frame interval |
| 318 // (will have no effect in non-svc). | 317 // (will have no effect in non-svc). |
| 319 config_->kf_min_dist = config_->kf_max_dist; | 318 config_->kf_min_dist = config_->kf_max_dist; |
| 320 } else { | 319 } else { |
| 321 config_->kf_mode = VPX_KF_DISABLED; | 320 config_->kf_mode = VPX_KF_DISABLED; |
| 322 } | 321 } |
| 323 config_->rc_resize_allowed = | 322 config_->rc_resize_allowed = inst->VP9().automaticResizeOn ? 1 : 0; |
| 324 inst->codecSpecific.VP9.automaticResizeOn ? 1 : 0; | |
| 325 // Determine number of threads based on the image size and #cores. | 323 // Determine number of threads based on the image size and #cores. |
| 326 config_->g_threads = | 324 config_->g_threads = |
| 327 NumberOfThreads(config_->g_w, config_->g_h, number_of_cores); | 325 NumberOfThreads(config_->g_w, config_->g_h, number_of_cores); |
| 328 | 326 |
| 329 cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); | 327 cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); |
| 330 | 328 |
| 331 // TODO(asapersson): Check configuration of temporal switch up and increase | 329 // TODO(asapersson): Check configuration of temporal switch up and increase |
| 332 // pattern length. | 330 // pattern length. |
| 333 is_flexible_mode_ = inst->codecSpecific.VP9.flexibleMode; | 331 is_flexible_mode_ = inst->VP9().flexibleMode; |
| 334 if (is_flexible_mode_) { | 332 if (is_flexible_mode_) { |
| 335 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; | 333 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; |
| 336 config_->ts_number_layers = num_temporal_layers_; | 334 config_->ts_number_layers = num_temporal_layers_; |
| 337 if (codec_.mode == kScreensharing) | 335 if (codec_.mode == kScreensharing) |
| 338 spatial_layer_->ConfigureBitrate(inst->startBitrate, 0); | 336 spatial_layer_->ConfigureBitrate(inst->startBitrate, 0); |
| 339 } else if (num_temporal_layers_ == 1) { | 337 } else if (num_temporal_layers_ == 1) { |
| 340 gof_.SetGofInfoVP9(kTemporalStructureMode1); | 338 gof_.SetGofInfoVP9(kTemporalStructureMode1); |
| 341 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING; | 339 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING; |
| 342 config_->ts_number_layers = 1; | 340 config_->ts_number_layers = 1; |
| 343 config_->ts_rate_decimator[0] = 1; | 341 config_->ts_rate_decimator[0] = 1; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 415 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 418 } | 416 } |
| 419 | 417 |
| 420 if (vpx_codec_enc_init(encoder_, vpx_codec_vp9_cx(), config_, 0)) { | 418 if (vpx_codec_enc_init(encoder_, vpx_codec_vp9_cx(), config_, 0)) { |
| 421 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 419 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 422 } | 420 } |
| 423 vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); | 421 vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_); |
| 424 vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT, | 422 vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT, |
| 425 rc_max_intra_target_); | 423 rc_max_intra_target_); |
| 426 vpx_codec_control(encoder_, VP9E_SET_AQ_MODE, | 424 vpx_codec_control(encoder_, VP9E_SET_AQ_MODE, |
| 427 inst->codecSpecific.VP9.adaptiveQpMode ? 3 : 0); | 425 inst->VP9().adaptiveQpMode ? 3 : 0); |
| 428 | 426 |
| 429 vpx_codec_control( | 427 vpx_codec_control( |
| 430 encoder_, VP9E_SET_SVC, | 428 encoder_, VP9E_SET_SVC, |
| 431 (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) ? 1 : 0); | 429 (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) ? 1 : 0); |
| 432 if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { | 430 if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { |
| 433 vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, | 431 vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, |
| 434 &svc_internal_.svc_params); | 432 &svc_internal_.svc_params); |
| 435 } | 433 } |
| 436 // Register callback for getting each spatial layer. | 434 // Register callback for getting each spatial layer. |
| 437 vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = { | 435 vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = { |
| 438 VP9EncoderImpl::EncoderOutputCodedPacketCallback, | 436 VP9EncoderImpl::EncoderOutputCodedPacketCallback, |
| 439 reinterpret_cast<void*>(this)}; | 437 reinterpret_cast<void*>(this)}; |
| 440 vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK, | 438 vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK, |
| 441 reinterpret_cast<void*>(&cbp)); | 439 reinterpret_cast<void*>(&cbp)); |
| 442 | 440 |
| 443 // Control function to set the number of column tiles in encoding a frame, in | 441 // Control function to set the number of column tiles in encoding a frame, in |
| 444 // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. | 442 // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. |
| 445 // The number tile columns will be capped by the encoder based on image size | 443 // The number tile columns will be capped by the encoder based on image size |
| 446 // (minimum width of tile column is 256 pixels, maximum is 4096). | 444 // (minimum width of tile column is 256 pixels, maximum is 4096). |
| 447 vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); | 445 vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); |
| 448 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) && \ | 446 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) && \ |
| 449 !defined(ANDROID) | 447 !defined(ANDROID) |
| 450 // Note denoiser is still off by default until further testing/optimization, | 448 // Note denoiser is still off by default until further testing/optimization, |
| 451 // i.e., codecSpecific.VP9.denoisingOn == 0. | 449 // i.e., VP9().denoisingOn == 0. |
| 452 vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, | 450 vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, |
| 453 inst->codecSpecific.VP9.denoisingOn ? 1 : 0); | 451 inst->VP9().denoisingOn ? 1 : 0); |
| 454 #endif | 452 #endif |
| 455 if (codec_.mode == kScreensharing) { | 453 if (codec_.mode == kScreensharing) { |
| 456 // Adjust internal parameters to screen content. | 454 // Adjust internal parameters to screen content. |
| 457 vpx_codec_control(encoder_, VP9E_SET_TUNE_CONTENT, 1); | 455 vpx_codec_control(encoder_, VP9E_SET_TUNE_CONTENT, 1); |
| 458 } | 456 } |
| 459 // Enable encoder skip of static/low content blocks. | 457 // Enable encoder skip of static/low content blocks. |
| 460 vpx_codec_control(encoder_, VP8E_SET_STATIC_THRESHOLD, 1); | 458 vpx_codec_control(encoder_, VP8E_SET_STATIC_THRESHOLD, 1); |
| 461 inited_ = true; | 459 inited_ = true; |
| 462 return WEBRTC_VIDEO_CODEC_OK; | 460 return WEBRTC_VIDEO_CODEC_OK; |
| 463 } | 461 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, | 556 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, |
| 559 const vpx_codec_cx_pkt& pkt, | 557 const vpx_codec_cx_pkt& pkt, |
| 560 uint32_t timestamp) { | 558 uint32_t timestamp) { |
| 561 assert(codec_specific != NULL); | 559 assert(codec_specific != NULL); |
| 562 codec_specific->codecType = kVideoCodecVP9; | 560 codec_specific->codecType = kVideoCodecVP9; |
| 563 codec_specific->codec_name = ImplementationName(); | 561 codec_specific->codec_name = ImplementationName(); |
| 564 CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9); | 562 CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9); |
| 565 // TODO(asapersson): Set correct value. | 563 // TODO(asapersson): Set correct value. |
| 566 vp9_info->inter_pic_predicted = | 564 vp9_info->inter_pic_predicted = |
| 567 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true; | 565 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true; |
| 568 vp9_info->flexible_mode = codec_.codecSpecific.VP9.flexibleMode; | 566 vp9_info->flexible_mode = codec_.VP9()->flexibleMode; |
| 569 vp9_info->ss_data_available = ((pkt.data.frame.flags & VPX_FRAME_IS_KEY) && | 567 vp9_info->ss_data_available = |
| 570 !codec_.codecSpecific.VP9.flexibleMode) | 568 ((pkt.data.frame.flags & VPX_FRAME_IS_KEY) && !codec_.VP9()->flexibleMode) |
| 571 ? true | 569 ? true |
| 572 : false; | 570 : false; |
| 573 | 571 |
| 574 vpx_svc_layer_id_t layer_id = {0}; | 572 vpx_svc_layer_id_t layer_id = {0}; |
| 575 vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id); | 573 vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id); |
| 576 | 574 |
| 577 assert(num_temporal_layers_ > 0); | 575 assert(num_temporal_layers_ > 0); |
| 578 assert(num_spatial_layers_ > 0); | 576 assert(num_spatial_layers_ > 0); |
| 579 if (num_temporal_layers_ == 1) { | 577 if (num_temporal_layers_ == 1) { |
| 580 assert(layer_id.temporal_layer_id == 0); | 578 assert(layer_id.temporal_layer_id == 0); |
| 581 vp9_info->temporal_idx = kNoTemporalIdx; | 579 vp9_info->temporal_idx = kNoTemporalIdx; |
| 582 } else { | 580 } else { |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 frame_buffer_pool_.ClearPool(); | 994 frame_buffer_pool_.ClearPool(); |
| 997 inited_ = false; | 995 inited_ = false; |
| 998 return WEBRTC_VIDEO_CODEC_OK; | 996 return WEBRTC_VIDEO_CODEC_OK; |
| 999 } | 997 } |
| 1000 | 998 |
| 1001 const char* VP9DecoderImpl::ImplementationName() const { | 999 const char* VP9DecoderImpl::ImplementationName() const { |
| 1002 return "libvpx"; | 1000 return "libvpx"; |
| 1003 } | 1001 } |
| 1004 | 1002 |
| 1005 } // namespace webrtc | 1003 } // namespace webrtc |
| OLD | NEW |