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() { | |
261 if (quality_scaler_enabled_) | |
262 quality_scaler_.ReportDroppedFrame(); | |
263 } | |
264 | |
265 const char* VP8EncoderImpl::ImplementationName() const { | 258 const char* VP8EncoderImpl::ImplementationName() const { |
266 return "libvpx"; | 259 return "libvpx"; |
267 } | 260 } |
268 | 261 |
269 void VP8EncoderImpl::SetStreamState(bool send_stream, | 262 void VP8EncoderImpl::SetStreamState(bool send_stream, |
270 int stream_idx) { | 263 int stream_idx) { |
271 if (send_stream && !send_stream_[stream_idx]) { | 264 if (send_stream && !send_stream_[stream_idx]) { |
272 // Need a key frame if we have not sent this stream before. | 265 // Need a key frame if we have not sent this stream before. |
273 key_frame_request_[stream_idx] = true; | 266 key_frame_request_[stream_idx] = true; |
274 } | 267 } |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 inst->simulcastStream[stream_idx].width, | 516 inst->simulcastStream[stream_idx].width, |
524 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); | 517 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); |
525 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); | 518 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
526 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; | 519 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; |
527 temporal_layers_[stream_idx]->OnRatesUpdated( | 520 temporal_layers_[stream_idx]->OnRatesUpdated( |
528 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); | 521 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); |
529 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | 522 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); |
530 } | 523 } |
531 | 524 |
532 rps_.Init(); | 525 rps_.Init(); |
533 quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width, | |
534 codec_.height, codec_.maxFramerate); | |
535 | |
536 // Only apply scaling to improve for single-layer streams. The scaling metrics | |
537 // use frame drops as a signal and is only applicable when we drop frames. | |
538 quality_scaler_enabled_ = encoders_.size() == 1 && | |
539 configurations_[0].rc_dropframe_thresh > 0 && | |
540 codec_.VP8()->automaticResizeOn; | |
541 | |
542 return InitAndSetControlSettings(); | 526 return InitAndSetControlSettings(); |
543 } | 527 } |
544 | 528 |
545 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { | 529 int VP8EncoderImpl::SetCpuSpeed(int width, int height) { |
546 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 530 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
547 // On mobile platform, use a lower speed setting for lower resolutions for | 531 // On mobile platform, use a lower speed setting for lower resolutions for |
548 // CPUs with 4 or more cores. | 532 // CPUs with 4 or more cores. |
549 RTC_DCHECK_GT(number_of_cores_, 0); | 533 RTC_DCHECK_GT(number_of_cores_, 0); |
550 if (number_of_cores_ <= 3) | 534 if (number_of_cores_ <= 3) |
551 return -12; | 535 return -12; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; | 648 uint32_t targetPct = optimalBuffersize * scalePar * codec_.maxFramerate / 10; |
665 | 649 |
666 // Don't go below 3 times the per frame bandwidth. | 650 // Don't go below 3 times the per frame bandwidth. |
667 const uint32_t minIntraTh = 300; | 651 const uint32_t minIntraTh = 300; |
668 return (targetPct < minIntraTh) ? minIntraTh : targetPct; | 652 return (targetPct < minIntraTh) ? minIntraTh : targetPct; |
669 } | 653 } |
670 | 654 |
671 int VP8EncoderImpl::Encode(const VideoFrame& frame, | 655 int VP8EncoderImpl::Encode(const VideoFrame& frame, |
672 const CodecSpecificInfo* codec_specific_info, | 656 const CodecSpecificInfo* codec_specific_info, |
673 const std::vector<FrameType>* frame_types) { | 657 const std::vector<FrameType>* frame_types) { |
| 658 RTC_DCHECK_EQ(frame.width(), codec_.width); |
| 659 RTC_DCHECK_EQ(frame.height(), codec_.height); |
| 660 |
674 if (!inited_) | 661 if (!inited_) |
675 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 662 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
676 if (frame.IsZeroSize()) | 663 if (frame.IsZeroSize()) |
677 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 664 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
678 if (encoded_complete_callback_ == NULL) | 665 if (encoded_complete_callback_ == NULL) |
679 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 666 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
680 | 667 |
681 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); | 668 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); |
682 | |
683 if (quality_scaler_enabled_) { | |
684 quality_scaler_.OnEncodeFrame(frame.width(), frame.height()); | |
685 input_image = quality_scaler_.GetScaledBuffer(input_image); | |
686 | |
687 if (input_image->width() != codec_.width || | |
688 input_image->height() != codec_.height) { | |
689 int ret = | |
690 UpdateCodecFrameSize(input_image->width(), input_image->height()); | |
691 if (ret < 0) | |
692 return ret; | |
693 } | |
694 } | |
695 | |
696 // Since we are extracting raw pointers from |input_image| to | 669 // Since we are extracting raw pointers from |input_image| to |
697 // |raw_images_[0]|, the resolution of these frames must match. Note that | 670 // |raw_images_[0]|, the resolution of these frames must match. Note that |
698 // |input_image| might be scaled from |frame|. In that case, the resolution of | 671 // |input_image| might be scaled from |frame|. In that case, the resolution of |
699 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. | 672 // |raw_images_[0]| should have been updated in UpdateCodecFrameSize. |
700 RTC_DCHECK_EQ(input_image->width(), raw_images_[0].d_w); | 673 RTC_DCHECK_EQ(input_image->width(), raw_images_[0].d_w); |
701 RTC_DCHECK_EQ(input_image->height(), raw_images_[0].d_h); | 674 RTC_DCHECK_EQ(input_image->height(), raw_images_[0].d_h); |
702 | 675 |
703 // Image in vpx_image_t format. | 676 // Image in vpx_image_t format. |
704 // Input image is const. VP8's raw image is not defined as const. | 677 // Input image is const. VP8's raw image is not defined as const. |
705 raw_images_[0].planes[VPX_PLANE_Y] = | 678 raw_images_[0].planes[VPX_PLANE_Y] = |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 encoded_images_[encoder_idx]._length, | 955 encoded_images_[encoder_idx]._length, |
983 encoded_images_[encoder_idx]._timeStamp, qp); | 956 encoded_images_[encoder_idx]._timeStamp, qp); |
984 if (send_stream_[stream_idx]) { | 957 if (send_stream_[stream_idx]) { |
985 if (encoded_images_[encoder_idx]._length > 0) { | 958 if (encoded_images_[encoder_idx]._length > 0) { |
986 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, | 959 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, |
987 encoded_images_[encoder_idx]._length); | 960 encoded_images_[encoder_idx]._length); |
988 encoded_images_[encoder_idx]._encodedHeight = | 961 encoded_images_[encoder_idx]._encodedHeight = |
989 codec_.simulcastStream[stream_idx].height; | 962 codec_.simulcastStream[stream_idx].height; |
990 encoded_images_[encoder_idx]._encodedWidth = | 963 encoded_images_[encoder_idx]._encodedWidth = |
991 codec_.simulcastStream[stream_idx].width; | 964 codec_.simulcastStream[stream_idx].width; |
992 encoded_images_[encoder_idx] | |
993 .adapt_reason_.quality_resolution_downscales = | |
994 quality_scaler_enabled_ ? quality_scaler_.downscale_shift() : -1; | |
995 // Report once per frame (lowest stream always sent). | 965 // Report once per frame (lowest stream always sent). |
996 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = | 966 encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled = |
997 (stream_idx == 0) ? bw_resolutions_disabled : -1; | 967 (stream_idx == 0) ? bw_resolutions_disabled : -1; |
998 int qp_128 = -1; | 968 int qp_128 = -1; |
999 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, | 969 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER, |
1000 &qp_128); | 970 &qp_128); |
1001 encoded_images_[encoder_idx].qp_ = qp_128; | 971 encoded_images_[encoder_idx].qp_ = qp_128; |
1002 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], | 972 encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx], |
1003 &codec_specific, &frag_info); | 973 &codec_specific, &frag_info); |
1004 } else if (codec_.mode == kScreensharing) { | 974 } else if (codec_.mode == kScreensharing) { |
1005 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; | 975 result = WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT; |
1006 } | 976 } |
1007 } | 977 } |
1008 } | 978 } |
1009 if (encoders_.size() == 1 && send_stream_[0]) { | |
1010 if (encoded_images_[0]._length > 0) { | |
1011 int qp_128; | |
1012 vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER, &qp_128); | |
1013 quality_scaler_.ReportQP(qp_128); | |
1014 } else { | |
1015 quality_scaler_.ReportDroppedFrame(); | |
1016 } | |
1017 } | |
1018 return result; | 979 return result; |
1019 } | 980 } |
1020 | 981 |
| 982 VideoEncoder::ScalingSettings VP8EncoderImpl::GetScalingSettings() const { |
| 983 const bool enable_scaling = encoders_.size() == 1 && |
| 984 configurations_[0].rc_dropframe_thresh > 0 && |
| 985 codec_.VP8().automaticResizeOn; |
| 986 return VideoEncoder::ScalingSettings(enable_scaling); |
| 987 } |
| 988 |
1021 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { | 989 int VP8EncoderImpl::SetChannelParameters(uint32_t packetLoss, int64_t rtt) { |
1022 rps_.SetRtt(rtt); | 990 rps_.SetRtt(rtt); |
1023 return WEBRTC_VIDEO_CODEC_OK; | 991 return WEBRTC_VIDEO_CODEC_OK; |
1024 } | 992 } |
1025 | 993 |
1026 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 994 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
1027 EncodedImageCallback* callback) { | 995 EncodedImageCallback* callback) { |
1028 encoded_complete_callback_ = callback; | 996 encoded_complete_callback_ = callback; |
1029 return WEBRTC_VIDEO_CODEC_OK; | 997 return WEBRTC_VIDEO_CODEC_OK; |
1030 } | 998 } |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 return -1; | 1276 return -1; |
1309 } | 1277 } |
1310 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | 1278 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != |
1311 VPX_CODEC_OK) { | 1279 VPX_CODEC_OK) { |
1312 return -1; | 1280 return -1; |
1313 } | 1281 } |
1314 return 0; | 1282 return 0; |
1315 } | 1283 } |
1316 | 1284 |
1317 } // namespace webrtc | 1285 } // namespace webrtc |
OLD | NEW |