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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 void OnMessage(rtc::Message* msg) override; | 120 void OnMessage(rtc::Message* msg) override; |
121 | 121 |
122 void OnDroppedFrame() override; | 122 void OnDroppedFrame() override; |
123 | 123 |
124 int GetTargetFramerate() override; | 124 int GetTargetFramerate() override; |
125 | 125 |
126 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; } | 126 bool SupportsNativeHandle() const override { return egl_context_ != nullptr; } |
127 const char* ImplementationName() const override; | 127 const char* ImplementationName() const override; |
128 | 128 |
129 private: | 129 private: |
130 // CHECK-fail if not running on |codec_thread_|. | |
131 void CheckOnCodecThread(); | |
132 | |
133 private: | |
134 // ResetCodecOnCodecThread() calls ReleaseOnCodecThread() and | 130 // ResetCodecOnCodecThread() calls ReleaseOnCodecThread() and |
135 // InitEncodeOnCodecThread() in an attempt to restore the codec to an | 131 // InitEncodeOnCodecThread() in an attempt to restore the codec to an |
136 // operable state. Necessary after all manner of OMX-layer errors. | 132 // operable state. Necessary after all manner of OMX-layer errors. |
137 bool ResetCodecOnCodecThread(); | 133 bool ResetCodecOnCodecThread(); |
138 | 134 |
139 // Implementation of webrtc::VideoEncoder methods above, all running on the | 135 // Implementation of webrtc::VideoEncoder methods above, all running on the |
140 // codec thread exclusively. | 136 // codec thread exclusively. |
141 // | 137 // |
142 // If width==0 then this is assumed to be a re-initialization and the | 138 // If width==0 then this is assumed to be a re-initialization and the |
143 // previously-current values are reused instead of the passed parameters | 139 // previously-current values are reused instead of the passed parameters |
144 // (makes it easier to reason about thread-safety). | 140 // (makes it easier to reason about thread-safety). |
145 int32_t InitEncodeOnCodecThread(int width, int height, int kbps, int fps, | 141 int32_t InitEncodeOnCodecThread(int width, int height, int kbps, int fps, |
146 bool use_surface); | 142 bool use_surface); |
147 // Reconfigure to match |frame| in width, height. Also reconfigures the | 143 // Reconfigure to match |frame| in width, height. Also reconfigures the |
148 // encoder if |frame| is a texture/byte buffer and the encoder is initialized | 144 // encoder if |frame| is a texture/byte buffer and the encoder is initialized |
149 // for byte buffer/texture. Returns false if reconfiguring fails. | 145 // for byte buffer/texture. Returns false if reconfiguring fails. |
150 bool MaybeReconfigureEncoderOnCodecThread(const webrtc::VideoFrame& frame); | 146 bool MaybeReconfigureEncoderOnCodecThread(const webrtc::VideoFrame& frame); |
151 int32_t EncodeOnCodecThread( | 147 int32_t EncodeOnCodecThread( |
152 const webrtc::VideoFrame& input_image, | 148 const webrtc::VideoFrame& input_image, |
153 const std::vector<webrtc::FrameType>* frame_types); | 149 const std::vector<webrtc::FrameType>* frame_types); |
154 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, | 150 bool EncodeByteBufferOnCodecThread(JNIEnv* jni, |
155 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); | 151 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index); |
156 bool EncodeTextureOnCodecThread(JNIEnv* jni, | 152 bool EncodeTextureOnCodecThread(JNIEnv* jni, |
157 bool key_frame, const webrtc::VideoFrame& frame); | 153 bool key_frame, const webrtc::VideoFrame& frame); |
158 | 154 |
159 int32_t RegisterEncodeCompleteCallbackOnCodecThread( | 155 int32_t RegisterEncodeCompleteCallbackOnCodecThread( |
160 webrtc::EncodedImageCallback* callback); | 156 webrtc::EncodedImageCallback* callback); |
161 int32_t ReleaseOnCodecThread(); | 157 int32_t ReleaseOnCodecThread(); |
162 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(); |
163 | 160 |
164 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. | 161 // Helper accessors for MediaCodecVideoEncoder$OutputBufferInfo members. |
165 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); | 162 int GetOutputBufferInfoIndex(JNIEnv* jni, jobject j_output_buffer_info); |
166 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); | 163 jobject GetOutputBufferInfoBuffer(JNIEnv* jni, jobject j_output_buffer_info); |
167 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); | 164 bool GetOutputBufferInfoIsKeyFrame(JNIEnv* jni, jobject j_output_buffer_info); |
168 jlong GetOutputBufferInfoPresentationTimestampUs( | 165 jlong GetOutputBufferInfoPresentationTimestampUs( |
169 JNIEnv* jni, jobject j_output_buffer_info); | 166 JNIEnv* jni, jobject j_output_buffer_info); |
170 | 167 |
171 // Deliver any outputs pending in the MediaCodec to our |callback_| and return | 168 // Deliver any outputs pending in the MediaCodec to our |callback_| and return |
172 // true on success. | 169 // true on success. |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 637 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
641 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ | 638 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ |
642 << ". Kbps: " << last_set_bitrate_kbps_; | 639 << ". Kbps: " << last_set_bitrate_kbps_; |
643 } | 640 } |
644 | 641 |
645 if (drop_next_input_frame_) { | 642 if (drop_next_input_frame_) { |
646 ALOGW << "Encoder drop frame - failed callback."; | 643 ALOGW << "Encoder drop frame - failed callback."; |
647 drop_next_input_frame_ = false; | 644 drop_next_input_frame_ = false; |
648 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 645 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
649 frames_dropped_media_encoder_++; | 646 frames_dropped_media_encoder_++; |
650 OnDroppedFrame(); | 647 OnDroppedFrameOnCodecThread(); |
651 return WEBRTC_VIDEO_CODEC_OK; | 648 return WEBRTC_VIDEO_CODEC_OK; |
652 } | 649 } |
653 | 650 |
654 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; | 651 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; |
655 | 652 |
656 // Check if we accumulated too many frames in encoder input buffers and drop | 653 // Check if we accumulated too many frames in encoder input buffers and drop |
657 // frame if so. | 654 // frame if so. |
658 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { | 655 if (input_frame_infos_.size() > MAX_ENCODER_Q_SIZE) { |
659 ALOGD << "Already " << input_frame_infos_.size() | 656 ALOGD << "Already " << input_frame_infos_.size() |
660 << " frames in the queue, dropping" | 657 << " frames in the queue, dropping" |
661 << ". TS: " << (int)(current_timestamp_us_ / 1000) | 658 << ". TS: " << (int)(current_timestamp_us_ / 1000) |
662 << ". Fps: " << last_set_fps_ | 659 << ". Fps: " << last_set_fps_ |
663 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; | 660 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; |
664 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 661 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
665 consecutive_full_queue_frame_drops_++; | 662 consecutive_full_queue_frame_drops_++; |
666 if (consecutive_full_queue_frame_drops_ >= | 663 if (consecutive_full_queue_frame_drops_ >= |
667 ENCODER_STALL_FRAMEDROP_THRESHOLD) { | 664 ENCODER_STALL_FRAMEDROP_THRESHOLD) { |
668 ALOGE << "Encoder got stuck. Reset."; | 665 ALOGE << "Encoder got stuck. Reset."; |
669 ResetCodecOnCodecThread(); | 666 ResetCodecOnCodecThread(); |
670 return WEBRTC_VIDEO_CODEC_ERROR; | 667 return WEBRTC_VIDEO_CODEC_ERROR; |
671 } | 668 } |
672 frames_dropped_media_encoder_++; | 669 frames_dropped_media_encoder_++; |
673 OnDroppedFrame(); | 670 OnDroppedFrameOnCodecThread(); |
674 return WEBRTC_VIDEO_CODEC_OK; | 671 return WEBRTC_VIDEO_CODEC_OK; |
675 } | 672 } |
676 consecutive_full_queue_frame_drops_ = 0; | 673 consecutive_full_queue_frame_drops_ = 0; |
677 | 674 |
678 VideoFrame input_frame = frame; | 675 VideoFrame input_frame = frame; |
679 if (scale_) { | 676 if (scale_) { |
680 // Check framerate before spatial resolution change. | 677 // Check framerate before spatial resolution change. |
681 quality_scaler_.OnEncodeFrame(frame); | 678 quality_scaler_.OnEncodeFrame(frame); |
682 const webrtc::QualityScaler::Resolution scaled_resolution = | 679 const webrtc::QualityScaler::Resolution scaled_resolution = |
683 quality_scaler_.GetScaledResolution(); | 680 quality_scaler_.GetScaledResolution(); |
(...skipping 24 matching lines...) Expand all Loading... |
708 bool encode_status = true; | 705 bool encode_status = true; |
709 if (!input_frame.video_frame_buffer()->native_handle()) { | 706 if (!input_frame.video_frame_buffer()->native_handle()) { |
710 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, | 707 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, |
711 j_dequeue_input_buffer_method_); | 708 j_dequeue_input_buffer_method_); |
712 CHECK_EXCEPTION(jni); | 709 CHECK_EXCEPTION(jni); |
713 if (j_input_buffer_index == -1) { | 710 if (j_input_buffer_index == -1) { |
714 // Video codec falls behind - no input buffer available. | 711 // Video codec falls behind - no input buffer available. |
715 ALOGW << "Encoder drop frame - no input buffers available"; | 712 ALOGW << "Encoder drop frame - no input buffers available"; |
716 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 713 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
717 frames_dropped_media_encoder_++; | 714 frames_dropped_media_encoder_++; |
718 OnDroppedFrame(); | 715 OnDroppedFrameOnCodecThread(); |
719 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. | 716 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. |
720 } | 717 } |
721 if (j_input_buffer_index == -2) { | 718 if (j_input_buffer_index == -2) { |
722 ResetCodecOnCodecThread(); | 719 ResetCodecOnCodecThread(); |
723 return WEBRTC_VIDEO_CODEC_ERROR; | 720 return WEBRTC_VIDEO_CODEC_ERROR; |
724 } | 721 } |
725 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, | 722 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, |
726 j_input_buffer_index); | 723 j_input_buffer_index); |
727 } else { | 724 } else { |
728 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); | 725 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 if (head[3] != 0x01) { // got 000000xx | 1161 if (head[3] != 0x01) { // got 000000xx |
1165 head++; // xx != 1, continue searching. | 1162 head++; // xx != 1, continue searching. |
1166 continue; | 1163 continue; |
1167 } | 1164 } |
1168 return (int32_t)(head - buffer); | 1165 return (int32_t)(head - buffer); |
1169 } | 1166 } |
1170 return -1; | 1167 return -1; |
1171 } | 1168 } |
1172 | 1169 |
1173 void MediaCodecVideoEncoder::OnDroppedFrame() { | 1170 void MediaCodecVideoEncoder::OnDroppedFrame() { |
| 1171 // Methods running on the codec thread should call OnDroppedFrameOnCodecThread |
| 1172 // directly. |
| 1173 RTC_DCHECK(!codec_thread_checker_.CalledOnValidThread()); |
| 1174 codec_thread_->Invoke<void>( |
| 1175 Bind(&MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread, this)); |
| 1176 } |
| 1177 |
| 1178 void MediaCodecVideoEncoder::OnDroppedFrameOnCodecThread() { |
| 1179 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
1174 // Report dropped frame to quality_scaler_. | 1180 // Report dropped frame to quality_scaler_. |
1175 if (scale_) | 1181 if (scale_) |
1176 quality_scaler_.ReportDroppedFrame(); | 1182 quality_scaler_.ReportDroppedFrame(); |
1177 } | 1183 } |
1178 | 1184 |
1179 int MediaCodecVideoEncoder::GetTargetFramerate() { | 1185 int MediaCodecVideoEncoder::GetTargetFramerate() { |
1180 return scale_ ? quality_scaler_.GetTargetFramerate() : -1; | 1186 return scale_ ? quality_scaler_.GetTargetFramerate() : -1; |
1181 } | 1187 } |
1182 | 1188 |
1183 const char* MediaCodecVideoEncoder::ImplementationName() const { | 1189 const char* MediaCodecVideoEncoder::ImplementationName() const { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 return supported_codecs_; | 1273 return supported_codecs_; |
1268 } | 1274 } |
1269 | 1275 |
1270 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1276 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1271 webrtc::VideoEncoder* encoder) { | 1277 webrtc::VideoEncoder* encoder) { |
1272 ALOGD << "Destroy video encoder."; | 1278 ALOGD << "Destroy video encoder."; |
1273 delete encoder; | 1279 delete encoder; |
1274 } | 1280 } |
1275 | 1281 |
1276 } // namespace webrtc_jni | 1282 } // namespace webrtc_jni |
OLD | NEW |