OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2015 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 const int64_t frame_input_time_ms); | 158 const int64_t frame_input_time_ms); |
159 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, | 159 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, |
160 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); | 160 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); |
161 bool EncodeTextureOnCodecThread(JNIEnv* jni, | 161 bool EncodeTextureOnCodecThread(JNIEnv* jni, |
162 bool key_frame, const webrtc::VideoFrame& frame); | 162 bool key_frame, const webrtc::VideoFrame& frame); |
163 | 163 |
164 int32_t RegisterEncodeCompleteCallbackOnCodecThread( | 164 int32_t RegisterEncodeCompleteCallbackOnCodecThread( |
165 webrtc::EncodedImageCallback* callback); | 165 webrtc::EncodedImageCallback* callback); |
166 int32_t ReleaseOnCodecThread(); | 166 int32_t ReleaseOnCodecThread(); |
167 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate); | 167 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate); |
168 void OnDroppedFrameOnCodecThread(); | |
169 | 168 |
170 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. | 169 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. |
171 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); | 170 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); |
172 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); | 171 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); |
173 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); | 172 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); |
174 jlong GetOutputBufferInfoPresentationTimestampUs( | 173 jlong GetOutputBufferInfoPresentationTimestampUs( |
175 JNIEnv* jni, jobject j_output_buffer_info); | 174 JNIEnv* jni, jobject j_output_buffer_info); |
176 | 175 |
177 // Deliver any outputs pending in the MediaCodec to our |callback_| and return | 176 // Deliver any outputs pending in the MediaCodec to our |callback_| and return |
178 // true on success. | 177 // true on success. |
179 bool DeliverPendingOutputs(JNIEnv* jni); | 178 bool DeliverPendingOutputs(JNIEnv* jni); |
180 | 179 |
181 // Search for H.264 start codes. | 180 // Search for H.264 start codes. |
182 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); | 181 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); |
183 | 182 |
| 183 QualityScaler::Settings GetQPThresholds() const override; |
| 184 |
184 // Displays encoder statistics. | 185 // Displays encoder statistics. |
185 void LogStatistics(bool force_log); | 186 void LogStatistics(bool force_log); |
186 | 187 |
187 // Type of video codec. | 188 // Type of video codec. |
188 VideoCodecType codecType_; | 189 VideoCodecType codecType_; |
189 | 190 |
190 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to | 191 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to |
191 // |codec_thread_| synchronously. | 192 // |codec_thread_| synchronously. |
192 webrtc::EncodedImageCallback* callback_; | 193 webrtc::EncodedImageCallback* callback_; |
193 | 194 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // |input_frame_infos_|. | 260 // |input_frame_infos_|. |
260 int64_t output_render_time_ms_; // Last output frame render time from | 261 int64_t output_render_time_ms_; // Last output frame render time from |
261 // |input_frame_infos_|. | 262 // |input_frame_infos_|. |
262 webrtc::VideoRotation output_rotation_; // Last output frame rotation from | 263 webrtc::VideoRotation output_rotation_; // Last output frame rotation from |
263 // |input_frame_infos_|. | 264 // |input_frame_infos_|. |
264 // Frame size in bytes fed to MediaCodec. | 265 // Frame size in bytes fed to MediaCodec. |
265 int yuv_size_; | 266 int yuv_size_; |
266 // True only when between a callback_->OnEncodedImage() call return a positive | 267 // True only when between a callback_->OnEncodedImage() call return a positive |
267 // value and the next Encode() call being ignored. | 268 // value and the next Encode() call being ignored. |
268 bool drop_next_input_frame_; | 269 bool drop_next_input_frame_; |
| 270 bool scale_; |
269 // Global references; must be deleted in Release(). | 271 // Global references; must be deleted in Release(). |
270 std::vector<jobject> input_buffers_; | 272 std::vector<jobject> input_buffers_; |
271 QualityScaler quality_scaler_; | |
272 // Dynamic resolution change, off by default. | |
273 bool scale_; | |
274 | |
275 // H264 bitstream parser, used to extract QP from encoded bitstreams. | |
276 webrtc::H264BitstreamParser h264_bitstream_parser_; | 273 webrtc::H264BitstreamParser h264_bitstream_parser_; |
277 | 274 |
278 // VP9 variables to populate codec specific structure. | 275 // VP9 variables to populate codec specific structure. |
279 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for | 276 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for |
280 // non-flexible VP9 mode. | 277 // non-flexible VP9 mode. |
281 uint8_t tl0_pic_idx_; | 278 uint8_t tl0_pic_idx_; |
282 size_t gof_idx_; | 279 size_t gof_idx_; |
283 | 280 |
284 // EGL context - owned by factory, should not be allocated/destroyed | 281 // EGL context - owned by factory, should not be allocated/destroyed |
285 // by MediaCodecVideoEncoder. | 282 // by MediaCodecVideoEncoder. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 scale_ = false; | 402 scale_ = false; |
406 if (codecType_ == kVideoCodecVP8) { | 403 if (codecType_ == kVideoCodecVP8) { |
407 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; | 404 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; |
408 } else if (codecType_ != kVideoCodecVP9) { | 405 } else if (codecType_ != kVideoCodecVP9) { |
409 scale_ = true; | 406 scale_ = true; |
410 } | 407 } |
411 | 408 |
412 ALOGD << "InitEncode request: " << init_width << " x " << init_height; | 409 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
413 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 410 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
414 | 411 |
415 if (scale_) { | |
416 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264) { | |
417 quality_scaler_.Init(codecType_, codec_settings->startBitrate, | |
418 codec_settings->width, codec_settings->height, | |
419 codec_settings->maxFramerate); | |
420 } else { | |
421 // When adding codec support to additional hardware codecs, also configure | |
422 // their QP thresholds for scaling. | |
423 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | |
424 scale_ = false; | |
425 } | |
426 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | |
427 init_width = res.width; | |
428 init_height = res.height; | |
429 ALOGD << "Scaled resolution: " << init_width << " x " << init_height; | |
430 } | |
431 | |
432 return codec_thread_->Invoke<int32_t>( | 412 return codec_thread_->Invoke<int32_t>( |
433 RTC_FROM_HERE, | 413 RTC_FROM_HERE, |
434 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, this, init_width, | 414 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, this, init_width, |
435 init_height, codec_settings->startBitrate, | 415 init_height, codec_settings->startBitrate, |
436 codec_settings->maxFramerate, | 416 codec_settings->maxFramerate, |
437 codec_settings->expect_encode_from_texture)); | 417 codec_settings->expect_encode_from_texture)); |
438 } | 418 } |
439 | 419 |
440 int32_t MediaCodecVideoEncoder::Encode( | 420 int32_t MediaCodecVideoEncoder::Encode( |
441 const webrtc::VideoFrame& frame, | 421 const webrtc::VideoFrame& frame, |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 681 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
702 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ | 682 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ |
703 << ". Kbps: " << last_set_bitrate_kbps_; | 683 << ". Kbps: " << last_set_bitrate_kbps_; |
704 } | 684 } |
705 | 685 |
706 if (drop_next_input_frame_) { | 686 if (drop_next_input_frame_) { |
707 ALOGW << "Encoder drop frame - failed callback."; | 687 ALOGW << "Encoder drop frame - failed callback."; |
708 drop_next_input_frame_ = false; | 688 drop_next_input_frame_ = false; |
709 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 689 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
710 frames_dropped_media_encoder_++; | 690 frames_dropped_media_encoder_++; |
711 OnDroppedFrameOnCodecThread(); | |
712 return WEBRTC_VIDEO_CODEC_OK; | 691 return WEBRTC_VIDEO_CODEC_OK; |
713 } | 692 } |
714 | 693 |
715 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; | 694 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; |
716 | 695 |
717 // Check if we accumulated too many frames in encoder input buffers and drop | 696 // Check if we accumulated too many frames in encoder input buffers and drop |
718 // frame if so. | 697 // frame if so. |
719 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { | 698 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { |
720 ALOGD << "Already " << input_frame_infos_.size() | 699 ALOGD << "Already " << input_frame_infos_.size() |
721 << " frames in the queue, dropping" | 700 << " frames in the queue, dropping" |
722 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 701 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
723 << ". Fps: " << last_set_fps_ | 702 << ". Fps: " << last_set_fps_ |
724 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; | 703 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; |
725 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 704 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
726 consecutive_full_queue_frame_drops_++; | 705 consecutive_full_queue_frame_drops_++; |
727 if (consecutive_full_queue_frame_drops_ >= | 706 if (consecutive_full_queue_frame_drops_ >= |
728 ENCODER_STALL_FRAMEDROP_THRESHOLD) { | 707 ENCODER_STALL_FRAMEDROP_THRESHOLD) { |
729 ALOGE << "Encoder got stuck."; | 708 ALOGE << "Encoder got stuck."; |
730 return ProcessHWErrorOnEncodeOnCodecThread(); | 709 return ProcessHWErrorOnEncodeOnCodecThread(); |
731 } | 710 } |
732 frames_dropped_media_encoder_++; | 711 frames_dropped_media_encoder_++; |
733 OnDroppedFrameOnCodecThread(); | |
734 return WEBRTC_VIDEO_CODEC_OK; | 712 return WEBRTC_VIDEO_CODEC_OK; |
735 } | 713 } |
736 consecutive_full_queue_frame_drops_ = 0; | 714 consecutive_full_queue_frame_drops_ = 0; |
737 | 715 |
738 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( | 716 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( |
739 frame.video_frame_buffer()); | 717 frame.video_frame_buffer()); |
740 if (scale_) { | |
741 // Check framerate before spatial resolution change. | |
742 quality_scaler_.OnEncodeFrame(frame.width(), frame.height()); | |
743 const webrtc::QualityScaler::Resolution scaled_resolution = | |
744 quality_scaler_.GetScaledResolution(); | |
745 if (scaled_resolution.width != frame.width() || | |
746 scaled_resolution.height != frame.height()) { | |
747 if (input_buffer->native_handle() != nullptr) { | |
748 input_buffer = static_cast<AndroidTextureBuffer*>(input_buffer.get()) | |
749 ->CropScaleAndRotate(frame.width(), frame.height(), | |
750 0, 0, | |
751 scaled_resolution.width, | |
752 scaled_resolution.height, | |
753 webrtc::kVideoRotation_0); | |
754 } else { | |
755 input_buffer = quality_scaler_.GetScaledBuffer(input_buffer); | |
756 } | |
757 } | |
758 } | |
759 | 718 |
760 VideoFrame input_frame(input_buffer, frame.timestamp(), | 719 VideoFrame input_frame(input_buffer, frame.timestamp(), |
761 frame.render_time_ms(), frame.rotation()); | 720 frame.render_time_ms(), frame.rotation()); |
762 | 721 |
763 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) { | 722 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) { |
764 ALOGE << "Failed to reconfigure encoder."; | 723 ALOGE << "Failed to reconfigure encoder."; |
765 return WEBRTC_VIDEO_CODEC_ERROR; | 724 return WEBRTC_VIDEO_CODEC_ERROR; |
766 } | 725 } |
767 | 726 |
768 const bool key_frame = | 727 const bool key_frame = |
769 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; | 728 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; |
770 bool encode_status = true; | 729 bool encode_status = true; |
771 if (!input_frame.video_frame_buffer()->native_handle()) { | 730 if (!input_frame.video_frame_buffer()->native_handle()) { |
772 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, | 731 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, |
773 j_dequeue_input_buffer_method_); | 732 j_dequeue_input_buffer_method_); |
774 if (CheckException(jni)) { | 733 if (CheckException(jni)) { |
775 ALOGE << "Exception in dequeu input buffer."; | 734 ALOGE << "Exception in dequeu input buffer."; |
776 return ProcessHWErrorOnEncodeOnCodecThread(); | 735 return ProcessHWErrorOnEncodeOnCodecThread(); |
777 } | 736 } |
778 if (j_input_buffer_index == -1) { | 737 if (j_input_buffer_index == -1) { |
779 // Video codec falls behind - no input buffer available. | 738 // Video codec falls behind - no input buffer available. |
780 ALOGW << "Encoder drop frame - no input buffers available"; | 739 ALOGW << "Encoder drop frame - no input buffers available"; |
781 if (frames_received_ > 1) { | 740 if (frames_received_ > 1) { |
782 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 741 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
783 frames_dropped_media_encoder_++; | 742 frames_dropped_media_encoder_++; |
784 OnDroppedFrameOnCodecThread(); | |
785 } else { | 743 } else { |
786 // Input buffers are not ready after codec initialization, HW is still | 744 // Input buffers are not ready after codec initialization, HW is still |
787 // allocating thme - this is expected and should not result in drop | 745 // allocating thme - this is expected and should not result in drop |
788 // frame report. | 746 // frame report. |
789 frames_received_ = 0; | 747 frames_received_ = 0; |
790 } | 748 } |
791 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. | 749 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. |
792 } else if (j_input_buffer_index == -2) { | 750 } else if (j_input_buffer_index == -2) { |
793 return ProcessHWErrorOnEncodeOnCodecThread(); | 751 return ProcessHWErrorOnEncodeOnCodecThread(); |
794 } | 752 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 uint32_t frame_rate) { | 913 uint32_t frame_rate) { |
956 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 914 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
957 if (sw_fallback_required_) | 915 if (sw_fallback_required_) |
958 return WEBRTC_VIDEO_CODEC_OK; | 916 return WEBRTC_VIDEO_CODEC_OK; |
959 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? | 917 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? |
960 frame_rate : MAX_ALLOWED_VIDEO_FPS; | 918 frame_rate : MAX_ALLOWED_VIDEO_FPS; |
961 if (last_set_bitrate_kbps_ == new_bit_rate && | 919 if (last_set_bitrate_kbps_ == new_bit_rate && |
962 last_set_fps_ == frame_rate) { | 920 last_set_fps_ == frame_rate) { |
963 return WEBRTC_VIDEO_CODEC_OK; | 921 return WEBRTC_VIDEO_CODEC_OK; |
964 } | 922 } |
965 if (scale_) { | |
966 quality_scaler_.ReportFramerate(frame_rate); | |
967 } | |
968 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 923 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
969 ScopedLocalRefFrame local_ref_frame(jni); | 924 ScopedLocalRefFrame local_ref_frame(jni); |
970 if (new_bit_rate > 0) { | 925 if (new_bit_rate > 0) { |
971 last_set_bitrate_kbps_ = new_bit_rate; | 926 last_set_bitrate_kbps_ = new_bit_rate; |
972 } | 927 } |
973 if (frame_rate > 0) { | 928 if (frame_rate > 0) { |
974 last_set_fps_ = frame_rate; | 929 last_set_fps_ = frame_rate; |
975 } | 930 } |
976 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, | 931 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, |
977 j_set_rates_method_, | 932 j_set_rates_method_, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 std::unique_ptr<webrtc::EncodedImage> image( | 1024 std::unique_ptr<webrtc::EncodedImage> image( |
1070 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 1025 new webrtc::EncodedImage(payload, payload_size, payload_size)); |
1071 image->_encodedWidth = width_; | 1026 image->_encodedWidth = width_; |
1072 image->_encodedHeight = height_; | 1027 image->_encodedHeight = height_; |
1073 image->_timeStamp = output_timestamp_; | 1028 image->_timeStamp = output_timestamp_; |
1074 image->capture_time_ms_ = output_render_time_ms_; | 1029 image->capture_time_ms_ = output_render_time_ms_; |
1075 image->rotation_ = output_rotation_; | 1030 image->rotation_ = output_rotation_; |
1076 image->_frameType = | 1031 image->_frameType = |
1077 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 1032 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
1078 image->_completeFrame = true; | 1033 image->_completeFrame = true; |
1079 image->adapt_reason_.quality_resolution_downscales = | |
1080 scale_ ? quality_scaler_.downscale_shift() : -1; | |
1081 | |
1082 webrtc::CodecSpecificInfo info; | 1034 webrtc::CodecSpecificInfo info; |
1083 memset(&info, 0, sizeof(info)); | 1035 memset(&info, 0, sizeof(info)); |
1084 info.codecType = codecType_; | 1036 info.codecType = codecType_; |
1085 if (codecType_ == kVideoCodecVP8) { | 1037 if (codecType_ == kVideoCodecVP8) { |
1086 info.codecSpecific.VP8.pictureId = picture_id_; | 1038 info.codecSpecific.VP8.pictureId = picture_id_; |
1087 info.codecSpecific.VP8.nonReference = false; | 1039 info.codecSpecific.VP8.nonReference = false; |
1088 info.codecSpecific.VP8.simulcastIdx = 0; | 1040 info.codecSpecific.VP8.simulcastIdx = 0; |
1089 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; | 1041 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; |
1090 info.codecSpecific.VP8.layerSync = false; | 1042 info.codecSpecific.VP8.layerSync = false; |
1091 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; | 1043 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; |
(...skipping 26 matching lines...) Expand all Loading... |
1118 | 1070 |
1119 // Generate a header describing a single fragment. | 1071 // Generate a header describing a single fragment. |
1120 webrtc::RTPFragmentationHeader header; | 1072 webrtc::RTPFragmentationHeader header; |
1121 memset(&header, 0, sizeof(header)); | 1073 memset(&header, 0, sizeof(header)); |
1122 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { | 1074 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { |
1123 header.VerifyAndAllocateFragmentationHeader(1); | 1075 header.VerifyAndAllocateFragmentationHeader(1); |
1124 header.fragmentationOffset[0] = 0; | 1076 header.fragmentationOffset[0] = 0; |
1125 header.fragmentationLength[0] = image->_length; | 1077 header.fragmentationLength[0] = image->_length; |
1126 header.fragmentationPlType[0] = 0; | 1078 header.fragmentationPlType[0] = 0; |
1127 header.fragmentationTimeDiff[0] = 0; | 1079 header.fragmentationTimeDiff[0] = 0; |
1128 if (codecType_ == kVideoCodecVP8 && scale_) { | 1080 if (codecType_ == kVideoCodecVP8) { |
1129 int qp; | 1081 int qp; |
1130 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { | 1082 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { |
1131 current_acc_qp_ += qp; | 1083 current_acc_qp_ += qp; |
1132 quality_scaler_.ReportQP(qp); | |
1133 image->qp_ = qp; | 1084 image->qp_ = qp; |
1134 } | 1085 } |
1135 } | 1086 } |
1136 } else if (codecType_ == kVideoCodecH264) { | 1087 } else if (codecType_ == kVideoCodecH264) { |
1137 if (scale_) { | 1088 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
1138 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 1089 int qp; |
1139 int qp; | 1090 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
1140 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 1091 current_acc_qp_ += qp; |
1141 current_acc_qp_ += qp; | 1092 image->qp_ = qp; |
1142 quality_scaler_.ReportQP(qp); | |
1143 } | |
1144 } | 1093 } |
1145 // For H.264 search for start codes. | 1094 // For H.264 search for start codes. |
1146 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; | 1095 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; |
1147 int32_t scPositionsLength = 0; | 1096 int32_t scPositionsLength = 0; |
1148 int32_t scPosition = 0; | 1097 int32_t scPosition = 0; |
1149 while (scPositionsLength < MAX_NALUS_PERFRAME) { | 1098 while (scPositionsLength < MAX_NALUS_PERFRAME) { |
1150 int32_t naluPosition = NextNaluPosition( | 1099 int32_t naluPosition = NextNaluPosition( |
1151 payload + scPosition, payload_size - scPosition); | 1100 payload + scPosition, payload_size - scPosition); |
1152 if (naluPosition < 0) { | 1101 if (naluPosition < 0) { |
1153 break; | 1102 break; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 ". QP: " << (current_acc_qp_ / current_frames_divider) << | 1183 ". QP: " << (current_acc_qp_ / current_frames_divider) << |
1235 " for last " << statistic_time_ms << " ms."; | 1184 " for last " << statistic_time_ms << " ms."; |
1236 stat_start_time_ms_ = rtc::TimeMillis(); | 1185 stat_start_time_ms_ = rtc::TimeMillis(); |
1237 current_frames_ = 0; | 1186 current_frames_ = 0; |
1238 current_bytes_ = 0; | 1187 current_bytes_ = 0; |
1239 current_acc_qp_ = 0; | 1188 current_acc_qp_ = 0; |
1240 current_encoding_time_ms_ = 0; | 1189 current_encoding_time_ms_ = 0; |
1241 } | 1190 } |
1242 } | 1191 } |
1243 | 1192 |
| 1193 QualityScaler::Settings MediaCodecVideoEncoder::GetQPThresholds() const { |
| 1194 return QualityScaler::Settings(scale_); |
| 1195 } |
| 1196 |
1244 int32_t MediaCodecVideoEncoder::NextNaluPosition( | 1197 int32_t MediaCodecVideoEncoder::NextNaluPosition( |
1245 uint8_t *buffer, size_t buffer_size) { | 1198 uint8_t *buffer, size_t buffer_size) { |
1246 if (buffer_size < H264_SC_LENGTH) { | 1199 if (buffer_size < H264_SC_LENGTH) { |
1247 return -1; | 1200 return -1; |
1248 } | 1201 } |
1249 uint8_t *head = buffer; | 1202 uint8_t *head = buffer; |
1250 // Set end buffer pointer to 4 bytes before actual buffer end so we can | 1203 // Set end buffer pointer to 4 bytes before actual buffer end so we can |
1251 // access head[1], head[2] and head[3] in a loop without buffer overrun. | 1204 // access head[1], head[2] and head[3] in a loop without buffer overrun. |
1252 uint8_t *end = buffer + buffer_size - H264_SC_LENGTH; | 1205 uint8_t *end = buffer + buffer_size - H264_SC_LENGTH; |
1253 | 1206 |
(...skipping 13 matching lines...) Expand all Loading... |
1267 if (head[3] != 0x01) { // got 000000xx | 1220 if (head[3] != 0x01) { // got 000000xx |
1268 head++; // xx != 1, continue searching. | 1221 head++; // xx != 1, continue searching. |
1269 continue; | 1222 continue; |
1270 } | 1223 } |
1271 return (int32_t)(head - buffer); | 1224 return (int32_t)(head - buffer); |
1272 } | 1225 } |
1273 return -1; | 1226 return -1; |
1274 } | 1227 } |
1275 | 1228 |
1276 void MediaCodecVideoEncoder::OnDroppedFrame() { | 1229 void MediaCodecVideoEncoder::OnDroppedFrame() { |
1277 // Methods running on the codec thread should call OnDroppedFrameOnCodecThread | |
1278 // directly. | |
1279 RTC_DCHECK(!codec_thread_checker_.CalledOnValidThread()); | 1230 RTC_DCHECK(!codec_thread_checker_.CalledOnValidThread()); |
1280 codec_thread_->Invoke<void>( | |
1281 RTC_FROM_HERE, | |
1282 Bind(&MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread, this)); | |
1283 } | |
1284 | |
1285 void MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread() { | |
1286 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | |
1287 // Report dropped frame to quality_scaler_. | |
1288 if (scale_) | |
1289 quality_scaler_.ReportDroppedFrame(); | |
1290 } | 1231 } |
1291 | 1232 |
1292 const char* MediaCodecVideoEncoder::ImplementationName() const { | 1233 const char* MediaCodecVideoEncoder::ImplementationName() const { |
1293 return "MediaCodec"; | 1234 return "MediaCodec"; |
1294 } | 1235 } |
1295 | 1236 |
1296 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() | 1237 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() |
1297 : egl_context_(nullptr) { | 1238 : egl_context_(nullptr) { |
1298 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1239 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
1299 ScopedLocalRefFrame local_ref_frame(jni); | 1240 ScopedLocalRefFrame local_ref_frame(jni); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1370 return supported_codecs_; | 1311 return supported_codecs_; |
1371 } | 1312 } |
1372 | 1313 |
1373 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1314 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1374 webrtc::VideoEncoder* encoder) { | 1315 webrtc::VideoEncoder* encoder) { |
1375 ALOGD << "Destroy video encoder."; | 1316 ALOGD << "Destroy video encoder."; |
1376 delete encoder; | 1317 delete encoder; |
1377 } | 1318 } |
1378 | 1319 |
1379 } // namespace webrtc_jni | 1320 } // namespace webrtc_jni |
OLD | NEW |