| 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 |