OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 #define MAX_VIDEO_WIDTH 1280 | 70 #define MAX_VIDEO_WIDTH 1280 |
71 #define MAX_VIDEO_HEIGHT 1280 | 71 #define MAX_VIDEO_HEIGHT 1280 |
72 // Maximum supported HW video encoder fps. | 72 // Maximum supported HW video encoder fps. |
73 #define MAX_VIDEO_FPS 30 | 73 #define MAX_VIDEO_FPS 30 |
74 // Maximum allowed fps value in SetRates() call. | 74 // Maximum allowed fps value in SetRates() call. |
75 #define MAX_ALLOWED_VIDEO_FPS 60 | 75 #define MAX_ALLOWED_VIDEO_FPS 60 |
76 // Maximum allowed frames in encoder input queue. | 76 // Maximum allowed frames in encoder input queue. |
77 #define MAX_ENCODER_Q_SIZE 2 | 77 #define MAX_ENCODER_Q_SIZE 2 |
78 // Maximum allowed latency in ms. | 78 // Maximum allowed latency in ms. |
79 #define MAX_ENCODER_LATENCY_MS 70 | 79 #define MAX_ENCODER_LATENCY_MS 70 |
80 | 80 // Maximum amount of dropped frames caused by full encoder queue - exceeding |
81 // this threshold means that encoder probably got stuck and need to be reset. | |
82 #define MAX_DROPPED_FRAMES 60 | |
pbos-webrtc
2016/01/18 10:33:07
ENCODER_STALL_FRAMEDROP_THRESHOLD maybe, something
jackychen_
2016/01/19 02:21:01
In the comment, "reset the encoder when it drops m
AlexG
2016/01/19 22:13:41
Done.
AlexG
2016/01/19 22:13:41
Done.
| |
81 | 83 |
82 // Logging macros. | 84 // Logging macros. |
83 #define TAG_ENCODER "MediaCodecVideoEncoder" | 85 #define TAG_ENCODER "MediaCodecVideoEncoder" |
84 #ifdef TRACK_BUFFER_TIMING | 86 #ifdef TRACK_BUFFER_TIMING |
85 #define ALOGV(...) | 87 #define ALOGV(...) |
86 __android_log_print(ANDROID_LOG_VERBOSE, TAG_ENCODER, __VA_ARGS__) | 88 __android_log_print(ANDROID_LOG_VERBOSE, TAG_ENCODER, __VA_ARGS__) |
87 #else | 89 #else |
88 #define ALOGV(...) | 90 #define ALOGV(...) |
89 #endif | 91 #endif |
90 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER) | 92 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 bool inited_; | 216 bool inited_; |
215 bool use_surface_; | 217 bool use_surface_; |
216 uint16_t picture_id_; | 218 uint16_t picture_id_; |
217 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. | 219 enum libyuv::FourCC encoder_fourcc_; // Encoder color space format. |
218 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. | 220 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. |
219 int last_set_fps_; // Last-requested frame rate. | 221 int last_set_fps_; // Last-requested frame rate. |
220 int64_t current_timestamp_us_; // Current frame timestamps in us. | 222 int64_t current_timestamp_us_; // Current frame timestamps in us. |
221 int frames_received_; // Number of frames received by encoder. | 223 int frames_received_; // Number of frames received by encoder. |
222 int frames_encoded_; // Number of frames encoded by encoder. | 224 int frames_encoded_; // Number of frames encoded by encoder. |
223 int frames_dropped_; // Number of frames dropped by encoder. | 225 int frames_dropped_; // Number of frames dropped by encoder. |
226 int frames_dropped_q_full_; // Number of dropped frames caused by full queue. | |
pbos-webrtc
2016/01/18 10:33:07
consecutive_full_queue_frame_drops_
AlexG
2016/01/19 22:13:41
Done.
| |
224 int frames_in_queue_; // Number of frames in encoder queue. | 227 int frames_in_queue_; // Number of frames in encoder queue. |
225 int64_t start_time_ms_; // Start time for statistics. | 228 int64_t start_time_ms_; // Start time for statistics. |
226 int current_frames_; // Number of frames in the current statistics interval. | 229 int current_frames_; // Number of frames in the current statistics interval. |
227 int current_bytes_; // Encoded bytes in the current statistics interval. | 230 int current_bytes_; // Encoded bytes in the current statistics interval. |
228 int current_acc_qp_; // Accumulated QP in the current statistics interval. | 231 int current_acc_qp_; // Accumulated QP in the current statistics interval. |
229 int current_encoding_time_ms_; // Overall encoding time in the current second | 232 int current_encoding_time_ms_; // Overall encoding time in the current second |
230 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. | 233 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. |
231 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. | 234 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. |
232 std::vector<int32_t> timestamps_; // Video frames timestamp queue. | 235 std::vector<int32_t> timestamps_; // Video frames timestamp queue. |
233 std::vector<int64_t> render_times_ms_; // Video frames render time queue. | 236 std::vector<int64_t> render_times_ms_; // Video frames render time queue. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 scale_ = (codecType_ != kVideoCodecVP9) && (webrtc::field_trial::FindFullName( | 366 scale_ = (codecType_ != kVideoCodecVP9) && (webrtc::field_trial::FindFullName( |
364 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"); | 367 "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled"); |
365 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); | 368 ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled"); |
366 if (scale_) { | 369 if (scale_) { |
367 if (codecType_ == kVideoCodecVP8) { | 370 if (codecType_ == kVideoCodecVP8) { |
368 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the | 371 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the |
369 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is | 372 // (internal) range: [0, 127]. And we cannot change QP_max in HW, so it is |
370 // always = 127. Note that in SW, QP is that of the user-level range [0, | 373 // always = 127. Note that in SW, QP is that of the user-level range [0, |
371 // 63]. | 374 // 63]. |
372 const int kMaxQp = 127; | 375 const int kMaxQp = 127; |
373 // TODO(pbos): Investigate whether high-QP thresholds make sense for VP8. | 376 const int kBadQpThreshold = kMaxQp - kMaxQp / 4; |
pbos-webrtc
2016/01/18 10:33:07
I think this should just be hard-coded as another
AlexG
2016/01/19 22:13:41
Done.
| |
374 // This effectively disables high QP as VP8 QP can't go above this | 377 quality_scaler_.Init( |
375 // threshold. | 378 kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false); |
376 const int kDisabledBadQpThreshold = kMaxQp + 1; | |
377 quality_scaler_.Init(kMaxQp / kLowQpThresholdDenominator, | |
378 kDisabledBadQpThreshold, true); | |
379 } else if (codecType_ == kVideoCodecH264) { | 379 } else if (codecType_ == kVideoCodecH264) { |
380 // H264 QP is in the range [0, 51]. | 380 // H264 QP is in the range [0, 51]. |
381 const int kMaxQp = 51; | 381 const int kMaxQp = 51; |
382 const int kBadQpThreshold = 40; | 382 const int kBadQpThreshold = 40; |
383 quality_scaler_.Init(kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, | 383 quality_scaler_.Init( |
384 false); | 384 kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false); |
385 } else { | 385 } else { |
386 // When adding codec support to additional hardware codecs, also configure | 386 // When adding codec support to additional hardware codecs, also configure |
387 // their QP thresholds for scaling. | 387 // their QP thresholds for scaling. |
388 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; | 388 RTC_NOTREACHED() << "Unsupported codec without configured QP thresholds."; |
389 } | 389 } |
390 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight); | 390 quality_scaler_.SetMinResolution(kMinWidth, kMinHeight); |
391 quality_scaler_.ReportFramerate(codec_settings->maxFramerate); | 391 quality_scaler_.ReportFramerate(codec_settings->maxFramerate); |
392 } | 392 } |
393 return codec_thread_->Invoke<int32_t>( | 393 return codec_thread_->Invoke<int32_t>( |
394 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, | 394 Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread, |
(...skipping 27 matching lines...) Expand all Loading... | |
422 Bind(&MediaCodecVideoEncoder::ReleaseOnCodecThread, this)); | 422 Bind(&MediaCodecVideoEncoder::ReleaseOnCodecThread, this)); |
423 } | 423 } |
424 | 424 |
425 int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */, | 425 int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */, |
426 int64_t /* rtt */) { | 426 int64_t /* rtt */) { |
427 return WEBRTC_VIDEO_CODEC_OK; | 427 return WEBRTC_VIDEO_CODEC_OK; |
428 } | 428 } |
429 | 429 |
430 int32_t MediaCodecVideoEncoder::SetRates(uint32_t new_bit_rate, | 430 int32_t MediaCodecVideoEncoder::SetRates(uint32_t new_bit_rate, |
431 uint32_t frame_rate) { | 431 uint32_t frame_rate) { |
432 if (scale_) | |
433 quality_scaler_.ReportFramerate(frame_rate); | |
434 | |
435 return codec_thread_->Invoke<int32_t>( | 432 return codec_thread_->Invoke<int32_t>( |
436 Bind(&MediaCodecVideoEncoder::SetRatesOnCodecThread, | 433 Bind(&MediaCodecVideoEncoder::SetRatesOnCodecThread, |
437 this, | 434 this, |
438 new_bit_rate, | 435 new_bit_rate, |
439 frame_rate)); | 436 frame_rate)); |
440 } | 437 } |
441 | 438 |
442 void MediaCodecVideoEncoder::OnMessage(rtc::Message* msg) { | 439 void MediaCodecVideoEncoder::OnMessage(rtc::Message* msg) { |
443 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 440 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
444 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 441 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 } | 488 } |
492 | 489 |
493 width_ = width; | 490 width_ = width; |
494 height_ = height; | 491 height_ = height; |
495 last_set_bitrate_kbps_ = kbps; | 492 last_set_bitrate_kbps_ = kbps; |
496 last_set_fps_ = (fps < MAX_VIDEO_FPS) ? fps : MAX_VIDEO_FPS; | 493 last_set_fps_ = (fps < MAX_VIDEO_FPS) ? fps : MAX_VIDEO_FPS; |
497 yuv_size_ = width_ * height_ * 3 / 2; | 494 yuv_size_ = width_ * height_ * 3 / 2; |
498 frames_received_ = 0; | 495 frames_received_ = 0; |
499 frames_encoded_ = 0; | 496 frames_encoded_ = 0; |
500 frames_dropped_ = 0; | 497 frames_dropped_ = 0; |
498 frames_dropped_q_full_ = 0; | |
501 frames_in_queue_ = 0; | 499 frames_in_queue_ = 0; |
502 current_timestamp_us_ = 0; | 500 current_timestamp_us_ = 0; |
503 start_time_ms_ = GetCurrentTimeMs(); | 501 start_time_ms_ = GetCurrentTimeMs(); |
504 current_frames_ = 0; | 502 current_frames_ = 0; |
505 current_bytes_ = 0; | 503 current_bytes_ = 0; |
506 current_acc_qp_ = 0; | 504 current_acc_qp_ = 0; |
507 current_encoding_time_ms_ = 0; | 505 current_encoding_time_ms_ = 0; |
508 last_input_timestamp_ms_ = -1; | 506 last_input_timestamp_ms_ = -1; |
509 last_output_timestamp_ms_ = -1; | 507 last_output_timestamp_ms_ = -1; |
510 output_timestamp_ = 0; | 508 output_timestamp_ = 0; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; | 605 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; |
608 | 606 |
609 // Check if we accumulated too many frames in encoder input buffers | 607 // Check if we accumulated too many frames in encoder input buffers |
610 // or the encoder latency exceeds 70 ms and drop frame if so. | 608 // or the encoder latency exceeds 70 ms and drop frame if so. |
611 if (frames_in_queue_ > 0 && last_input_timestamp_ms_ >= 0) { | 609 if (frames_in_queue_ > 0 && last_input_timestamp_ms_ >= 0) { |
612 int encoder_latency_ms = last_input_timestamp_ms_ - | 610 int encoder_latency_ms = last_input_timestamp_ms_ - |
613 last_output_timestamp_ms_; | 611 last_output_timestamp_ms_; |
614 if (frames_in_queue_ > MAX_ENCODER_Q_SIZE || | 612 if (frames_in_queue_ > MAX_ENCODER_Q_SIZE || |
615 encoder_latency_ms > MAX_ENCODER_LATENCY_MS) { | 613 encoder_latency_ms > MAX_ENCODER_LATENCY_MS) { |
616 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms << | 614 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms << |
617 " ms. Q size: " << frames_in_queue_; | 615 " ms. Q size: " << frames_in_queue_ << ". Consecutive drops: " << |
616 frames_dropped_q_full_; | |
618 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 617 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
618 frames_dropped_q_full_++; | |
619 if (frames_dropped_q_full_ >= MAX_DROPPED_FRAMES) { | |
620 ALOGE << "Encoder got stuck. Reset."; | |
621 ResetCodecOnCodecThread(); | |
622 return WEBRTC_VIDEO_CODEC_ERROR; | |
623 } | |
619 OnDroppedFrame(); | 624 OnDroppedFrame(); |
620 return WEBRTC_VIDEO_CODEC_OK; | 625 return WEBRTC_VIDEO_CODEC_OK; |
621 } | 626 } |
622 } | 627 } |
628 frames_dropped_q_full_ = 0; | |
623 | 629 |
624 VideoFrame input_frame = frame; | 630 VideoFrame input_frame = frame; |
625 if (scale_) { | 631 if (scale_) { |
626 // Check framerate before spatial resolution change. | 632 // Check framerate before spatial resolution change. |
627 quality_scaler_.OnEncodeFrame(frame); | 633 quality_scaler_.OnEncodeFrame(frame); |
628 const webrtc::QualityScaler::Resolution scaled_resolution = | 634 const webrtc::QualityScaler::Resolution scaled_resolution = |
629 quality_scaler_.GetScaledResolution(); | 635 quality_scaler_.GetScaledResolution(); |
630 if (scaled_resolution.width != frame.width() || | 636 if (scaled_resolution.width != frame.width() || |
631 scaled_resolution.height != frame.height()) { | 637 scaled_resolution.height != frame.height()) { |
632 if (frame.native_handle() != nullptr) { | 638 if (frame.native_handle() != nullptr) { |
(...skipping 22 matching lines...) Expand all Loading... | |
655 bool encode_status = true; | 661 bool encode_status = true; |
656 if (!input_frame.native_handle()) { | 662 if (!input_frame.native_handle()) { |
657 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, | 663 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, |
658 j_dequeue_input_buffer_method_); | 664 j_dequeue_input_buffer_method_); |
659 CHECK_EXCEPTION(jni); | 665 CHECK_EXCEPTION(jni); |
660 if (j_input_buffer_index == -1) { | 666 if (j_input_buffer_index == -1) { |
661 // Video codec falls behind - no input buffer available. | 667 // Video codec falls behind - no input buffer available. |
662 ALOGW << "Encoder drop frame - no input buffers available"; | 668 ALOGW << "Encoder drop frame - no input buffers available"; |
663 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; | 669 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; |
664 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin()); | 670 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin()); |
671 OnDroppedFrame(); | |
665 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. | 672 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. |
666 } | 673 } |
667 if (j_input_buffer_index == -2) { | 674 if (j_input_buffer_index == -2) { |
668 ResetCodecOnCodecThread(); | 675 ResetCodecOnCodecThread(); |
669 return WEBRTC_VIDEO_CODEC_ERROR; | 676 return WEBRTC_VIDEO_CODEC_ERROR; |
670 } | 677 } |
671 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, | 678 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, |
672 j_input_buffer_index); | 679 j_input_buffer_index); |
673 } else { | 680 } else { |
674 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); | 681 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
808 | 815 |
809 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, | 816 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, |
810 uint32_t frame_rate) { | 817 uint32_t frame_rate) { |
811 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); | 818 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); |
812 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? | 819 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? |
813 frame_rate : MAX_ALLOWED_VIDEO_FPS; | 820 frame_rate : MAX_ALLOWED_VIDEO_FPS; |
814 if (last_set_bitrate_kbps_ == new_bit_rate && | 821 if (last_set_bitrate_kbps_ == new_bit_rate && |
815 last_set_fps_ == frame_rate) { | 822 last_set_fps_ == frame_rate) { |
816 return WEBRTC_VIDEO_CODEC_OK; | 823 return WEBRTC_VIDEO_CODEC_OK; |
817 } | 824 } |
825 if (scale_) { | |
826 quality_scaler_.ReportFramerate(frame_rate); | |
827 } | |
818 JNIEnv* jni = AttachCurrentThreadIfNeeded(); | 828 JNIEnv* jni = AttachCurrentThreadIfNeeded(); |
819 ScopedLocalRefFrame local_ref_frame(jni); | 829 ScopedLocalRefFrame local_ref_frame(jni); |
820 if (new_bit_rate > 0) { | 830 if (new_bit_rate > 0) { |
821 last_set_bitrate_kbps_ = new_bit_rate; | 831 last_set_bitrate_kbps_ = new_bit_rate; |
822 } | 832 } |
823 if (frame_rate > 0) { | 833 if (frame_rate > 0) { |
824 last_set_fps_ = frame_rate; | 834 last_set_fps_ = frame_rate; |
825 } | 835 } |
826 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, | 836 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, |
827 j_set_rates_method_, | 837 j_set_rates_method_, |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1206 } | 1216 } |
1207 | 1217 |
1208 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( | 1218 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( |
1209 webrtc::VideoEncoder* encoder) { | 1219 webrtc::VideoEncoder* encoder) { |
1210 ALOGD << "Destroy video encoder."; | 1220 ALOGD << "Destroy video encoder."; |
1211 delete encoder; | 1221 delete encoder; |
1212 } | 1222 } |
1213 | 1223 |
1214 } // namespace webrtc_jni | 1224 } // namespace webrtc_jni |
1215 | 1225 |
OLD | NEW |