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