OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 inited_(false), | 116 inited_(false), |
117 timestamp_(0), | 117 timestamp_(0), |
118 feedback_mode_(false), | 118 feedback_mode_(false), |
119 qp_max_(56), // Setting for max quantizer. | 119 qp_max_(56), // Setting for max quantizer. |
120 cpu_speed_default_(-6), | 120 cpu_speed_default_(-6), |
121 number_of_cores_(0), | 121 number_of_cores_(0), |
122 rc_max_intra_target_(0), | 122 rc_max_intra_target_(0), |
123 token_partitions_(VP8_ONE_TOKENPARTITION), | 123 token_partitions_(VP8_ONE_TOKENPARTITION), |
124 down_scale_requested_(false), | 124 down_scale_requested_(false), |
125 down_scale_bitrate_(0), | 125 down_scale_bitrate_(0), |
126 key_frame_request_(kMaxSimulcastStreams, false), | 126 key_frame_request_(kMaxSimulcastStreams, false) { |
127 quality_scaler_enabled_(false) { | |
128 uint32_t seed = rtc::Time32(); | 127 uint32_t seed = rtc::Time32(); |
129 srand(seed); | 128 srand(seed); |
130 | 129 |
131 picture_id_.reserve(kMaxSimulcastStreams); | 130 picture_id_.reserve(kMaxSimulcastStreams); |
132 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); | 131 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); |
133 temporal_layers_.reserve(kMaxSimulcastStreams); | 132 temporal_layers_.reserve(kMaxSimulcastStreams); |
134 raw_images_.reserve(kMaxSimulcastStreams); | 133 raw_images_.reserve(kMaxSimulcastStreams); |
135 encoded_images_.reserve(kMaxSimulcastStreams); | 134 encoded_images_.reserve(kMaxSimulcastStreams); |
136 send_stream_.reserve(kMaxSimulcastStreams); | 135 send_stream_.reserve(kMaxSimulcastStreams); |
137 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. | 136 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 if (send_stream || encoders_.size() > 1) | 245 if (send_stream || encoders_.size() > 1) |
247 SetStreamState(send_stream, stream_idx); | 246 SetStreamState(send_stream, stream_idx); |
248 | 247 |
249 configurations_[i].rc_target_bitrate = target_bitrate_kbps; | 248 configurations_[i].rc_target_bitrate = target_bitrate_kbps; |
250 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | 249 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); |
251 | 250 |
252 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { | 251 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { |
253 return WEBRTC_VIDEO_CODEC_ERROR; | 252 return WEBRTC_VIDEO_CODEC_ERROR; |
254 } | 253 } |
255 } | 254 } |
256 quality_scaler_.ReportFramerate(new_framerate); | |
257 return WEBRTC_VIDEO_CODEC_OK; | 255 return WEBRTC_VIDEO_CODEC_OK; |
258 } | 256 } |
259 | 257 |
260 void VP8EncoderImpl::OnDroppedFrame() { | 258 void VP8EncoderImpl::OnDroppedFrame() { |
261 if (quality_scaler_enabled_) | |
262 quality_scaler_.ReportDroppedFrame(); | |
263 } | 259 } |
264 | 260 |
265 const char* VP8EncoderImpl::ImplementationName() const { | 261 const char* VP8EncoderImpl::ImplementationName() const { |
266 return "libvpx"; | 262 return "libvpx"; |
267 } | 263 } |
268 | 264 |
269 void VP8EncoderImpl::SetStreamState(bool send_stream, | 265 void VP8EncoderImpl::SetStreamState(bool send_stream, |
270 int stream_idx) { | 266 int stream_idx) { |
271 if (send_stream && !send_stream_[stream_idx]) { | 267 if (send_stream && !send_stream_[stream_idx]) { |
272 // Need a key frame if we have not sent this stream before. | 268 // Need a key frame if we have not sent this stream before. |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 inst->simulcastStream[stream_idx].width, | 523 inst->simulcastStream[stream_idx].width, |
528 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); | 524 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); |
529 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); | 525 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
530 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; | 526 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; |
531 temporal_layers_[stream_idx]->OnRatesUpdated( | 527 temporal_layers_[stream_idx]->OnRatesUpdated( |
532 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); | 528 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); |
533 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | 529 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); |
534 } | 530 } |
535 | 531 |
536 rps_.Init(); | 532 rps_.Init(); |
537 quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width, | |
538 codec_.height, codec_.maxFramerate); | |
539 | |
540 // Only apply scaling to improve for single-layer streams. The scaling metrics | |
541 // use frame drops as a signal and is only applicable when we drop frames. | |
542 quality_scaler_enabled_ = encoders_.size() == 1 && | |
543 configurations_[0].rc_dropframe_thresh > 0 && | |
544 codec_.VP8()->automaticResizeOn; | |
545 | |
546 return InitAndSetControlSettings(); | 533 return InitAndSetControlSettings(); |
547 } | 534 } |
548 | 535 |
549 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { | 536 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { |
550 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 537 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
551 // On mobile platform, use a lower speed setting for lower resolutions for | 538 // On mobile platform, use a lower speed setting for lower resolutions for |
552 // CPUs with 4 or more cores. | 539 // CPUs with 4 or more cores. |
553 RTC_DCHECK_GT(number_of_cores_, 0); | 540 RTC_DCHECK_GT(number_of_cores_, 0); |
554 if (number_of_cores_ <= 3) | 541 if (number_of_cores_ <= 3) |
555 return -12; | 542 return -12; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; | 655 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; |
669 | 656 |
670 // Don't go below 3 times the per frame bandwidth. | 657 // Don't go below 3 times the per frame bandwidth. |
671 const uint32_t minIntraTh = 300; | 658 const uint32_t minIntraTh = 300; |
672 return (targetPct < minIntraTh) ? minIntraTh : targetPct; | 659 return (targetPct < minIntraTh) ? minIntraTh : targetPct; |
673 } | 660 } |
674 | 661 |
675 int VP8EncoderImpl::Encode(const VideoFrame& frame, | 662 int VP8EncoderImpl::Encode(const VideoFrame& frame, |
676 const CodecSpecificInfo* codec_specific_info, | 663 const CodecSpecificInfo* codec_specific_info, |
677 const std::vector<FrameType>* frame_types) { | 664 const std::vector<FrameType>* frame_types) { |
| 665 RTC_DCHECK_EQ(frame.width(), codec_.width); |
| 666 RTC_DCHECK_EQ(frame.height(), codec_.height); |
| 667 |
678 if (!inited_) | 668 if (!inited_) |
679 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 669 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
680 if (frame.IsZeroSize()) | 670 if (frame.IsZeroSize()) |
681 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 671 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
682 if (encoded_complete_callback_ == NULL) | 672 if (encoded_complete_callback_ == NULL) |
683 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 673 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
684 | 674 |
685 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); | 675 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); |
686 | |
687 if (quality_scaler_enabled_) { | |
688 quality_scaler_.OnEncodeFrame(frame.width(), frame.height()); | |
689 input_image = quality_scaler_.GetScaledBuffer(input_image); | |
690 | |
691 if (input_image->width() != codec_.width || | |
692 input_image->height() != codec_.height) { | |
693 int ret = | |
694 UpdateCodecFrameSize(input_image->width(), input_image->height()); | |
695 if (ret < 0) | |
696 return ret; | |
697 } | |
698 } | |
699 | |
700 // Since we are extracting raw pointers from |input_image| to | 676 // Since we are extracting raw pointers from |input_image| to |
701 // |raw_images_[0]|, the resolution of these frames must match. Note that | 677 // |raw_images_[0]|, the resolution of these frames must match. Note that |
702 // |input_image| might be scaled from |frame|. In that case, the resolution of | 678 // |input_image| might be scaled from |frame|. In that case, the resolution of |
703 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. | 679 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. |
704 RTC_DCHECK_EQ(input_image->width(), static_cast<int>(raw_images_[0].d_w)); | 680 RTC_DCHECK_EQ(input_image->width(), static_cast<int>(raw_images_[0].d_w)); |
705 RTC_DCHECK_EQ(input_image->height(), static_cast<int>(raw_images_[0].d_h)); | 681 RTC_DCHECK_EQ(input_image->height(), static_cast<int>(raw_images_[0].d_h)); |
706 | 682 |
707 // Image in vpx_image_t format. | 683 // Image in vpx_image_t format. |
708 // Input image is const. VP8's raw image is not defined as const. | 684 // Input image is const. VP8's raw image is not defined as const. |
709 raw_images_[0].planes[VPX_PLANE_Y] = | 685 raw_images_[0].planes[VPX_PLANE_Y] = |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 encoded_images_[encoder_idx]._length, | 962 encoded_images_[encoder_idx]._length, |
987 encoded_images_[encoder_idx]._timeStamp, qp); | 963 encoded_images_[encoder_idx]._timeStamp, qp); |
988 if (send_stream_[stream_idx]) { | 964 if (send_stream_[stream_idx]) { |
989 if (encoded_images_[encoder_idx]._length > 0) { | 965 if (encoded_images_[encoder_idx]._length > 0) { |
990 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, | 966 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, |
991 encoded_images_[encoder_idx]._length); | 967 encoded_images_[encoder_idx]._length); |
992 encoded_images_[encoder_idx]._encodedHeight = | 968 encoded_images_[encoder_idx]._encodedHeight = |
993 codec_.simulcastStream[stream_idx].height; | 969 codec_.simulcastStream[stream_idx].height; |
994 encoded_images_[encoder_idx]._encodedWidth = | 970 encoded_images_[encoder_idx]._encodedWidth = |
995 codec_.simulcastStream[stream_idx].width; | 971 codec_.simulcastStream[stream_idx].width; |
996 encoded_images_[encoder_idx] | |
997 .adapt_reason_.quality_resolution_downscales = | |
998 quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1; | |
999 // Report once per frame (lowest stream always sent). | 972 // Report once per frame (lowest stream always sent). |
1000 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = | 973 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = |
1001 (stream_idx == 0) ? bw_resolutions_disabled : -1; | 974 (stream_idx == 0) ? bw_resolutions_disabled : -1; |
1002 int qp_128 = -1; | 975 int qp_128 = -1; |
1003 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, | 976 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, |
1004 &qp_128); | 977 &qp_128); |
1005 encoded_images_[encoder_idx].qp_ = qp_128; | 978 encoded_images_[encoder_idx].qp_ = qp_128; |
1006 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], | 979 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], |
1007 &codec_specific, &frag_info); | 980 &codec_specific, &frag_info); |
1008 } else if (codec_.mode == kScreensharing) { | 981 } else if (codec_.mode == kScreensharing) { |
1009 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; | 982 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; |
1010 } | 983 } |
1011 } | 984 } |
1012 } | 985 } |
1013 if (encoders_.size() == 1 && send_stream_[0]) { | |
1014 if (encoded_images_[0]._length > 0) { | |
1015 int qp_128; | |
1016 vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER, &qp_128); | |
1017 quality_scaler_.ReportQP(qp_128); | |
1018 } else { | |
1019 quality_scaler_.ReportDroppedFrame(); | |
1020 } | |
1021 } | |
1022 return result; | 986 return result; |
1023 } | 987 } |
1024 | 988 |
| 989 VideoEncoder::ScalingSettings VP8EncoderImpl::GetScalingSettings() const { |
| 990 const bool enable_scaling = encoders_.size() == 1 && |
| 991 configurations_[0].rc_dropframe_thresh > 0 && |
| 992 codec_.VP8().automaticResizeOn; |
| 993 return VideoEncoder::ScalingSettings(enable_scaling); |
| 994 } |
| 995 |
1025 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { | 996 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { |
1026 rps_.SetRtt(rtt); | 997 rps_.SetRtt(rtt); |
1027 return WEBRTC_VIDEO_CODEC_OK; | 998 return WEBRTC_VIDEO_CODEC_OK; |
1028 } | 999 } |
1029 | 1000 |
1030 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 1001 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
1031 EncodedImageCallback* callback) { | 1002 EncodedImageCallback* callback) { |
1032 encoded_complete_callback_ = callback; | 1003 encoded_complete_callback_ = callback; |
1033 return WEBRTC_VIDEO_CODEC_OK; | 1004 return WEBRTC_VIDEO_CODEC_OK; |
1034 } | 1005 } |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 return -1; | 1283 return -1; |
1313 } | 1284 } |
1314 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | 1285 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != |
1315 VPX_CODEC_OK) { | 1286 VPX_CODEC_OK) { |
1316 return -1; | 1287 return -1; |
1317 } | 1288 } |
1318 return 0; | 1289 return 0; |
1319 } | 1290 } |
1320 | 1291 |
1321 } // namespace webrtc | 1292 } // namespace webrtc |
OLD | NEW |