Chromium Code Reviews| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. | 219 int frames_dropped_media_encoder_; // Number of frames dropped by encoder. |
| 220 // Number of dropped frames caused by full queue. | 220 // Number of dropped frames caused by full queue. |
| 221 int consecutive_full_queue_frame_drops_; | 221 int consecutive_full_queue_frame_drops_; |
| 222 int64_t stat_start_time_ms_; // Start time for statistics. | 222 int64_t stat_start_time_ms_; // Start time for statistics. |
| 223 int current_frames_; // Number of frames in the current statistics interval. | 223 int current_frames_; // Number of frames in the current statistics interval. |
| 224 int current_bytes_; // Encoded bytes in the current statistics interval. | 224 int current_bytes_; // Encoded bytes in the current statistics interval. |
| 225 int current_acc_qp_; // Accumulated QP in the current statistics interval. | 225 int current_acc_qp_; // Accumulated QP in the current statistics interval. |
| 226 int current_encoding_time_ms_; // Overall encoding time in the current second | 226 int current_encoding_time_ms_; // Overall encoding time in the current second |
| 227 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. | 227 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. |
| 228 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. | 228 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. |
| 229 bool output_delivery_loop_running_; // Is the onMessage loop running | |
| 230 | 229 |
| 231 struct InputFrameInfo { | 230 struct InputFrameInfo { |
| 232 InputFrameInfo(int64_t encode_start_time, | 231 InputFrameInfo(int64_t encode_start_time, |
| 233 int32_t frame_timestamp, | 232 int32_t frame_timestamp, |
| 234 int64_t frame_render_time_ms, | 233 int64_t frame_render_time_ms, |
| 235 webrtc::VideoRotation rotation) | 234 webrtc::VideoRotation rotation) |
| 236 : encode_start_time(encode_start_time), | 235 : encode_start_time(encode_start_time), |
| 237 frame_timestamp(frame_timestamp), | 236 frame_timestamp(frame_timestamp), |
| 238 frame_render_time_ms(frame_render_time_ms), | 237 frame_render_time_ms(frame_render_time_ms), |
| 239 rotation(rotation) {} | 238 rotation(rotation) {} |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 j_media_codec_video_encoder_( | 299 j_media_codec_video_encoder_( |
| 301 jni, | 300 jni, |
| 302 jni->NewObject(*j_media_codec_video_encoder_class_, | 301 jni->NewObject(*j_media_codec_video_encoder_class_, |
| 303 GetMethodID(jni, | 302 GetMethodID(jni, |
| 304 *j_media_codec_video_encoder_class_, | 303 *j_media_codec_video_encoder_class_, |
| 305 "<init>", | 304 "<init>", |
| 306 "()V"))), | 305 "()V"))), |
| 307 inited_(false), | 306 inited_(false), |
| 308 use_surface_(false), | 307 use_surface_(false), |
| 309 picture_id_(0), | 308 picture_id_(0), |
| 310 output_delivery_loop_running_(false), | |
| 311 egl_context_(egl_context) { | 309 egl_context_(egl_context) { |
| 312 ScopedLocalRefFrame local_ref_frame(jni); | 310 ScopedLocalRefFrame local_ref_frame(jni); |
| 313 // It would be nice to avoid spinning up a new thread per MediaCodec, and | 311 // It would be nice to avoid spinning up a new thread per MediaCodec, and |
| 314 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug | 312 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug |
| 315 // 2732 means that deadlocks abound. This class synchronously trampolines | 313 // 2732 means that deadlocks abound. This class synchronously trampolines |
| 316 // to |codec_thread_|, so if anything else can be coming to _us_ from | 314 // to |codec_thread_|, so if anything else can be coming to _us_ from |
| 317 // |codec_thread_|, or from any thread holding the |_sendCritSect| described | 315 // |codec_thread_|, or from any thread holding the |_sendCritSect| described |
| 318 // in the bug, we have a problem. For now work around that with a dedicated | 316 // in the bug, we have a problem. For now work around that with a dedicated |
| 319 // thread. | 317 // thread. |
| 320 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); | 318 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 RTC_CHECK(!msg->pdata) << "Unexpected message!"; | 467 RTC_CHECK(!msg->pdata) << "Unexpected message!"; |
| 470 if (!inited_) { | 468 if (!inited_) { |
| 471 return; | 469 return; |
| 472 } | 470 } |
| 473 | 471 |
| 474 // It would be nice to recover from a failure here if one happened, but it's | 472 // It would be nice to recover from a failure here if one happened, but it's |
| 475 // unclear how to signal such a failure to the app, so instead we stay silent | 473 // unclear how to signal such a failure to the app, so instead we stay silent |
| 476 // about it and let the next app-called API method reveal the borkedness. | 474 // about it and let the next app-called API method reveal the borkedness. |
| 477 DeliverPendingOutputs(jni); | 475 DeliverPendingOutputs(jni); |
| 478 | 476 |
| 479 // If there aren't more frames to deliver, we can stop the loop | 477 // If there aren't more frames to deliver, we can start polling at lower rate. |
| 480 if (!input_frame_infos_.empty()) { | 478 if (!input_frame_infos_.empty()) { |
|
AlexG
2016/06/13 17:02:54
nit: better to use positive condition
if (input_f
| |
| 481 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | 479 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
| 482 } else { | 480 } else { |
| 483 output_delivery_loop_running_ = false; | 481 codec_thread_->PostDelayed(kMediaCodecPollNoFramesMs, this); |
| 484 } | 482 } |
| 483 | |
| 484 // Call log statistics here so it's called even if no frames are being | |
| 485 // delivered. | |
| 486 LogStatistics(false); | |
| 485 } | 487 } |
| 486 | 488 |
| 487 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { | 489 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { |
| 488 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 490 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
| 489 ALOGE << "ResetOnCodecThread"; | 491 ALOGE << "ResetOnCodecThread"; |
| 490 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || | 492 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || |
| 491 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != | 493 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != |
| 492 WEBRTC_VIDEO_CODEC_OK) { | 494 WEBRTC_VIDEO_CODEC_OK) { |
| 493 // TODO(fischman): wouldn't it be nice if there was a way to gracefully | 495 // TODO(fischman): wouldn't it be nice if there was a way to gracefully |
| 494 // degrade to a SW encoder at this point? There isn't one AFAICT :( | 496 // degrade to a SW encoder at this point? There isn't one AFAICT :( |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 733 // Save input image timestamps for later output. | 735 // Save input image timestamps for later output. |
| 734 input_frame_infos_.emplace_back( | 736 input_frame_infos_.emplace_back( |
| 735 time_before_calling_encode, input_frame.timestamp(), | 737 time_before_calling_encode, input_frame.timestamp(), |
| 736 input_frame.render_time_ms(), input_frame.rotation()); | 738 input_frame.render_time_ms(), input_frame.rotation()); |
| 737 | 739 |
| 738 last_input_timestamp_ms_ = | 740 last_input_timestamp_ms_ = |
| 739 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; | 741 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; |
| 740 | 742 |
| 741 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 743 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
| 742 | 744 |
| 743 if (!output_delivery_loop_running_) { | 745 codec_thread_->Clear(this); |
| 744 output_delivery_loop_running_ = true; | 746 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
| 745 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
| 746 } | |
| 747 | 747 |
| 748 if (!DeliverPendingOutputs(jni)) { | 748 if (!DeliverPendingOutputs(jni)) { |
| 749 ALOGE << "Failed deliver pending outputs."; | 749 ALOGE << "Failed deliver pending outputs."; |
| 750 ResetCodecOnCodecThread(); | 750 ResetCodecOnCodecThread(); |
| 751 return WEBRTC_VIDEO_CODEC_ERROR; | 751 return WEBRTC_VIDEO_CODEC_ERROR; |
| 752 } | 752 } |
| 753 return WEBRTC_VIDEO_CODEC_OK; | 753 return WEBRTC_VIDEO_CODEC_OK; |
| 754 } | 754 } |
| 755 | 755 |
| 756 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( | 756 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 855 ". Dropped: " << frames_dropped_media_encoder_; | 855 ". Dropped: " << frames_dropped_media_encoder_; |
| 856 ScopedLocalRefFrame local_ref_frame(jni); | 856 ScopedLocalRefFrame local_ref_frame(jni); |
| 857 for (size_t i = 0; i < input_buffers_.size(); ++i) | 857 for (size_t i = 0; i < input_buffers_.size(); ++i) |
| 858 jni->DeleteGlobalRef(input_buffers_[i]); | 858 jni->DeleteGlobalRef(input_buffers_[i]); |
| 859 input_buffers_.clear(); | 859 input_buffers_.clear(); |
| 860 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_); | 860 jni->CallVoidMethod(*j_media_codec_video_encoder_, j_release_method_); |
| 861 CHECK_EXCEPTION(jni); | 861 CHECK_EXCEPTION(jni); |
| 862 rtc::MessageQueueManager::Clear(this); | 862 rtc::MessageQueueManager::Clear(this); |
| 863 inited_ = false; | 863 inited_ = false; |
| 864 use_surface_ = false; | 864 use_surface_ = false; |
| 865 output_delivery_loop_running_ = false; | |
| 866 ALOGD << "EncoderReleaseOnCodecThread done."; | 865 ALOGD << "EncoderReleaseOnCodecThread done."; |
| 867 return WEBRTC_VIDEO_CODEC_OK; | 866 return WEBRTC_VIDEO_CODEC_OK; |
| 868 } | 867 } |
| 869 | 868 |
| 870 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, | 869 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, |
| 871 uint32_t frame_rate) { | 870 uint32_t frame_rate) { |
| 872 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 871 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
| 873 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? | 872 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? |
| 874 frame_rate : MAX_ALLOWED_VIDEO_FPS; | 873 frame_rate : MAX_ALLOWED_VIDEO_FPS; |
| 875 if (last_set_bitrate_kbps_ == new_bit_rate && | 874 if (last_set_bitrate_kbps_ == new_bit_rate && |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 919 | 918 |
| 920 jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs( | 919 jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs( |
| 921 JNIEnv* jni, | 920 JNIEnv* jni, |
| 922 jobject j_output_buffer_info) { | 921 jobject j_output_buffer_info) { |
| 923 return GetLongField( | 922 return GetLongField( |
| 924 jni, j_output_buffer_info, j_info_presentation_timestamp_us_field_); | 923 jni, j_output_buffer_info, j_info_presentation_timestamp_us_field_); |
| 925 } | 924 } |
| 926 | 925 |
| 927 bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { | 926 bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { |
| 928 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 927 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
| 928 | |
| 929 while (true) { | 929 while (true) { |
| 930 jobject j_output_buffer_info = jni->CallObjectMethod( | 930 jobject j_output_buffer_info = jni->CallObjectMethod( |
| 931 *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_); | 931 *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_); |
| 932 CHECK_EXCEPTION(jni); | 932 CHECK_EXCEPTION(jni); |
| 933 if (IsNull(jni, j_output_buffer_info)) { | 933 if (IsNull(jni, j_output_buffer_info)) { |
| 934 break; | 934 break; |
| 935 } | 935 } |
| 936 | 936 |
| 937 int output_buffer_index = | 937 int output_buffer_index = |
| 938 GetOutputBufferInfoIndex(jni, j_output_buffer_info); | 938 GetOutputBufferInfoIndex(jni, j_output_buffer_info); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1114 drop_next_input_frame_ = true; | 1114 drop_next_input_frame_ = true; |
| 1115 // Theoretically could handle callback_status<0 here, but unclear what | 1115 // Theoretically could handle callback_status<0 here, but unclear what |
| 1116 // that would mean for us. | 1116 // that would mean for us. |
| 1117 } | 1117 } |
| 1118 } | 1118 } |
| 1119 return true; | 1119 return true; |
| 1120 } | 1120 } |
| 1121 | 1121 |
| 1122 void MediaCodecVideoEncoder::LogStatistics(bool force_log) { | 1122 void MediaCodecVideoEncoder::LogStatistics(bool force_log) { |
| 1123 int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_; | 1123 int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_; |
| 1124 if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log) && | 1124 if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log) |
| 1125 current_frames_ > 0 && statistic_time_ms > 0) { | 1125 && statistic_time_ms > 0) { |
| 1126 // Prevent division by zero. | |
| 1127 int current_frames_divider = current_frames_ != 0 ? current_frames_ : 1; | |
| 1128 | |
| 1126 int current_bitrate = current_bytes_ * 8 / statistic_time_ms; | 1129 int current_bitrate = current_bytes_ * 8 / statistic_time_ms; |
| 1127 int current_fps = | 1130 int current_fps = |
| 1128 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms; | 1131 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms; |
| 1129 ALOGD << "Encoded frames: " << frames_encoded_ << | 1132 ALOGD << "Encoded frames: " << frames_encoded_ << |
| 1130 ". Bitrate: " << current_bitrate << | 1133 ". Bitrate: " << current_bitrate << |
| 1131 ", target: " << last_set_bitrate_kbps_ << " kbps" << | 1134 ", target: " << last_set_bitrate_kbps_ << " kbps" << |
| 1132 ", fps: " << current_fps << | 1135 ", fps: " << current_fps << |
| 1133 ", encTime: " << (current_encoding_time_ms_ / current_frames_) << | 1136 ", encTime: " << (current_encoding_time_ms_ / current_frames_divider) << |
| 1134 ". QP: " << (current_acc_qp_ / current_frames_) << | 1137 ". QP: " << (current_acc_qp_ / current_frames_divider) << |
| 1135 " for last " << statistic_time_ms << " ms."; | 1138 " for last " << statistic_time_ms << " ms."; |
| 1136 stat_start_time_ms_ = rtc::TimeMillis(); | 1139 stat_start_time_ms_ = rtc::TimeMillis(); |
| 1137 current_frames_ = 0; | 1140 current_frames_ = 0; |
| 1138 current_bytes_ = 0; | 1141 current_bytes_ = 0; |
| 1139 current_acc_qp_ = 0; | 1142 current_acc_qp_ = 0; |
| 1140 current_encoding_time_ms_ = 0; | 1143 current_encoding_time_ms_ = 0; |
| 1141 } | 1144 } |
| 1142 } | 1145 } |
| 1143 | 1146 |
| 1144 int32_t MediaCodecVideoEncoder::NextNaluPosition( | 1147 int32_t MediaCodecVideoEncoder::NextNaluPosition( |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1275 return supported_codecs_; | 1278 return supported_codecs_; |
| 1276 } | 1279 } |
| 1277 | 1280 |
| 1278 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1281 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
| 1279 webrtc::VideoEncoder* encoder) { | 1282 webrtc::VideoEncoder* encoder) { |
| 1280 ALOGD << "Destroy video encoder."; | 1283 ALOGD << "Destroy video encoder."; |
| 1281 delete encoder; | 1284 delete encoder; |
| 1282 } | 1285 } |
| 1283 | 1286 |
| 1284 } // namespace webrtc_jni | 1287 } // namespace webrtc_jni |
| OLD | NEW |