| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 else | 43 else |
| 44 return 7; | 44 return 7; |
| 45 } | 45 } |
| 46 | 46 |
| 47 VP9Encoder* VP9Encoder::Create() { | 47 VP9Encoder* VP9Encoder::Create() { |
| 48 return new VP9EncoderImpl(); | 48 return new VP9EncoderImpl(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 void VP9EncoderImpl::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt, | 51 void VP9EncoderImpl::EncoderOutputCodedPacketCallback(vpx_codec_cx_pkt* pkt, |
| 52 void* user_data) { | 52 void* user_data) { |
| 53 VP9EncoderImpl* enc = (VP9EncoderImpl*)(user_data); | 53 VP9EncoderImpl* enc = static_cast<VP9EncoderImpl*>(user_data); |
| 54 enc->GetEncodedLayerFrame(pkt); | 54 enc->GetEncodedLayerFrame(pkt); |
| 55 } | 55 } |
| 56 | 56 |
| 57 VP9EncoderImpl::VP9EncoderImpl() | 57 VP9EncoderImpl::VP9EncoderImpl() |
| 58 : encoded_image_(), | 58 : encoded_image_(), |
| 59 encoded_complete_callback_(NULL), | 59 encoded_complete_callback_(NULL), |
| 60 inited_(false), | 60 inited_(false), |
| 61 timestamp_(0), | 61 timestamp_(0), |
| 62 picture_id_(0), | 62 picture_id_(0), |
| 63 cpu_speed_(3), | 63 cpu_speed_(3), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 77 uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); | 77 uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp()); |
| 78 srand(seed); | 78 srand(seed); |
| 79 } | 79 } |
| 80 | 80 |
| 81 VP9EncoderImpl::~VP9EncoderImpl() { | 81 VP9EncoderImpl::~VP9EncoderImpl() { |
| 82 Release(); | 82 Release(); |
| 83 } | 83 } |
| 84 | 84 |
| 85 int VP9EncoderImpl::Release() { | 85 int VP9EncoderImpl::Release() { |
| 86 if (encoded_image_._buffer != NULL) { | 86 if (encoded_image_._buffer != NULL) { |
| 87 delete [] encoded_image_._buffer; | 87 delete[] encoded_image_._buffer; |
| 88 encoded_image_._buffer = NULL; | 88 encoded_image_._buffer = NULL; |
| 89 } | 89 } |
| 90 if (encoder_ != NULL) { | 90 if (encoder_ != NULL) { |
| 91 if (vpx_codec_destroy(encoder_)) { | 91 if (vpx_codec_destroy(encoder_)) { |
| 92 return WEBRTC_VIDEO_CODEC_MEMORY; | 92 return WEBRTC_VIDEO_CODEC_MEMORY; |
| 93 } | 93 } |
| 94 delete encoder_; | 94 delete encoder_; |
| 95 encoder_ = NULL; | 95 encoder_ = NULL; |
| 96 } | 96 } |
| 97 if (config_ != NULL) { | 97 if (config_ != NULL) { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 if (&codec_ != inst) { | 256 if (&codec_ != inst) { |
| 257 codec_ = *inst; | 257 codec_ = *inst; |
| 258 } | 258 } |
| 259 | 259 |
| 260 num_spatial_layers_ = inst->codecSpecific.VP9.numberOfSpatialLayers; | 260 num_spatial_layers_ = inst->codecSpecific.VP9.numberOfSpatialLayers; |
| 261 num_temporal_layers_ = inst->codecSpecific.VP9.numberOfTemporalLayers; | 261 num_temporal_layers_ = inst->codecSpecific.VP9.numberOfTemporalLayers; |
| 262 if (num_temporal_layers_ == 0) | 262 if (num_temporal_layers_ == 0) |
| 263 num_temporal_layers_ = 1; | 263 num_temporal_layers_ = 1; |
| 264 | 264 |
| 265 // Random start 16 bits is enough. | 265 // Random start 16 bits is enough. |
| 266 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 266 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; // NOLINT |
| 267 // Allocate memory for encoded image | 267 // Allocate memory for encoded image |
| 268 if (encoded_image_._buffer != NULL) { | 268 if (encoded_image_._buffer != NULL) { |
| 269 delete [] encoded_image_._buffer; | 269 delete[] encoded_image_._buffer; |
| 270 } | 270 } |
| 271 encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); | 271 encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height); |
| 272 encoded_image_._buffer = new uint8_t[encoded_image_._size]; | 272 encoded_image_._buffer = new uint8_t[encoded_image_._size]; |
| 273 encoded_image_._completeFrame = true; | 273 encoded_image_._completeFrame = true; |
| 274 // Creating a wrapper to the image - setting image data to NULL. Actual | 274 // Creating a wrapper to the image - setting image data to NULL. Actual |
| 275 // pointer will be set in encode. Setting align to 1, as it is meaningless | 275 // pointer will be set in encode. Setting align to 1, as it is meaningless |
| 276 // (actual memory is not allocated). | 276 // (actual memory is not allocated). |
| 277 raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height, | 277 raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height, 1, |
| 278 1, NULL); | 278 NULL); |
| 279 // Populate encoder configuration with default values. | 279 // Populate encoder configuration with default values. |
| 280 if (vpx_codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) { | 280 if (vpx_codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) { |
| 281 return WEBRTC_VIDEO_CODEC_ERROR; | 281 return WEBRTC_VIDEO_CODEC_ERROR; |
| 282 } | 282 } |
| 283 config_->g_w = codec_.width; | 283 config_->g_w = codec_.width; |
| 284 config_->g_h = codec_.height; | 284 config_->g_h = codec_.height; |
| 285 config_->rc_target_bitrate = inst->startBitrate; // in kbit/s | 285 config_->rc_target_bitrate = inst->startBitrate; // in kbit/s |
| 286 config_->g_error_resilient = 1; | 286 config_->g_error_resilient = 1; |
| 287 // Setting the time base of the codec. | 287 // Setting the time base of the codec. |
| 288 config_->g_timebase.num = 1; | 288 config_->g_timebase.num = 1; |
| 289 config_->g_timebase.den = 90000; | 289 config_->g_timebase.den = 90000; |
| 290 config_->g_lag_in_frames = 0; // 0- no frame lagging | 290 config_->g_lag_in_frames = 0; // 0- no frame lagging |
| 291 config_->g_threads = 1; | 291 config_->g_threads = 1; |
| 292 // Rate control settings. | 292 // Rate control settings. |
| 293 config_->rc_dropframe_thresh = inst->codecSpecific.VP9.frameDroppingOn ? | 293 config_->rc_dropframe_thresh = |
| 294 30 : 0; | 294 inst->codecSpecific.VP9.frameDroppingOn ? 30 : 0; |
| 295 config_->rc_end_usage = VPX_CBR; | 295 config_->rc_end_usage = VPX_CBR; |
| 296 config_->g_pass = VPX_RC_ONE_PASS; | 296 config_->g_pass = VPX_RC_ONE_PASS; |
| 297 config_->rc_min_quantizer = 2; | 297 config_->rc_min_quantizer = 2; |
| 298 config_->rc_max_quantizer = 52; | 298 config_->rc_max_quantizer = 52; |
| 299 config_->rc_undershoot_pct = 50; | 299 config_->rc_undershoot_pct = 50; |
| 300 config_->rc_overshoot_pct = 50; | 300 config_->rc_overshoot_pct = 50; |
| 301 config_->rc_buf_initial_sz = 500; | 301 config_->rc_buf_initial_sz = 500; |
| 302 config_->rc_buf_optimal_sz = 600; | 302 config_->rc_buf_optimal_sz = 600; |
| 303 config_->rc_buf_sz = 1000; | 303 config_->rc_buf_sz = 1000; |
| 304 // Set the maximum target size of any key-frame. | 304 // Set the maximum target size of any key-frame. |
| 305 rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz); | 305 rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz); |
| 306 if (inst->codecSpecific.VP9.keyFrameInterval > 0) { | 306 if (inst->codecSpecific.VP9.keyFrameInterval > 0) { |
| 307 config_->kf_mode = VPX_KF_AUTO; | 307 config_->kf_mode = VPX_KF_AUTO; |
| 308 config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval; | 308 config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval; |
| 309 // Needs to be set (in svc mode) to get correct periodic key frame interval | 309 // Needs to be set (in svc mode) to get correct periodic key frame interval |
| 310 // (will have no effect in non-svc). | 310 // (will have no effect in non-svc). |
| 311 config_->kf_min_dist = config_->kf_max_dist; | 311 config_->kf_min_dist = config_->kf_max_dist; |
| 312 } else { | 312 } else { |
| 313 config_->kf_mode = VPX_KF_DISABLED; | 313 config_->kf_mode = VPX_KF_DISABLED; |
| 314 } | 314 } |
| 315 config_->rc_resize_allowed = inst->codecSpecific.VP9.automaticResizeOn ? | 315 config_->rc_resize_allowed = |
| 316 1 : 0; | 316 inst->codecSpecific.VP9.automaticResizeOn ? 1 : 0; |
| 317 // Determine number of threads based on the image size and #cores. | 317 // Determine number of threads based on the image size and #cores. |
| 318 config_->g_threads = NumberOfThreads(config_->g_w, | 318 config_->g_threads = |
| 319 config_->g_h, | 319 NumberOfThreads(config_->g_w, config_->g_h, number_of_cores); |
| 320 number_of_cores); | |
| 321 | 320 |
| 322 cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); | 321 cpu_speed_ = GetCpuSpeed(config_->g_w, config_->g_h); |
| 323 | 322 |
| 324 // TODO(asapersson): Check configuration of temporal switch up and increase | 323 // TODO(asapersson): Check configuration of temporal switch up and increase |
| 325 // pattern length. | 324 // pattern length. |
| 326 is_flexible_mode_ = inst->codecSpecific.VP9.flexibleMode; | 325 is_flexible_mode_ = inst->codecSpecific.VP9.flexibleMode; |
| 327 if (is_flexible_mode_) { | 326 if (is_flexible_mode_) { |
| 328 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; | 327 config_->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; |
| 329 config_->ts_number_layers = num_temporal_layers_; | 328 config_->ts_number_layers = num_temporal_layers_; |
| 330 if (codec_.mode == kScreensharing) | 329 if (codec_.mode == kScreensharing) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 354 config_->ts_rate_decimator[2] = 1; | 353 config_->ts_rate_decimator[2] = 1; |
| 355 config_->ts_periodicity = 4; | 354 config_->ts_periodicity = 4; |
| 356 config_->ts_layer_id[0] = 0; | 355 config_->ts_layer_id[0] = 0; |
| 357 config_->ts_layer_id[1] = 2; | 356 config_->ts_layer_id[1] = 2; |
| 358 config_->ts_layer_id[2] = 1; | 357 config_->ts_layer_id[2] = 1; |
| 359 config_->ts_layer_id[3] = 2; | 358 config_->ts_layer_id[3] = 2; |
| 360 } else { | 359 } else { |
| 361 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 360 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 362 } | 361 } |
| 363 | 362 |
| 364 tl0_pic_idx_ = static_cast<uint8_t>(rand()); | 363 tl0_pic_idx_ = static_cast<uint8_t>(rand()); // NOLINT |
| 365 | 364 |
| 366 return InitAndSetControlSettings(inst); | 365 return InitAndSetControlSettings(inst); |
| 367 } | 366 } |
| 368 | 367 |
| 369 int VP9EncoderImpl::NumberOfThreads(int width, | 368 int VP9EncoderImpl::NumberOfThreads(int width, |
| 370 int height, | 369 int height, |
| 371 int number_of_cores) { | 370 int number_of_cores) { |
| 372 // Keep the number of encoder threads equal to the possible number of column | 371 // Keep the number of encoder threads equal to the possible number of column |
| 373 // tiles, which is (1, 2, 4, 8). See comments below for VP9E_SET_TILE_COLUMNS. | 372 // tiles, which is (1, 2, 4, 8). See comments below for VP9E_SET_TILE_COLUMNS. |
| 374 if (width * height >= 1280 * 720 && number_of_cores > 4) { | 373 if (width * height >= 1280 * 720 && number_of_cores > 4) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 | 420 |
| 422 vpx_codec_control( | 421 vpx_codec_control( |
| 423 encoder_, VP9E_SET_SVC, | 422 encoder_, VP9E_SET_SVC, |
| 424 (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) ? 1 : 0); | 423 (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) ? 1 : 0); |
| 425 if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { | 424 if (num_temporal_layers_ > 1 || num_spatial_layers_ > 1) { |
| 426 vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, | 425 vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, |
| 427 &svc_internal_.svc_params); | 426 &svc_internal_.svc_params); |
| 428 } | 427 } |
| 429 // Register callback for getting each spatial layer. | 428 // Register callback for getting each spatial layer. |
| 430 vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = { | 429 vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = { |
| 431 VP9EncoderImpl::EncoderOutputCodedPacketCallback, (void*)(this)}; | 430 VP9EncoderImpl::EncoderOutputCodedPacketCallback, |
| 432 vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK, (void*)(&cbp)); | 431 reinterpret_cast<void*>(this)}; |
| 432 vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK, |
| 433 reinterpret_cast<void*>(&cbp)); |
| 433 | 434 |
| 434 // Control function to set the number of column tiles in encoding a frame, in | 435 // Control function to set the number of column tiles in encoding a frame, in |
| 435 // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. | 436 // log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns. |
| 436 // The number tile columns will be capped by the encoder based on image size | 437 // The number tile columns will be capped by the encoder based on image size |
| 437 // (minimum width of tile column is 256 pixels, maximum is 4096). | 438 // (minimum width of tile column is 256 pixels, maximum is 4096). |
| 438 vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); | 439 vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1)); |
| 439 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) | 440 #if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) |
| 440 // Note denoiser is still off by default until further testing/optimization, | 441 // Note denoiser is still off by default until further testing/optimization, |
| 441 // i.e., codecSpecific.VP9.denoisingOn == 0. | 442 // i.e., codecSpecific.VP9.denoisingOn == 0. |
| 442 vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, | 443 vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 457 // and scaled by a scale_par. | 458 // and scaled by a scale_par. |
| 458 // Max target size = scale_par * optimal_buffer_size * targetBR[Kbps]. | 459 // Max target size = scale_par * optimal_buffer_size * targetBR[Kbps]. |
| 459 // This value is presented in percentage of perFrameBw: | 460 // This value is presented in percentage of perFrameBw: |
| 460 // perFrameBw = targetBR[Kbps] * 1000 / framerate. | 461 // perFrameBw = targetBR[Kbps] * 1000 / framerate. |
| 461 // The target in % is as follows: | 462 // The target in % is as follows: |
| 462 float scale_par = 0.5; | 463 float scale_par = 0.5; |
| 463 uint32_t target_pct = | 464 uint32_t target_pct = |
| 464 optimal_buffer_size * scale_par * codec_.maxFramerate / 10; | 465 optimal_buffer_size * scale_par * codec_.maxFramerate / 10; |
| 465 // Don't go below 3 times the per frame bandwidth. | 466 // Don't go below 3 times the per frame bandwidth. |
| 466 const uint32_t min_intra_size = 300; | 467 const uint32_t min_intra_size = 300; |
| 467 return (target_pct < min_intra_size) ? min_intra_size: target_pct; | 468 return (target_pct < min_intra_size) ? min_intra_size : target_pct; |
| 468 } | 469 } |
| 469 | 470 |
| 470 int VP9EncoderImpl::Encode(const VideoFrame& input_image, | 471 int VP9EncoderImpl::Encode(const VideoFrame& input_image, |
| 471 const CodecSpecificInfo* codec_specific_info, | 472 const CodecSpecificInfo* codec_specific_info, |
| 472 const std::vector<FrameType>* frame_types) { | 473 const std::vector<FrameType>* frame_types) { |
| 473 if (!inited_) { | 474 if (!inited_) { |
| 474 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 475 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 475 } | 476 } |
| 476 if (input_image.IsZeroSize()) { | 477 if (input_image.IsZeroSize()) { |
| 477 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 478 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags, | 537 if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags, |
| 537 VPX_DL_REALTIME)) { | 538 VPX_DL_REALTIME)) { |
| 538 return WEBRTC_VIDEO_CODEC_ERROR; | 539 return WEBRTC_VIDEO_CODEC_ERROR; |
| 539 } | 540 } |
| 540 timestamp_ += duration; | 541 timestamp_ += duration; |
| 541 | 542 |
| 542 return WEBRTC_VIDEO_CODEC_OK; | 543 return WEBRTC_VIDEO_CODEC_OK; |
| 543 } | 544 } |
| 544 | 545 |
| 545 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, | 546 void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, |
| 546 const vpx_codec_cx_pkt& pkt, | 547 const vpx_codec_cx_pkt& pkt, |
| 547 uint32_t timestamp) { | 548 uint32_t timestamp) { |
| 548 assert(codec_specific != NULL); | 549 assert(codec_specific != NULL); |
| 549 codec_specific->codecType = kVideoCodecVP9; | 550 codec_specific->codecType = kVideoCodecVP9; |
| 550 CodecSpecificInfoVP9 *vp9_info = &(codec_specific->codecSpecific.VP9); | 551 CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9); |
| 551 // TODO(asapersson): Set correct value. | 552 // TODO(asapersson): Set correct value. |
| 552 vp9_info->inter_pic_predicted = | 553 vp9_info->inter_pic_predicted = |
| 553 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true; | 554 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? false : true; |
| 554 vp9_info->flexible_mode = codec_.codecSpecific.VP9.flexibleMode; | 555 vp9_info->flexible_mode = codec_.codecSpecific.VP9.flexibleMode; |
| 555 vp9_info->ss_data_available = ((pkt.data.frame.flags & VPX_FRAME_IS_KEY) && | 556 vp9_info->ss_data_available = ((pkt.data.frame.flags & VPX_FRAME_IS_KEY) && |
| 556 !codec_.codecSpecific.VP9.flexibleMode) | 557 !codec_.codecSpecific.VP9.flexibleMode) |
| 557 ? true | 558 ? true |
| 558 : false; | 559 : false; |
| 559 | 560 |
| 560 vpx_svc_layer_id_t layer_id = {0}; | 561 vpx_svc_layer_id_t layer_id = {0}; |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 if (inst == NULL) { | 843 if (inst == NULL) { |
| 843 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 844 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 844 } | 845 } |
| 845 int ret_val = Release(); | 846 int ret_val = Release(); |
| 846 if (ret_val < 0) { | 847 if (ret_val < 0) { |
| 847 return ret_val; | 848 return ret_val; |
| 848 } | 849 } |
| 849 if (decoder_ == NULL) { | 850 if (decoder_ == NULL) { |
| 850 decoder_ = new vpx_codec_ctx_t; | 851 decoder_ = new vpx_codec_ctx_t; |
| 851 } | 852 } |
| 852 vpx_codec_dec_cfg_t cfg; | 853 vpx_codec_dec_cfg_t cfg; |
| 853 // Setting number of threads to a constant value (1) | 854 // Setting number of threads to a constant value (1) |
| 854 cfg.threads = 1; | 855 cfg.threads = 1; |
| 855 cfg.h = cfg.w = 0; // set after decode | 856 cfg.h = cfg.w = 0; // set after decode |
| 856 vpx_codec_flags_t flags = 0; | 857 vpx_codec_flags_t flags = 0; |
| 857 if (vpx_codec_dec_init(decoder_, vpx_codec_vp9_dx(), &cfg, flags)) { | 858 if (vpx_codec_dec_init(decoder_, vpx_codec_vp9_dx(), &cfg, flags)) { |
| 858 return WEBRTC_VIDEO_CODEC_MEMORY; | 859 return WEBRTC_VIDEO_CODEC_MEMORY; |
| 859 } | 860 } |
| 860 if (&codec_ != inst) { | 861 if (&codec_ != inst) { |
| 861 // Save VideoCodec instance for later; mainly for duplicating the decoder. | 862 // Save VideoCodec instance for later; mainly for duplicating the decoder. |
| 862 codec_ = *inst; | 863 codec_ = *inst; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 } | 896 } |
| 896 } | 897 } |
| 897 vpx_codec_iter_t iter = NULL; | 898 vpx_codec_iter_t iter = NULL; |
| 898 vpx_image_t* img; | 899 vpx_image_t* img; |
| 899 uint8_t* buffer = input_image._buffer; | 900 uint8_t* buffer = input_image._buffer; |
| 900 if (input_image._length == 0) { | 901 if (input_image._length == 0) { |
| 901 buffer = NULL; // Triggers full frame concealment. | 902 buffer = NULL; // Triggers full frame concealment. |
| 902 } | 903 } |
| 903 // During decode libvpx may get and release buffers from |frame_buffer_pool_|. | 904 // During decode libvpx may get and release buffers from |frame_buffer_pool_|. |
| 904 // In practice libvpx keeps a few (~3-4) buffers alive at a time. | 905 // In practice libvpx keeps a few (~3-4) buffers alive at a time. |
| 905 if (vpx_codec_decode(decoder_, | 906 if (vpx_codec_decode(decoder_, buffer, |
| 906 buffer, | 907 static_cast<unsigned int>(input_image._length), 0, |
| 907 static_cast<unsigned int>(input_image._length), | |
| 908 0, | |
| 909 VPX_DL_REALTIME)) { | 908 VPX_DL_REALTIME)) { |
| 910 return WEBRTC_VIDEO_CODEC_ERROR; | 909 return WEBRTC_VIDEO_CODEC_ERROR; |
| 911 } | 910 } |
| 912 // |img->fb_priv| contains the image data, a reference counted Vp9FrameBuffer. | 911 // |img->fb_priv| contains the image data, a reference counted Vp9FrameBuffer. |
| 913 // It may be released by libvpx during future vpx_codec_decode or | 912 // It may be released by libvpx during future vpx_codec_decode or |
| 914 // vpx_codec_destroy calls. | 913 // vpx_codec_destroy calls. |
| 915 img = vpx_codec_get_frame(decoder_, &iter); | 914 img = vpx_codec_get_frame(decoder_, &iter); |
| 916 int ret = ReturnFrame(img, input_image._timeStamp); | 915 int ret = ReturnFrame(img, input_image._timeStamp); |
| 917 if (ret != 0) { | 916 if (ret != 0) { |
| 918 return ret; | 917 return ret; |
| 919 } | 918 } |
| 920 return WEBRTC_VIDEO_CODEC_OK; | 919 return WEBRTC_VIDEO_CODEC_OK; |
| 921 } | 920 } |
| 922 | 921 |
| 923 int VP9DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) { | 922 int VP9DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) { |
| 924 if (img == NULL) { | 923 if (img == NULL) { |
| 925 // Decoder OK and NULL image => No show frame. | 924 // Decoder OK and NULL image => No show frame. |
| 926 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; | 925 return WEBRTC_VIDEO_CODEC_NO_OUTPUT; |
| 927 } | 926 } |
| 928 | 927 |
| 929 // This buffer contains all of |img|'s image data, a reference counted | 928 // This buffer contains all of |img|'s image data, a reference counted |
| 930 // Vp9FrameBuffer. (libvpx is done with the buffers after a few | 929 // Vp9FrameBuffer. (libvpx is done with the buffers after a few |
| 931 // vpx_codec_decode calls or vpx_codec_destroy). | 930 // vpx_codec_decode calls or vpx_codec_destroy). |
| 932 Vp9FrameBufferPool::Vp9FrameBuffer* img_buffer = | 931 Vp9FrameBufferPool::Vp9FrameBuffer* img_buffer = |
| 933 static_cast<Vp9FrameBufferPool::Vp9FrameBuffer*>(img->fb_priv); | 932 static_cast<Vp9FrameBufferPool::Vp9FrameBuffer*>(img->fb_priv); |
| 934 // The buffer can be used directly by the VideoFrame (without copy) by | 933 // The buffer can be used directly by the VideoFrame (without copy) by |
| 935 // using a WrappedI420Buffer. | 934 // using a WrappedI420Buffer. |
| 936 rtc::scoped_refptr<WrappedI420Buffer> img_wrapped_buffer( | 935 rtc::scoped_refptr<WrappedI420Buffer> img_wrapped_buffer( |
| 937 new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( | 936 new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( |
| 938 img->d_w, img->d_h, | 937 img->d_w, img->d_h, img->planes[VPX_PLANE_Y], |
| 939 img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y], | 938 img->stride[VPX_PLANE_Y], img->planes[VPX_PLANE_U], |
| 940 img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U], | 939 img->stride[VPX_PLANE_U], img->planes[VPX_PLANE_V], |
| 941 img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V], | 940 img->stride[VPX_PLANE_V], |
| 942 // WrappedI420Buffer's mechanism for allowing the release of its frame | 941 // WrappedI420Buffer's mechanism for allowing the release of its frame |
| 943 // buffer is through a callback function. This is where we should | 942 // buffer is through a callback function. This is where we should |
| 944 // release |img_buffer|. | 943 // release |img_buffer|. |
| 945 rtc::KeepRefUntilDone(img_buffer))); | 944 rtc::KeepRefUntilDone(img_buffer))); |
| 946 | 945 |
| 947 VideoFrame decoded_image; | 946 VideoFrame decoded_image; |
| 948 decoded_image.set_video_frame_buffer(img_wrapped_buffer); | 947 decoded_image.set_video_frame_buffer(img_wrapped_buffer); |
| 949 decoded_image.set_timestamp(timestamp); | 948 decoded_image.set_timestamp(timestamp); |
| 950 int ret = decode_complete_callback_->Decoded(decoded_image); | 949 int ret = decode_complete_callback_->Decoded(decoded_image); |
| 951 if (ret != 0) | 950 if (ret != 0) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 970 decoder_ = NULL; | 969 decoder_ = NULL; |
| 971 } | 970 } |
| 972 // Releases buffers from the pool. Any buffers not in use are deleted. Buffers | 971 // Releases buffers from the pool. Any buffers not in use are deleted. Buffers |
| 973 // still referenced externally are deleted once fully released, not returning | 972 // still referenced externally are deleted once fully released, not returning |
| 974 // to the pool. | 973 // to the pool. |
| 975 frame_buffer_pool_.ClearPool(); | 974 frame_buffer_pool_.ClearPool(); |
| 976 inited_ = false; | 975 inited_ = false; |
| 977 return WEBRTC_VIDEO_CODEC_OK; | 976 return WEBRTC_VIDEO_CODEC_OK; |
| 978 } | 977 } |
| 979 } // namespace webrtc | 978 } // namespace webrtc |
| OLD | NEW |