Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: webrtc/api/java/jni/androidmediaencoder_jni.cc

Issue 2051403002: Always on statistics for AndroidMediaEncoder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698