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 |