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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 int64_t current_timestamp_us_; // Current frame timestamps in us. | 216 int64_t current_timestamp_us_; // Current frame timestamps in us. |
217 int frames_received_; // Number of frames received by encoder. | 217 int frames_received_; // Number of frames received by encoder. |
218 int frames_encoded_; // Number of frames encoded by encoder. | 218 int frames_encoded_; // Number of frames encoded by encoder. |
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 // Number of DeliverPendingOuputs calls in the current statistics interval. | |
227 int deliver_pending_outputs_calls_; | |
226 int current_encoding_time_ms_; // Overall encoding time in the current second | 228 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. | 229 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. |
228 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. | 230 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. |
229 bool output_delivery_loop_running_; // Is the onMessage loop running | 231 // Is the onMessage loop running at regular polling rate. If false, it is |
232 // running at lower poll rate of kMediaCodecStatisticsIntervalMs. | |
233 bool output_delivery_loop_running_; | |
230 | 234 |
231 struct InputFrameInfo { | 235 struct InputFrameInfo { |
232 InputFrameInfo(int64_t encode_start_time, | 236 InputFrameInfo(int64_t encode_start_time, |
233 int32_t frame_timestamp, | 237 int32_t frame_timestamp, |
234 int64_t frame_render_time_ms, | 238 int64_t frame_render_time_ms, |
235 webrtc::VideoRotation rotation) | 239 webrtc::VideoRotation rotation) |
236 : encode_start_time(encode_start_time), | 240 : encode_start_time(encode_start_time), |
237 frame_timestamp(frame_timestamp), | 241 frame_timestamp(frame_timestamp), |
238 frame_render_time_ms(frame_render_time_ms), | 242 frame_render_time_ms(frame_render_time_ms), |
239 rotation(rotation) {} | 243 rotation(rotation) {} |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 j_media_codec_video_encoder_( | 304 j_media_codec_video_encoder_( |
301 jni, | 305 jni, |
302 jni->NewObject(*j_media_codec_video_encoder_class_, | 306 jni->NewObject(*j_media_codec_video_encoder_class_, |
303 GetMethodID(jni, | 307 GetMethodID(jni, |
304 *j_media_codec_video_encoder_class_, | 308 *j_media_codec_video_encoder_class_, |
305 "<init>", | 309 "<init>", |
306 "()V"))), | 310 "()V"))), |
307 inited_(false), | 311 inited_(false), |
308 use_surface_(false), | 312 use_surface_(false), |
309 picture_id_(0), | 313 picture_id_(0), |
310 output_delivery_loop_running_(false), | |
311 egl_context_(egl_context) { | 314 egl_context_(egl_context) { |
312 ScopedLocalRefFrame local_ref_frame(jni); | 315 ScopedLocalRefFrame local_ref_frame(jni); |
313 // It would be nice to avoid spinning up a new thread per MediaCodec, and | 316 // 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 | 317 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug |
315 // 2732 means that deadlocks abound. This class synchronously trampolines | 318 // 2732 means that deadlocks abound. This class synchronously trampolines |
316 // to |codec_thread_|, so if anything else can be coming to _us_ from | 319 // to |codec_thread_|, so if anything else can be coming to _us_ from |
317 // |codec_thread_|, or from any thread holding the |_sendCritSect| described | 320 // |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 | 321 // in the bug, we have a problem. For now work around that with a dedicated |
319 // thread. | 322 // thread. |
320 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); | 323 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 } | 475 } |
473 | 476 |
474 // It would be nice to recover from a failure here if one happened, but it's | 477 // 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 | 478 // 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. | 479 // about it and let the next app-called API method reveal the borkedness. |
477 DeliverPendingOutputs(jni); | 480 DeliverPendingOutputs(jni); |
478 | 481 |
479 // If there aren't more frames to deliver, we can stop the loop | 482 // If there aren't more frames to deliver, we can stop the loop |
480 if (!input_frame_infos_.empty()) { | 483 if (!input_frame_infos_.empty()) { |
481 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | 484 codec_thread_->PostDelayed(kMediaCodecPollMs, this); |
485 output_delivery_loop_running_ = true; | |
482 } else { | 486 } else { |
487 codec_thread_->PostDelayed(kMediaCodecStatisticsIntervalMs, this); | |
483 output_delivery_loop_running_ = false; | 488 output_delivery_loop_running_ = false; |
484 } | 489 } |
490 | |
491 // Call log statistics here so it's called even if no frames are being | |
492 // delivered. | |
493 LogStatistics(false); | |
485 } | 494 } |
486 | 495 |
487 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { | 496 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { |
488 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 497 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
489 ALOGE << "ResetOnCodecThread"; | 498 ALOGE << "ResetOnCodecThread"; |
490 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || | 499 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || |
491 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != | 500 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != |
492 WEBRTC_VIDEO_CODEC_OK) { | 501 WEBRTC_VIDEO_CODEC_OK) { |
493 // TODO(fischman): wouldn't it be nice if there was a way to gracefully | 502 // 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 :( | 503 // degrade to a SW encoder at this point? There isn't one AFAICT :( |
(...skipping 27 matching lines...) Expand all Loading... | |
522 yuv_size_ = width_ * height_ * 3 / 2; | 531 yuv_size_ = width_ * height_ * 3 / 2; |
523 frames_received_ = 0; | 532 frames_received_ = 0; |
524 frames_encoded_ = 0; | 533 frames_encoded_ = 0; |
525 frames_dropped_media_encoder_ = 0; | 534 frames_dropped_media_encoder_ = 0; |
526 consecutive_full_queue_frame_drops_ = 0; | 535 consecutive_full_queue_frame_drops_ = 0; |
527 current_timestamp_us_ = 0; | 536 current_timestamp_us_ = 0; |
528 stat_start_time_ms_ = rtc::TimeMillis(); | 537 stat_start_time_ms_ = rtc::TimeMillis(); |
529 current_frames_ = 0; | 538 current_frames_ = 0; |
530 current_bytes_ = 0; | 539 current_bytes_ = 0; |
531 current_acc_qp_ = 0; | 540 current_acc_qp_ = 0; |
541 deliver_pending_outputs_calls_ = 0; | |
532 current_encoding_time_ms_ = 0; | 542 current_encoding_time_ms_ = 0; |
533 last_input_timestamp_ms_ = -1; | 543 last_input_timestamp_ms_ = -1; |
534 last_output_timestamp_ms_ = -1; | 544 last_output_timestamp_ms_ = -1; |
545 output_delivery_loop_running_ = false; | |
535 output_timestamp_ = 0; | 546 output_timestamp_ = 0; |
536 output_render_time_ms_ = 0; | 547 output_render_time_ms_ = 0; |
537 input_frame_infos_.clear(); | 548 input_frame_infos_.clear(); |
538 drop_next_input_frame_ = false; | 549 drop_next_input_frame_ = false; |
539 use_surface_ = use_surface; | 550 use_surface_ = use_surface; |
540 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; | 551 picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF; |
541 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); | 552 gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1); |
542 tl0_pic_idx_ = static_cast<uint8_t>(rand()); | 553 tl0_pic_idx_ = static_cast<uint8_t>(rand()); |
543 gof_idx_ = 0; | 554 gof_idx_ = 0; |
544 last_frame_received_ms_ = -1; | 555 last_frame_received_ms_ = -1; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 input_buffers_[i] = | 599 input_buffers_[i] = |
589 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); | 600 jni->NewGlobalRef(jni->GetObjectArrayElement(input_buffers, i)); |
590 int64_t yuv_buffer_capacity = | 601 int64_t yuv_buffer_capacity = |
591 jni->GetDirectBufferCapacity(input_buffers_[i]); | 602 jni->GetDirectBufferCapacity(input_buffers_[i]); |
592 CHECK_EXCEPTION(jni); | 603 CHECK_EXCEPTION(jni); |
593 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity"; | 604 RTC_CHECK(yuv_buffer_capacity >= yuv_size_) << "Insufficient capacity"; |
594 } | 605 } |
595 } | 606 } |
596 | 607 |
597 inited_ = true; | 608 inited_ = true; |
609 codec_thread_->PostDelayed(kMediaCodecStatisticsIntervalMs, this); | |
598 return WEBRTC_VIDEO_CODEC_OK; | 610 return WEBRTC_VIDEO_CODEC_OK; |
599 } | 611 } |
600 | 612 |
601 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( | 613 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( |
602 const webrtc::VideoFrame& frame, | 614 const webrtc::VideoFrame& frame, |
603 const std::vector<webrtc::FrameType>* frame_types) { | 615 const std::vector<webrtc::FrameType>* frame_types) { |
604 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 616 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
605 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 617 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
606 ScopedLocalRefFrame local_ref_frame(jni); | 618 ScopedLocalRefFrame local_ref_frame(jni); |
607 | 619 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
734 input_frame_infos_.emplace_back( | 746 input_frame_infos_.emplace_back( |
735 time_before_calling_encode, input_frame.timestamp(), | 747 time_before_calling_encode, input_frame.timestamp(), |
736 input_frame.render_time_ms(), input_frame.rotation()); | 748 input_frame.render_time_ms(), input_frame.rotation()); |
737 | 749 |
738 last_input_timestamp_ms_ = | 750 last_input_timestamp_ms_ = |
739 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; | 751 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; |
740 | 752 |
741 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 753 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
742 | 754 |
743 if (!output_delivery_loop_running_) { | 755 if (!output_delivery_loop_running_) { |
756 codec_thread_->Clear(this); | |
757 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
744 output_delivery_loop_running_ = true; | 758 output_delivery_loop_running_ = true; |
745 codec_thread_->PostDelayed(kMediaCodecPollMs, this); | |
746 } | 759 } |
747 | 760 |
748 if (!DeliverPendingOutputs(jni)) { | 761 if (!DeliverPendingOutputs(jni)) { |
749 ALOGE << "Failed deliver pending outputs."; | 762 ALOGE << "Failed deliver pending outputs."; |
750 ResetCodecOnCodecThread(); | 763 ResetCodecOnCodecThread(); |
751 return WEBRTC_VIDEO_CODEC_ERROR; | 764 return WEBRTC_VIDEO_CODEC_ERROR; |
752 } | 765 } |
753 return WEBRTC_VIDEO_CODEC_OK; | 766 return WEBRTC_VIDEO_CODEC_OK; |
754 } | 767 } |
755 | 768 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 | 932 |
920 jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs( | 933 jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs( |
921 JNIEnv* jni, | 934 JNIEnv* jni, |
922 jobject j_output_buffer_info) { | 935 jobject j_output_buffer_info) { |
923 return GetLongField( | 936 return GetLongField( |
924 jni, j_output_buffer_info, j_info_presentation_timestamp_us_field_); | 937 jni, j_output_buffer_info, j_info_presentation_timestamp_us_field_); |
925 } | 938 } |
926 | 939 |
927 bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { | 940 bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { |
928 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 941 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
942 deliver_pending_outputs_calls_++; | |
943 | |
929 while (true) { | 944 while (true) { |
930 jobject j_output_buffer_info = jni->CallObjectMethod( | 945 jobject j_output_buffer_info = jni->CallObjectMethod( |
931 *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_); | 946 *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_); |
932 CHECK_EXCEPTION(jni); | 947 CHECK_EXCEPTION(jni); |
933 if (IsNull(jni, j_output_buffer_info)) { | 948 if (IsNull(jni, j_output_buffer_info)) { |
934 break; | 949 break; |
935 } | 950 } |
936 | 951 |
937 int output_buffer_index = | 952 int output_buffer_index = |
938 GetOutputBufferInfoIndex(jni, j_output_buffer_info); | 953 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; | 1129 drop_next_input_frame_ = true; |
1115 // Theoretically could handle callback_status<0 here, but unclear what | 1130 // Theoretically could handle callback_status<0 here, but unclear what |
1116 // that would mean for us. | 1131 // that would mean for us. |
1117 } | 1132 } |
1118 } | 1133 } |
1119 return true; | 1134 return true; |
1120 } | 1135 } |
1121 | 1136 |
1122 void MediaCodecVideoEncoder::LogStatistics(bool force_log) { | 1137 void MediaCodecVideoEncoder::LogStatistics(bool force_log) { |
1123 int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_; | 1138 int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_; |
1124 if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log) && | 1139 if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log) |
1125 current_frames_ > 0 && statistic_time_ms > 0) { | 1140 && statistic_time_ms > 0) { |
1141 // Prevent division by zero | |
1142 int current_frames_divider = current_frames_ != 0 ? current_frames_ : 1; | |
1143 | |
1126 int current_bitrate = current_bytes_ * 8 / statistic_time_ms; | 1144 int current_bitrate = current_bytes_ * 8 / statistic_time_ms; |
1127 int current_fps = | 1145 int current_fps = |
1128 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms; | 1146 (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms; |
1129 ALOGD << "Encoded frames: " << frames_encoded_ << | 1147 ALOGD << "Encoded frames: " << frames_encoded_ << |
1130 ". Bitrate: " << current_bitrate << | 1148 ". Bitrate: " << current_bitrate << |
1131 ", target: " << last_set_bitrate_kbps_ << " kbps" << | 1149 ", target: " << last_set_bitrate_kbps_ << " kbps" << |
1132 ", fps: " << current_fps << | 1150 ", fps: " << current_fps << |
1133 ", encTime: " << (current_encoding_time_ms_ / current_frames_) << | 1151 ", encTime: " << (current_encoding_time_ms_ / current_frames_divider) << |
1134 ". QP: " << (current_acc_qp_ / current_frames_) << | 1152 ". QP: " << (current_acc_qp_ / current_frames_divider) << |
1153 ", DeliverPendingOutputs: " << deliver_pending_outputs_calls_ << | |
perkj_webrtc
2016/06/10 11:37:48
I don't think we care about how many times Deliver
| |
1135 " for last " << statistic_time_ms << " ms."; | 1154 " for last " << statistic_time_ms << " ms."; |
1136 stat_start_time_ms_ = rtc::TimeMillis(); | 1155 stat_start_time_ms_ = rtc::TimeMillis(); |
1137 current_frames_ = 0; | 1156 current_frames_ = 0; |
1138 current_bytes_ = 0; | 1157 current_bytes_ = 0; |
1139 current_acc_qp_ = 0; | 1158 current_acc_qp_ = 0; |
1159 deliver_pending_outputs_calls_ = 0; | |
perkj_webrtc
2016/06/10 11:37:48
And remove DeliverPendingOutputs.
| |
1140 current_encoding_time_ms_ = 0; | 1160 current_encoding_time_ms_ = 0; |
1141 } | 1161 } |
1142 } | 1162 } |
1143 | 1163 |
1144 int32_t MediaCodecVideoEncoder::NextNaluPosition( | 1164 int32_t MediaCodecVideoEncoder::NextNaluPosition( |
1145 uint8_t *buffer, size_t buffer_size) { | 1165 uint8_t *buffer, size_t buffer_size) { |
1146 if (buffer_size < H264_SC_LENGTH) { | 1166 if (buffer_size < H264_SC_LENGTH) { |
1147 return -1; | 1167 return -1; |
1148 } | 1168 } |
1149 uint8_t *head = buffer; | 1169 uint8_t *head = buffer; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1275 return supported_codecs_; | 1295 return supported_codecs_; |
1276 } | 1296 } |
1277 | 1297 |
1278 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1298 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1279 webrtc::VideoEncoder* encoder) { | 1299 webrtc::VideoEncoder* encoder) { |
1280 ALOGD << "Destroy video encoder."; | 1300 ALOGD << "Destroy video encoder."; |
1281 delete encoder; | 1301 delete encoder; |
1282 } | 1302 } |
1283 | 1303 |
1284 } // namespace webrtc_jni | 1304 } // namespace webrtc_jni |
OLD | NEW |