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 13 matching lines...) Expand all Loading... | |
24 #include "webrtc/api/android/jni/native_handle_impl.h" | 24 #include "webrtc/api/android/jni/native_handle_impl.h" |
25 #include "webrtc/base/bind.h" | 25 #include "webrtc/base/bind.h" |
26 #include "webrtc/base/checks.h" | 26 #include "webrtc/base/checks.h" |
27 #include "webrtc/base/logging.h" | 27 #include "webrtc/base/logging.h" |
28 #include "webrtc/base/thread.h" | 28 #include "webrtc/base/thread.h" |
29 #include "webrtc/base/thread_checker.h" | 29 #include "webrtc/base/thread_checker.h" |
30 #include "webrtc/base/timeutils.h" | 30 #include "webrtc/base/timeutils.h" |
31 #include "webrtc/common_types.h" | 31 #include "webrtc/common_types.h" |
32 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 32 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
33 #include "webrtc/modules/video_coding/utility/h264_bitstream_parser.h" | 33 #include "webrtc/modules/video_coding/utility/h264_bitstream_parser.h" |
34 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | |
magjed_webrtc
2016/10/26 14:28:36
nit: revert this change. It was right before.
kthelgason
2016/10/26 19:02:49
Alphabet is hard :(
| |
34 #include "webrtc/modules/video_coding/utility/quality_scaler.h" | 35 #include "webrtc/modules/video_coding/utility/quality_scaler.h" |
35 #include "webrtc/modules/video_coding/utility/vp8_header_parser.h" | |
36 #include "webrtc/system_wrappers/include/field_trial.h" | 36 #include "webrtc/system_wrappers/include/field_trial.h" |
37 #include "webrtc/system_wrappers/include/logcat_trace_context.h" | 37 #include "webrtc/system_wrappers/include/logcat_trace_context.h" |
38 | 38 |
39 using rtc::Bind; | 39 using rtc::Bind; |
40 using rtc::Thread; | 40 using rtc::Thread; |
41 using rtc::ThreadManager; | 41 using rtc::ThreadManager; |
42 | 42 |
43 using webrtc::CodecSpecificInfo; | 43 using webrtc::CodecSpecificInfo; |
44 using webrtc::EncodedImage; | 44 using webrtc::EncodedImage; |
45 using webrtc::VideoFrame; | 45 using webrtc::VideoFrame; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 const int64_t frame_input_time_ms); | 149 const int64_t frame_input_time_ms); |
150 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, | 150 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, |
151 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); | 151 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); |
152 bool EncodeTextureOnCodecThread(JNIEnv* jni, | 152 bool EncodeTextureOnCodecThread(JNIEnv* jni, |
153 bool key_frame, const webrtc::VideoFrame& frame); | 153 bool key_frame, const webrtc::VideoFrame& frame); |
154 | 154 |
155 int32_t RegisterEncodeCompleteCallbackOnCodecThread( | 155 int32_t RegisterEncodeCompleteCallbackOnCodecThread( |
156 webrtc::EncodedImageCallback* callback); | 156 webrtc::EncodedImageCallback* callback); |
157 int32_t ReleaseOnCodecThread(); | 157 int32_t ReleaseOnCodecThread(); |
158 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate); | 158 int32_t SetRatesOnCodecThread(uint32_t new_bit_rate, uint32_t frame_rate); |
159 void OnDroppedFrameOnCodecThread(); | |
160 | 159 |
161 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. | 160 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. |
162 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); | 161 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); |
163 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); | 162 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); |
164 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); | 163 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); |
165 jlong GetOutputBufferInfoPresentationTimestampUs( | 164 jlong GetOutputBufferInfoPresentationTimestampUs( |
166 JNIEnv* jni, jobject j_output_buffer_info); | 165 JNIEnv* jni, jobject j_output_buffer_info); |
167 | 166 |
168 // Deliver any outputs pending in the MediaCodec to our |callback_| and return | 167 // Deliver any outputs pending in the MediaCodec to our |callback_| and return |
169 // true on success. | 168 // true on success. |
170 bool DeliverPendingOutputs(JNIEnv* jni); | 169 bool DeliverPendingOutputs(JNIEnv* jni); |
171 | 170 |
172 // Search for H.264 start codes. | 171 // Search for H.264 start codes. |
173 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); | 172 int32_t NextNaluPosition(uint8_t *buffer, size_t buffer_size); |
174 | 173 |
174 QualityScaler::Settings GetQPThresholds() const override; | |
175 | |
175 // Displays encoder statistics. | 176 // Displays encoder statistics. |
176 void LogStatistics(bool force_log); | 177 void LogStatistics(bool force_log); |
177 | 178 |
178 // Type of video codec. | 179 // Type of video codec. |
179 VideoCodecType codecType_; | 180 VideoCodecType codecType_; |
180 | 181 |
181 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to | 182 // Valid all the time since RegisterEncodeCompleteCallback() Invoke()s to |
182 // |codec_thread_| synchronously. | 183 // |codec_thread_| synchronously. |
183 webrtc::EncodedImageCallback* callback_; | 184 webrtc::EncodedImageCallback* callback_; |
184 | 185 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 // |input_frame_infos_|. | 251 // |input_frame_infos_|. |
251 int64_t output_render_time_ms_; // Last output frame render time from | 252 int64_t output_render_time_ms_; // Last output frame render time from |
252 // |input_frame_infos_|. | 253 // |input_frame_infos_|. |
253 webrtc::VideoRotation output_rotation_; // Last output frame rotation from | 254 webrtc::VideoRotation output_rotation_; // Last output frame rotation from |
254 // |input_frame_infos_|. | 255 // |input_frame_infos_|. |
255 // Frame size in bytes fed to MediaCodec. | 256 // Frame size in bytes fed to MediaCodec. |
256 int yuv_size_; | 257 int yuv_size_; |
257 // True only when between a callback_->Encoded() call return a positive value | 258 // True only when between a callback_->Encoded() call return a positive value |
258 // and the next Encode() call being ignored. | 259 // and the next Encode() call being ignored. |
259 bool drop_next_input_frame_; | 260 bool drop_next_input_frame_; |
261 bool scale_; | |
260 // Global references; must be deleted in Release(). | 262 // Global references; must be deleted in Release(). |
261 std::vector<jobject> input_buffers_; | 263 std::vector<jobject> input_buffers_; |
262 QualityScaler quality_scaler_; | |
263 // Dynamic resolution change, off by default. | |
264 bool scale_; | |
265 | |
266 // H264 bitstream parser, used to extract QP from encoded bitstreams. | |
267 webrtc::H264BitstreamParser h264_bitstream_parser_; | 264 webrtc::H264BitstreamParser h264_bitstream_parser_; |
268 | 265 |
269 // VP9 variables to populate codec specific structure. | 266 // VP9 variables to populate codec specific structure. |
270 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for | 267 webrtc::GofInfoVP9 gof_; // Contains each frame's temporal information for |
271 // non-flexible VP9 mode. | 268 // non-flexible VP9 mode. |
272 uint8_t tl0_pic_idx_; | 269 uint8_t tl0_pic_idx_; |
273 size_t gof_idx_; | 270 size_t gof_idx_; |
274 | 271 |
275 // EGL context - owned by factory, should not be allocated/destroyed | 272 // EGL context - owned by factory, should not be allocated/destroyed |
276 // by MediaCodecVideoEncoder. | 273 // by MediaCodecVideoEncoder. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 if (codec_settings == NULL) { | 370 if (codec_settings == NULL) { |
374 ALOGE << "NULL VideoCodec instance"; | 371 ALOGE << "NULL VideoCodec instance"; |
375 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 372 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
376 } | 373 } |
377 // Factory should guard against other codecs being used with us. | 374 // Factory should guard against other codecs being used with us. |
378 RTC_CHECK(codec_settings->codecType == codecType_) | 375 RTC_CHECK(codec_settings->codecType == codecType_) |
379 << "Unsupported codec " << codec_settings->codecType << " for " | 376 << "Unsupported codec " << codec_settings->codecType << " for " |
380 << codecType_; | 377 << codecType_; |
381 | 378 |
382 codec_mode_ = codec_settings->mode; | 379 codec_mode_ = codec_settings->mode; |
380 scale_ = | |
381 codecType_ == (kVideoCodecVP8 && | |
magjed_webrtc
2016/10/26 14:28:36
The parentheses are misplaced so it's doing someth
kthelgason
2016/10/26 19:02:49
Oops. good catch, thanks. I've replaced it to the
| |
382 codec_settings->codecSpecific.VP8.automaticResizeOn) || | |
383 codecType_ != kVideoCodecVP9; | |
383 int init_width = codec_settings->width; | 384 int init_width = codec_settings->width; |
384 int init_height = codec_settings->height; | 385 int init_height = codec_settings->height; |
385 // Scaling is disabled for VP9, but optionally enabled for VP8. | |
386 // TODO(pbos): Extract automaticResizeOn out of VP8 settings. | |
387 scale_ = false; | |
388 if (codecType_ == kVideoCodecVP8) { | |
389 scale_ = codec_settings->codecSpecific.VP8.automaticResizeOn; | |
390 } else if (codecType_ != kVideoCodecVP9) { | |
391 scale_ = true; | |
392 } | |
393 | |
394 ALOGD << "InitEncode request: " << init_width << " x " << init_height; | 386 ALOGD << "InitEncode request: " << init_width << " x " << init_height; |
395 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | |
396 | |
397 if (scale_) { | |
398 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264) { | |
399 quality_scaler_.Init(codecType_, codec_settings->startBitrate, | |
400 codec_settings->width, codec_settings->height, | |
401 codec_settings->maxFramerate); | |
402 } else { | |
403 // When adding codec support to additional hardware codecs, also configure | |
404 // their QP thresholds for scaling. | |
405 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | |
406 scale_ = false; | |
407 } | |
408 QualityScaler::Resolution res = quality_scaler_.GetScaledResolution(); | |
409 init_width = res.width; | |
410 init_height = res.height; | |
411 ALOGD << "Scaled resolution: " << init_width << " x " << init_height; | |
412 } | |
413 | 387 |
414 return codec_thread_->Invoke<int32_t>( | 388 return codec_thread_->Invoke<int32_t>( |
415 RTC_FROM_HERE, | 389 RTC_FROM_HERE, |
416 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, this, init_width, | 390 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, this, init_width, |
417 init_height, codec_settings->startBitrate, | 391 init_height, codec_settings->startBitrate, |
418 codec_settings->maxFramerate, | 392 codec_settings->maxFramerate, |
419 codec_settings->expect_encode_from_texture)); | 393 codec_settings->expect_encode_from_texture)); |
420 } | 394 } |
421 | 395 |
422 int32_t MediaCodecVideoEncoder::Encode( | 396 int32_t MediaCodecVideoEncoder::Encode( |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
637 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 611 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
638 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ | 612 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ |
639 << ". Kbps: " << last_set_bitrate_kbps_; | 613 << ". Kbps: " << last_set_bitrate_kbps_; |
640 } | 614 } |
641 | 615 |
642 if (drop_next_input_frame_) { | 616 if (drop_next_input_frame_) { |
643 ALOGW << "Encoder drop frame - failed callback."; | 617 ALOGW << "Encoder drop frame - failed callback."; |
644 drop_next_input_frame_ = false; | 618 drop_next_input_frame_ = false; |
645 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 619 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
646 frames_dropped_media_encoder_++; | 620 frames_dropped_media_encoder_++; |
647 OnDroppedFrameOnCodecThread(); | |
648 return WEBRTC_VIDEO_CODEC_OK; | 621 return WEBRTC_VIDEO_CODEC_OK; |
649 } | 622 } |
650 | 623 |
651 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; | 624 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; |
652 | 625 |
653 // Check if we accumulated too many frames in encoder input buffers and drop | 626 // Check if we accumulated too many frames in encoder input buffers and drop |
654 // frame if so. | 627 // frame if so. |
655 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { | 628 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { |
656 ALOGD << "Already " << input_frame_infos_.size() | 629 ALOGD << "Already " << input_frame_infos_.size() |
657 << " frames in the queue, dropping" | 630 << " frames in the queue, dropping" |
658 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 631 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
659 << ". Fps: " << last_set_fps_ | 632 << ". Fps: " << last_set_fps_ |
660 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; | 633 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; |
661 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 634 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
662 consecutive_full_queue_frame_drops_++; | 635 consecutive_full_queue_frame_drops_++; |
663 if (consecutive_full_queue_frame_drops_ >= | 636 if (consecutive_full_queue_frame_drops_ >= |
664 ENCODER_STALL_FRAMEDROP_THRESHOLD) { | 637 ENCODER_STALL_FRAMEDROP_THRESHOLD) { |
665 ALOGE << "Encoder got stuck. Reset."; | 638 ALOGE << "Encoder got stuck. Reset."; |
666 ResetCodecOnCodecThread(); | 639 ResetCodecOnCodecThread(); |
667 return WEBRTC_VIDEO_CODEC_ERROR; | 640 return WEBRTC_VIDEO_CODEC_ERROR; |
668 } | 641 } |
669 frames_dropped_media_encoder_++; | 642 frames_dropped_media_encoder_++; |
670 OnDroppedFrameOnCodecThread(); | |
671 return WEBRTC_VIDEO_CODEC_OK; | 643 return WEBRTC_VIDEO_CODEC_OK; |
672 } | 644 } |
673 consecutive_full_queue_frame_drops_ = 0; | 645 consecutive_full_queue_frame_drops_ = 0; |
674 | 646 |
675 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( | 647 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( |
676 frame.video_frame_buffer()); | 648 frame.video_frame_buffer()); |
677 if (scale_) { | |
678 // Check framerate before spatial resolution change. | |
679 quality_scaler_.OnEncodeFrame(frame.width(), frame.height()); | |
680 const webrtc::QualityScaler::Resolution scaled_resolution = | |
681 quality_scaler_.GetScaledResolution(); | |
682 if (scaled_resolution.width != frame.width() || | |
683 scaled_resolution.height != frame.height()) { | |
684 if (input_buffer->native_handle() != nullptr) { | |
685 input_buffer = static_cast<AndroidTextureBuffer*>(input_buffer.get()) | |
686 ->CropScaleAndRotate(frame.width(), frame.height(), | |
687 0, 0, | |
688 scaled_resolution.width, | |
689 scaled_resolution.height, | |
690 webrtc::kVideoRotation_0); | |
691 } else { | |
692 input_buffer = quality_scaler_.GetScaledBuffer(input_buffer); | |
693 } | |
694 } | |
695 } | |
696 | 649 |
697 VideoFrame input_frame(input_buffer, frame.timestamp(), | 650 VideoFrame input_frame(input_buffer, frame.timestamp(), |
698 frame.render_time_ms(), frame.rotation()); | 651 frame.render_time_ms(), frame.rotation()); |
699 | 652 |
700 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) { | 653 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) { |
701 ALOGE << "Failed to reconfigure encoder."; | 654 ALOGE << "Failed to reconfigure encoder."; |
702 return WEBRTC_VIDEO_CODEC_ERROR; | 655 return WEBRTC_VIDEO_CODEC_ERROR; |
703 } | 656 } |
704 | 657 |
705 const bool key_frame = | 658 const bool key_frame = |
706 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; | 659 frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame; |
707 bool encode_status = true; | 660 bool encode_status = true; |
708 if (!input_frame.video_frame_buffer()->native_handle()) { | 661 if (!input_frame.video_frame_buffer()->native_handle()) { |
709 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, | 662 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, |
710 j_dequeue_input_buffer_method_); | 663 j_dequeue_input_buffer_method_); |
711 CHECK_EXCEPTION(jni); | 664 CHECK_EXCEPTION(jni); |
712 if (j_input_buffer_index == -1) { | 665 if (j_input_buffer_index == -1) { |
713 // Video codec falls behind - no input buffer available. | 666 // Video codec falls behind - no input buffer available. |
714 ALOGW << "Encoder drop frame - no input buffers available"; | 667 ALOGW << "Encoder drop frame - no input buffers available"; |
715 if (frames_received_ > 1) { | 668 if (frames_received_ > 1) { |
716 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 669 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
717 frames_dropped_media_encoder_++; | 670 frames_dropped_media_encoder_++; |
718 OnDroppedFrameOnCodecThread(); | |
719 } else { | 671 } else { |
720 // Input buffers are not ready after codec initialization, HW is still | 672 // Input buffers are not ready after codec initialization, HW is still |
721 // allocating thme - this is expected and should not result in drop | 673 // allocating thme - this is expected and should not result in drop |
722 // frame report. | 674 // frame report. |
723 frames_received_ = 0; | 675 frames_received_ = 0; |
724 } | 676 } |
725 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. | 677 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. |
726 } else if (j_input_buffer_index == -2) { | 678 } else if (j_input_buffer_index == -2) { |
727 ResetCodecOnCodecThread(); | 679 ResetCodecOnCodecThread(); |
728 return WEBRTC_VIDEO_CODEC_ERROR; | 680 return WEBRTC_VIDEO_CODEC_ERROR; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
875 | 827 |
876 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, | 828 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, |
877 uint32_t frame_rate) { | 829 uint32_t frame_rate) { |
878 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 830 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
879 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? | 831 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? |
880 frame_rate : MAX_ALLOWED_VIDEO_FPS; | 832 frame_rate : MAX_ALLOWED_VIDEO_FPS; |
881 if (last_set_bitrate_kbps_ == new_bit_rate && | 833 if (last_set_bitrate_kbps_ == new_bit_rate && |
882 last_set_fps_ == frame_rate) { | 834 last_set_fps_ == frame_rate) { |
883 return WEBRTC_VIDEO_CODEC_OK; | 835 return WEBRTC_VIDEO_CODEC_OK; |
884 } | 836 } |
885 if (scale_) { | |
886 quality_scaler_.ReportFramerate(frame_rate); | |
887 } | |
888 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 837 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
889 ScopedLocalRefFrame local_ref_frame(jni); | 838 ScopedLocalRefFrame local_ref_frame(jni); |
890 if (new_bit_rate > 0) { | 839 if (new_bit_rate > 0) { |
891 last_set_bitrate_kbps_ = new_bit_rate; | 840 last_set_bitrate_kbps_ = new_bit_rate; |
892 } | 841 } |
893 if (frame_rate > 0) { | 842 if (frame_rate > 0) { |
894 last_set_fps_ = frame_rate; | 843 last_set_fps_ = frame_rate; |
895 } | 844 } |
896 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, | 845 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, |
897 j_set_rates_method_, | 846 j_set_rates_method_, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
980 std::unique_ptr<webrtc::EncodedImage> image( | 929 std::unique_ptr<webrtc::EncodedImage> image( |
981 new webrtc::EncodedImage(payload, payload_size, payload_size)); | 930 new webrtc::EncodedImage(payload, payload_size, payload_size)); |
982 image->_encodedWidth = width_; | 931 image->_encodedWidth = width_; |
983 image->_encodedHeight = height_; | 932 image->_encodedHeight = height_; |
984 image->_timeStamp = output_timestamp_; | 933 image->_timeStamp = output_timestamp_; |
985 image->capture_time_ms_ = output_render_time_ms_; | 934 image->capture_time_ms_ = output_render_time_ms_; |
986 image->rotation_ = output_rotation_; | 935 image->rotation_ = output_rotation_; |
987 image->_frameType = | 936 image->_frameType = |
988 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); | 937 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); |
989 image->_completeFrame = true; | 938 image->_completeFrame = true; |
990 image->adapt_reason_.quality_resolution_downscales = | |
991 scale_ ? quality_scaler_.downscale_shift() : -1; | |
992 | |
993 webrtc::CodecSpecificInfo info; | 939 webrtc::CodecSpecificInfo info; |
994 memset(&info, 0, sizeof(info)); | 940 memset(&info, 0, sizeof(info)); |
995 info.codecType = codecType_; | 941 info.codecType = codecType_; |
996 if (codecType_ == kVideoCodecVP8) { | 942 if (codecType_ == kVideoCodecVP8) { |
997 info.codecSpecific.VP8.pictureId = picture_id_; | 943 info.codecSpecific.VP8.pictureId = picture_id_; |
998 info.codecSpecific.VP8.nonReference = false; | 944 info.codecSpecific.VP8.nonReference = false; |
999 info.codecSpecific.VP8.simulcastIdx = 0; | 945 info.codecSpecific.VP8.simulcastIdx = 0; |
1000 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; | 946 info.codecSpecific.VP8.temporalIdx = webrtc::kNoTemporalIdx; |
1001 info.codecSpecific.VP8.layerSync = false; | 947 info.codecSpecific.VP8.layerSync = false; |
1002 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; | 948 info.codecSpecific.VP8.tl0PicIdx = webrtc::kNoTl0PicIdx; |
(...skipping 26 matching lines...) Expand all Loading... | |
1029 | 975 |
1030 // Generate a header describing a single fragment. | 976 // Generate a header describing a single fragment. |
1031 webrtc::RTPFragmentationHeader header; | 977 webrtc::RTPFragmentationHeader header; |
1032 memset(&header, 0, sizeof(header)); | 978 memset(&header, 0, sizeof(header)); |
1033 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { | 979 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { |
1034 header.VerifyAndAllocateFragmentationHeader(1); | 980 header.VerifyAndAllocateFragmentationHeader(1); |
1035 header.fragmentationOffset[0] = 0; | 981 header.fragmentationOffset[0] = 0; |
1036 header.fragmentationLength[0] = image->_length; | 982 header.fragmentationLength[0] = image->_length; |
1037 header.fragmentationPlType[0] = 0; | 983 header.fragmentationPlType[0] = 0; |
1038 header.fragmentationTimeDiff[0] = 0; | 984 header.fragmentationTimeDiff[0] = 0; |
1039 if (codecType_ == kVideoCodecVP8 && scale_) { | 985 if (codecType_ == kVideoCodecVP8) { |
1040 int qp; | 986 int qp; |
1041 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { | 987 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) { |
1042 current_acc_qp_ += qp; | 988 current_acc_qp_ += qp; |
1043 quality_scaler_.ReportQP(qp); | |
1044 image->qp_ = qp; | 989 image->qp_ = qp; |
1045 } | 990 } |
1046 } | 991 } |
1047 } else if (codecType_ == kVideoCodecH264) { | 992 } else if (codecType_ == kVideoCodecH264) { |
1048 if (scale_) { | 993 h264_bitstream_parser_.ParseBitstream(payload, payload_size); |
1049 h264_bitstream_parser_.ParseBitstream(payload, payload_size); | 994 int qp; |
1050 int qp; | 995 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { |
1051 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | 996 current_acc_qp_ += qp; |
1052 current_acc_qp_ += qp; | 997 image->qp_ = qp; |
1053 quality_scaler_.ReportQP(qp); | |
1054 } | |
1055 } | 998 } |
1056 // For H.264 search for start codes. | 999 // For H.264 search for start codes. |
1057 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; | 1000 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; |
1058 int32_t scPositionsLength = 0; | 1001 int32_t scPositionsLength = 0; |
1059 int32_t scPosition = 0; | 1002 int32_t scPosition = 0; |
1060 while (scPositionsLength < MAX_NALUS_PERFRAME) { | 1003 while (scPositionsLength < MAX_NALUS_PERFRAME) { |
1061 int32_t naluPosition = NextNaluPosition( | 1004 int32_t naluPosition = NextNaluPosition( |
1062 payload + scPosition, payload_size - scPosition); | 1005 payload + scPosition, payload_size - scPosition); |
1063 if (naluPosition < 0) { | 1006 if (naluPosition < 0) { |
1064 break; | 1007 break; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1148 ". QP: " << (current_acc_qp_ / current_frames_divider) << | 1091 ". QP: " << (current_acc_qp_ / current_frames_divider) << |
1149 " for last " << statistic_time_ms << " ms."; | 1092 " for last " << statistic_time_ms << " ms."; |
1150 stat_start_time_ms_ = rtc::TimeMillis(); | 1093 stat_start_time_ms_ = rtc::TimeMillis(); |
1151 current_frames_ = 0; | 1094 current_frames_ = 0; |
1152 current_bytes_ = 0; | 1095 current_bytes_ = 0; |
1153 current_acc_qp_ = 0; | 1096 current_acc_qp_ = 0; |
1154 current_encoding_time_ms_ = 0; | 1097 current_encoding_time_ms_ = 0; |
1155 } | 1098 } |
1156 } | 1099 } |
1157 | 1100 |
1101 QualityScaler::Settings MediaCodecVideoEncoder::GetQPThresholds() const { | |
1102 return QualityScaler::Settings(scale_); | |
1103 } | |
1104 | |
1158 int32_t MediaCodecVideoEncoder::NextNaluPosition( | 1105 int32_t MediaCodecVideoEncoder::NextNaluPosition( |
1159 uint8_t *buffer, size_t buffer_size) { | 1106 uint8_t *buffer, size_t buffer_size) { |
1160 if (buffer_size < H264_SC_LENGTH) { | 1107 if (buffer_size < H264_SC_LENGTH) { |
1161 return -1; | 1108 return -1; |
1162 } | 1109 } |
1163 uint8_t *head = buffer; | 1110 uint8_t *head = buffer; |
1164 // Set end buffer pointer to 4 bytes before actual buffer end so we can | 1111 // Set end buffer pointer to 4 bytes before actual buffer end so we can |
1165 // access head[1], head[2] and head[3] in a loop without buffer overrun. | 1112 // access head[1], head[2] and head[3] in a loop without buffer overrun. |
1166 uint8_t *end = buffer + buffer_size - H264_SC_LENGTH; | 1113 uint8_t *end = buffer + buffer_size - H264_SC_LENGTH; |
1167 | 1114 |
(...skipping 13 matching lines...) Expand all Loading... | |
1181 if (head[3] != 0x01) { // got 000000xx | 1128 if (head[3] != 0x01) { // got 000000xx |
1182 head++; // xx != 1, continue searching. | 1129 head++; // xx != 1, continue searching. |
1183 continue; | 1130 continue; |
1184 } | 1131 } |
1185 return (int32_t)(head - buffer); | 1132 return (int32_t)(head - buffer); |
1186 } | 1133 } |
1187 return -1; | 1134 return -1; |
1188 } | 1135 } |
1189 | 1136 |
1190 void MediaCodecVideoEncoder::OnDroppedFrame() { | 1137 void MediaCodecVideoEncoder::OnDroppedFrame() { |
1191 // Methods running on the codec thread should call OnDroppedFrameOnCodecThread | |
1192 // directly. | |
1193 RTC_DCHECK(!codec_thread_checker_.CalledOnValidThread()); | 1138 RTC_DCHECK(!codec_thread_checker_.CalledOnValidThread()); |
1194 codec_thread_->Invoke<void>( | |
1195 RTC_FROM_HERE, | |
1196 Bind(&MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread, this)); | |
1197 } | |
1198 | |
1199 void MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread() { | |
1200 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | |
1201 // Report dropped frame to quality_scaler_. | |
1202 if (scale_) | |
1203 quality_scaler_.ReportDroppedFrame(); | |
1204 } | 1139 } |
1205 | 1140 |
1206 const char* MediaCodecVideoEncoder::ImplementationName() const { | 1141 const char* MediaCodecVideoEncoder::ImplementationName() const { |
1207 return "MediaCodec"; | 1142 return "MediaCodec"; |
1208 } | 1143 } |
1209 | 1144 |
1210 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() | 1145 MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() |
1211 : egl_context_(nullptr) { | 1146 : egl_context_(nullptr) { |
1212 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 1147 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
1213 ScopedLocalRefFrame local_ref_frame(jni); | 1148 ScopedLocalRefFrame local_ref_frame(jni); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1290 return supported_codecs_; | 1225 return supported_codecs_; |
1291 } | 1226 } |
1292 | 1227 |
1293 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1228 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1294 webrtc::VideoEncoder* encoder) { | 1229 webrtc::VideoEncoder* encoder) { |
1295 ALOGD << "Destroy video encoder."; | 1230 ALOGD << "Destroy video encoder."; |
1296 delete encoder; | 1231 delete encoder; |
1297 } | 1232 } |
1298 | 1233 |
1299 } // namespace webrtc_jni | 1234 } // namespace webrtc_jni |
OLD | NEW |