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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 inited_(false), | 117 inited_(false), |
118 timestamp_(0), | 118 timestamp_(0), |
119 feedback_mode_(false), | 119 feedback_mode_(false), |
120 qp_max_(56), // Setting for max quantizer. | 120 qp_max_(56), // Setting for max quantizer. |
121 cpu_speed_default_(-6), | 121 cpu_speed_default_(-6), |
122 number_of_cores_(0), | 122 number_of_cores_(0), |
123 rc_max_intra_target_(0), | 123 rc_max_intra_target_(0), |
124 token_partitions_(VP8_ONE_TOKENPARTITION), | 124 token_partitions_(VP8_ONE_TOKENPARTITION), |
125 down_scale_requested_(false), | 125 down_scale_requested_(false), |
126 down_scale_bitrate_(0), | 126 down_scale_bitrate_(0), |
127 key_frame_request_(kMaxSimulcastStreams, false), | 127 key_frame_request_(kMaxSimulcastStreams, false) { |
128 quality_scaler_enabled_(false) { | |
129 uint32_t seed = rtc::Time32(); | 128 uint32_t seed = rtc::Time32(); |
130 srand(seed); | 129 srand(seed); |
131 | 130 |
132 picture_id_.reserve(kMaxSimulcastStreams); | 131 picture_id_.reserve(kMaxSimulcastStreams); |
133 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); | 132 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); |
134 temporal_layers_.reserve(kMaxSimulcastStreams); | 133 temporal_layers_.reserve(kMaxSimulcastStreams); |
135 raw_images_.reserve(kMaxSimulcastStreams); | 134 raw_images_.reserve(kMaxSimulcastStreams); |
136 encoded_images_.reserve(kMaxSimulcastStreams); | 135 encoded_images_.reserve(kMaxSimulcastStreams); |
137 send_stream_.reserve(kMaxSimulcastStreams); | 136 send_stream_.reserve(kMaxSimulcastStreams); |
138 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. | 137 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 max_bitrate = std::min(codec_.maxBitrate, target_bitrate); | 254 max_bitrate = std::min(codec_.maxBitrate, target_bitrate); |
256 target_bitrate = tl0_bitrate; | 255 target_bitrate = tl0_bitrate; |
257 } | 256 } |
258 configurations_[i].rc_target_bitrate = target_bitrate; | 257 configurations_[i].rc_target_bitrate = target_bitrate; |
259 temporal_layers_[stream_idx]->ConfigureBitrates( | 258 temporal_layers_[stream_idx]->ConfigureBitrates( |
260 target_bitrate, max_bitrate, framerate, &configurations_[i]); | 259 target_bitrate, max_bitrate, framerate, &configurations_[i]); |
261 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { | 260 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { |
262 return WEBRTC_VIDEO_CODEC_ERROR; | 261 return WEBRTC_VIDEO_CODEC_ERROR; |
263 } | 262 } |
264 } | 263 } |
265 quality_scaler_.ReportFramerate(new_framerate); | |
266 return WEBRTC_VIDEO_CODEC_OK; | 264 return WEBRTC_VIDEO_CODEC_OK; |
267 } | 265 } |
268 | 266 |
269 void VP8EncoderImpl::OnDroppedFrame() { | 267 void VP8EncoderImpl::OnDroppedFrame() { |
270 if (quality_scaler_enabled_) | |
271 quality_scaler_.ReportDroppedFrame(); | |
272 } | 268 } |
273 | 269 |
274 const char* VP8EncoderImpl::ImplementationName() const { | 270 const char* VP8EncoderImpl::ImplementationName() const { |
275 return "libvpx"; | 271 return "libvpx"; |
276 } | 272 } |
277 | 273 |
278 void VP8EncoderImpl::SetStreamState(bool send_stream, | 274 void VP8EncoderImpl::SetStreamState(bool send_stream, |
279 int stream_idx) { | 275 int stream_idx) { |
280 if (send_stream && !send_stream_[stream_idx]) { | 276 if (send_stream && !send_stream_[stream_idx]) { |
281 // Need a key frame if we have not sent this stream before. | 277 // Need a key frame if we have not sent this stream before. |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); | 545 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); |
550 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); | 546 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
551 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; | 547 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; |
552 temporal_layers_[stream_idx]->ConfigureBitrates( | 548 temporal_layers_[stream_idx]->ConfigureBitrates( |
553 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, | 549 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, |
554 &configurations_[i]); | 550 &configurations_[i]); |
555 } | 551 } |
556 } | 552 } |
557 | 553 |
558 rps_.Init(); | 554 rps_.Init(); |
559 quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width, | |
560 codec_.height, codec_.maxFramerate); | |
561 | |
562 // Only apply scaling to improve for single-layer streams. The scaling metrics | |
563 // use frame drops as a signal and is only applicable when we drop frames. | |
564 quality_scaler_enabled_ = encoders_.size() == 1 && | |
565 configurations_[0].rc_dropframe_thresh > 0 && | |
566 codec_.VP8()->automaticResizeOn; | |
567 | |
568 return InitAndSetControlSettings(); | 555 return InitAndSetControlSettings(); |
569 } | 556 } |
570 | 557 |
571 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { | 558 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { |
572 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 559 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
573 // On mobile platform, use a lower speed setting for lower resolutions for | 560 // On mobile platform, use a lower speed setting for lower resolutions for |
574 // CPUs with 4 or more cores. | 561 // CPUs with 4 or more cores. |
575 RTC_DCHECK_GT(number_of_cores_, 0); | 562 RTC_DCHECK_GT(number_of_cores_, 0); |
576 if (number_of_cores_ <= 3) | 563 if (number_of_cores_ <= 3) |
577 return -12; | 564 return -12; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; | 677 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; |
691 | 678 |
692 // Don't go below 3 times the per frame bandwidth. | 679 // Don't go below 3 times the per frame bandwidth. |
693 const uint32_t minIntraTh = 300; | 680 const uint32_t minIntraTh = 300; |
694 return (targetPct < minIntraTh) ? minIntraTh : targetPct; | 681 return (targetPct < minIntraTh) ? minIntraTh : targetPct; |
695 } | 682 } |
696 | 683 |
697 int VP8EncoderImpl::Encode(const VideoFrame& frame, | 684 int VP8EncoderImpl::Encode(const VideoFrame& frame, |
698 const CodecSpecificInfo* codec_specific_info, | 685 const CodecSpecificInfo* codec_specific_info, |
699 const std::vector<FrameType>* frame_types) { | 686 const std::vector<FrameType>* frame_types) { |
| 687 RTC_DCHECK_EQ(frame.width(), codec_.width); |
| 688 RTC_DCHECK_EQ(frame.height(), codec_.height); |
| 689 |
700 if (!inited_) | 690 if (!inited_) |
701 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 691 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
702 if (frame.IsZeroSize()) | 692 if (frame.IsZeroSize()) |
703 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 693 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
704 if (encoded_complete_callback_ == NULL) | 694 if (encoded_complete_callback_ == NULL) |
705 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 695 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
706 | 696 |
707 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); | 697 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); |
708 | |
709 if (quality_scaler_enabled_) { | |
710 quality_scaler_.OnEncodeFrame(frame.width(), frame.height()); | |
711 input_image = quality_scaler_.GetScaledBuffer(input_image); | |
712 | |
713 if (input_image->width() != codec_.width || | |
714 input_image->height() != codec_.height) { | |
715 int ret = | |
716 UpdateCodecFrameSize(input_image->width(), input_image->height()); | |
717 if (ret < 0) | |
718 return ret; | |
719 } | |
720 } | |
721 | |
722 // Since we are extracting raw pointers from |input_image| to | 698 // Since we are extracting raw pointers from |input_image| to |
723 // |raw_images_[0]|, the resolution of these frames must match. Note that | 699 // |raw_images_[0]|, the resolution of these frames must match. Note that |
724 // |input_image| might be scaled from |frame|. In that case, the resolution of | 700 // |input_image| might be scaled from |frame|. In that case, the resolution of |
725 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. | 701 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. |
726 RTC_DCHECK_EQ(input_image->width(), static_cast<int>(raw_images_[0].d_w)); | 702 RTC_DCHECK_EQ(input_image->width(), static_cast<int>(raw_images_[0].d_w)); |
727 RTC_DCHECK_EQ(input_image->height(), static_cast<int>(raw_images_[0].d_h)); | 703 RTC_DCHECK_EQ(input_image->height(), static_cast<int>(raw_images_[0].d_h)); |
728 | 704 |
729 // Image in vpx_image_t format. | 705 // Image in vpx_image_t format. |
730 // Input image is const. VP8's raw image is not defined as const. | 706 // Input image is const. VP8's raw image is not defined as const. |
731 raw_images_[0].planes[VPX_PLANE_Y] = | 707 raw_images_[0].planes[VPX_PLANE_Y] = |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 encoded_images_[encoder_idx]._length, | 984 encoded_images_[encoder_idx]._length, |
1009 encoded_images_[encoder_idx]._timeStamp, qp); | 985 encoded_images_[encoder_idx]._timeStamp, qp); |
1010 if (send_stream_[stream_idx]) { | 986 if (send_stream_[stream_idx]) { |
1011 if (encoded_images_[encoder_idx]._length > 0) { | 987 if (encoded_images_[encoder_idx]._length > 0) { |
1012 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, | 988 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, |
1013 encoded_images_[encoder_idx]._length); | 989 encoded_images_[encoder_idx]._length); |
1014 encoded_images_[encoder_idx]._encodedHeight = | 990 encoded_images_[encoder_idx]._encodedHeight = |
1015 codec_.simulcastStream[stream_idx].height; | 991 codec_.simulcastStream[stream_idx].height; |
1016 encoded_images_[encoder_idx]._encodedWidth = | 992 encoded_images_[encoder_idx]._encodedWidth = |
1017 codec_.simulcastStream[stream_idx].width; | 993 codec_.simulcastStream[stream_idx].width; |
1018 encoded_images_[encoder_idx] | |
1019 .adapt_reason_.quality_resolution_downscales = | |
1020 quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1; | |
1021 // Report once per frame (lowest stream always sent). | 994 // Report once per frame (lowest stream always sent). |
1022 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = | 995 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = |
1023 (stream_idx == 0) ? bw_resolutions_disabled : -1; | 996 (stream_idx == 0) ? bw_resolutions_disabled : -1; |
1024 int qp_128 = -1; | 997 int qp_128 = -1; |
1025 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, | 998 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, |
1026 &qp_128); | 999 &qp_128); |
1027 encoded_images_[encoder_idx].qp_ = qp_128; | 1000 encoded_images_[encoder_idx].qp_ = qp_128; |
1028 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], | 1001 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], |
1029 &codec_specific, &frag_info); | 1002 &codec_specific, &frag_info); |
1030 } else if (codec_.mode == kScreensharing) { | 1003 } else if (codec_.mode == kScreensharing) { |
1031 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; | 1004 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; |
1032 } | 1005 } |
1033 } | 1006 } |
1034 } | 1007 } |
1035 if (encoders_.size() == 1 && send_stream_[0]) { | |
1036 if (encoded_images_[0]._length > 0) { | |
1037 int qp_128; | |
1038 vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER, &qp_128); | |
1039 quality_scaler_.ReportQP(qp_128); | |
1040 } else { | |
1041 quality_scaler_.ReportDroppedFrame(); | |
1042 } | |
1043 } | |
1044 return result; | 1008 return result; |
1045 } | 1009 } |
1046 | 1010 |
| 1011 QualityScaler::Settings VP8EncoderImpl::GetQPThresholds() const { |
| 1012 const bool enable_scaling = encoders_.size() == 1 && |
| 1013 configurations_[0].rc_dropframe_thresh > 0 && |
| 1014 codec_.codecSpecific.VP8.automaticResizeOn; |
| 1015 return QualityScaler::Settings(enable_scaling); |
| 1016 } |
| 1017 |
1047 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { | 1018 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { |
1048 rps_.SetRtt(rtt); | 1019 rps_.SetRtt(rtt); |
1049 return WEBRTC_VIDEO_CODEC_OK; | 1020 return WEBRTC_VIDEO_CODEC_OK; |
1050 } | 1021 } |
1051 | 1022 |
1052 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 1023 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
1053 EncodedImageCallback* callback) { | 1024 EncodedImageCallback* callback) { |
1054 encoded_complete_callback_ = callback; | 1025 encoded_complete_callback_ = callback; |
1055 return WEBRTC_VIDEO_CODEC_OK; | 1026 return WEBRTC_VIDEO_CODEC_OK; |
1056 } | 1027 } |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 return -1; | 1305 return -1; |
1335 } | 1306 } |
1336 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | 1307 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != |
1337 VPX_CODEC_OK) { | 1308 VPX_CODEC_OK) { |
1338 return -1; | 1309 return -1; |
1339 } | 1310 } |
1340 return 0; | 1311 return 0; |
1341 } | 1312 } |
1342 | 1313 |
1343 } // namespace webrtc | 1314 } // namespace webrtc |
OLD | NEW |