| Index: talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| index e87abaf5a5d5a74ce6063aba938b6af6214ac9c2..edaf603d212db880d30974e325c1ce65016922b7 100644
|
| --- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| +++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| @@ -78,7 +78,9 @@ namespace webrtc_jni {
|
| #define MAX_ENCODER_Q_SIZE 2
|
| // Maximum allowed latency in ms.
|
| #define MAX_ENCODER_LATENCY_MS 70
|
| -
|
| +// Maximum amount of dropped frames caused by full encoder queue - exceeding
|
| +// this threshold means that encoder probably got stuck and need to be reset.
|
| +#define ENCODER_STALL_FRAMEDROP_THRESHOLD 60
|
|
|
| // Logging macros.
|
| #define TAG_ENCODER "MediaCodecVideoEncoder"
|
| @@ -227,7 +229,9 @@ class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
|
| int64_t current_timestamp_us_; // Current frame timestamps in us.
|
| int frames_received_; // Number of frames received by encoder.
|
| int frames_encoded_; // Number of frames encoded by encoder.
|
| - int frames_dropped_; // Number of frames dropped by encoder.
|
| + int frames_dropped_media_encoder_; // Number of frames dropped by encoder.
|
| + // Number of dropped frames caused by full queue.
|
| + int consecutive_full_queue_frame_drops_;
|
| int frames_in_queue_; // Number of frames in encoder queue.
|
| int64_t start_time_ms_; // Start time for statistics.
|
| int current_frames_; // Number of frames in the current statistics interval.
|
| @@ -385,18 +389,15 @@ int32_t MediaCodecVideoEncoder::InitEncode(
|
| // always = 127. Note that in SW, QP is that of the user-level range [0,
|
| // 63].
|
| const int kMaxQp = 127;
|
| - // TODO(pbos): Investigate whether high-QP thresholds make sense for VP8.
|
| - // This effectively disables high QP as VP8 QP can't go above this
|
| - // threshold.
|
| - const int kDisabledBadQpThreshold = kMaxQp + 1;
|
| - quality_scaler_.Init(kMaxQp / kLowQpThresholdDenominator,
|
| - kDisabledBadQpThreshold, true);
|
| + const int kBadQpThreshold = 95;
|
| + quality_scaler_.Init(
|
| + kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false);
|
| } else if (codecType_ == kVideoCodecH264) {
|
| // H264 QP is in the range [0, 51].
|
| const int kMaxQp = 51;
|
| const int kBadQpThreshold = 40;
|
| - quality_scaler_.Init(kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold,
|
| - false);
|
| + quality_scaler_.Init(
|
| + kMaxQp / kLowQpThresholdDenominator, kBadQpThreshold, false);
|
| } else {
|
| // When adding codec support to additional hardware codecs, also configure
|
| // their QP thresholds for scaling.
|
| @@ -444,9 +445,6 @@ int32_t MediaCodecVideoEncoder::SetChannelParameters(uint32_t /* packet_loss */,
|
|
|
| int32_t MediaCodecVideoEncoder::SetRates(uint32_t new_bit_rate,
|
| uint32_t frame_rate) {
|
| - if (scale_)
|
| - quality_scaler_.ReportFramerate(frame_rate);
|
| -
|
| return codec_thread_->Invoke<int32_t>(
|
| Bind(&MediaCodecVideoEncoder::SetRatesOnCodecThread,
|
| this,
|
| @@ -512,7 +510,8 @@ int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
|
| yuv_size_ = width_ * height_ * 3 / 2;
|
| frames_received_ = 0;
|
| frames_encoded_ = 0;
|
| - frames_dropped_ = 0;
|
| + frames_dropped_media_encoder_ = 0;
|
| + consecutive_full_queue_frame_drops_ = 0;
|
| frames_in_queue_ = 0;
|
| current_timestamp_us_ = 0;
|
| start_time_ms_ = GetCurrentTimeMs();
|
| @@ -634,6 +633,7 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
|
| ALOGW << "Encoder drop frame - failed callback.";
|
| drop_next_input_frame_ = false;
|
| current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
|
| + frames_dropped_media_encoder_++;
|
| OnDroppedFrame();
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
| @@ -648,12 +648,22 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
|
| if (frames_in_queue_ > MAX_ENCODER_Q_SIZE ||
|
| encoder_latency_ms > MAX_ENCODER_LATENCY_MS) {
|
| ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms <<
|
| - " ms. Q size: " << frames_in_queue_;
|
| + " ms. Q size: " << frames_in_queue_ << ". Consecutive drops: " <<
|
| + consecutive_full_queue_frame_drops_;
|
| current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
|
| + consecutive_full_queue_frame_drops_++;
|
| + if (consecutive_full_queue_frame_drops_ >=
|
| + ENCODER_STALL_FRAMEDROP_THRESHOLD) {
|
| + ALOGE << "Encoder got stuck. Reset.";
|
| + ResetCodecOnCodecThread();
|
| + return WEBRTC_VIDEO_CODEC_ERROR;
|
| + }
|
| + frames_dropped_media_encoder_++;
|
| OnDroppedFrame();
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
| }
|
| + consecutive_full_queue_frame_drops_ = 0;
|
|
|
| VideoFrame input_frame = frame;
|
| if (scale_) {
|
| @@ -695,8 +705,10 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
|
| if (j_input_buffer_index == -1) {
|
| // Video codec falls behind - no input buffer available.
|
| ALOGW << "Encoder drop frame - no input buffers available";
|
| - current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
|
| frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
|
| + current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
|
| + frames_dropped_media_encoder_++;
|
| + OnDroppedFrame();
|
| return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
|
| }
|
| if (j_input_buffer_index == -2) {
|
| @@ -827,7 +839,7 @@ int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
|
| JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
| ALOGD << "EncoderReleaseOnCodecThread: Frames received: " <<
|
| frames_received_ << ". Encoded: " << frames_encoded_ <<
|
| - ". Dropped: " << frames_dropped_;
|
| + ". Dropped: " << frames_dropped_media_encoder_;
|
| ScopedLocalRefFrame local_ref_frame(jni);
|
| for (size_t i = 0; i < input_buffers_.size(); ++i)
|
| jni->DeleteGlobalRef(input_buffers_[i]);
|
| @@ -850,6 +862,9 @@ int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
|
| last_set_fps_ == frame_rate) {
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
| + if (scale_) {
|
| + quality_scaler_.ReportFramerate(frame_rate);
|
| + }
|
| JNIEnv* jni = AttachCurrentThreadIfNeeded();
|
| ScopedLocalRefFrame local_ref_frame(jni);
|
| if (new_bit_rate > 0) {
|
| @@ -1135,7 +1150,6 @@ int32_t MediaCodecVideoEncoder::NextNaluPosition(
|
| }
|
|
|
| void MediaCodecVideoEncoder::OnDroppedFrame() {
|
| - frames_dropped_++;
|
| // Report dropped frame to quality_scaler_.
|
| if (scale_)
|
| quality_scaler_.ReportDroppedFrame();
|
|
|