| 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 7f558c0551b07e657d2163df58167a4734ecf06d..e87abaf5a5d5a74ce6063aba938b6af6214ac9c2 100644
|
| --- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| +++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
|
| @@ -35,6 +35,7 @@
|
| #include "webrtc/base/logging.h"
|
| #include "webrtc/base/thread.h"
|
| #include "webrtc/base/thread_checker.h"
|
| +#include "webrtc/common_types.h"
|
| #include "webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h"
|
| #include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
| #include "webrtc/modules/video_coding/utility/quality_scaler.h"
|
| @@ -91,6 +92,12 @@ namespace webrtc_jni {
|
| #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER)
|
| #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER)
|
|
|
| +namespace {
|
| +// Maximum time limit between incoming frames before requesting a key frame.
|
| +const size_t kFrameDiffThresholdMs = 1100;
|
| +const int kMinKeyFrameInterval = 2;
|
| +} // namespace
|
| +
|
| // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses
|
| // Android's MediaCodec SDK API behind the scenes to implement (hopefully)
|
| // HW-backed video encode. This C++ class is implemented as a very thin shim,
|
| @@ -259,6 +266,13 @@ class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
|
| // EGL context - owned by factory, should not be allocated/destroyed
|
| // by MediaCodecVideoEncoder.
|
| jobject egl_context_;
|
| +
|
| + // Temporary fix for VP8.
|
| + // Sends a key frame if frames are largely spaced apart (possibly
|
| + // corresponding to a large image change).
|
| + int64_t last_frame_received_ms_;
|
| + int frames_received_since_last_key_;
|
| + webrtc::VideoCodecMode codec_mode_;
|
| };
|
|
|
| MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
|
| @@ -360,6 +374,7 @@ int32_t MediaCodecVideoEncoder::InitEncode(
|
| << codecType_;
|
|
|
| ALOGD << "InitEncode request";
|
| + codec_mode_ = codec_settings->mode;
|
| scale_ = (codecType_ != kVideoCodecVP9) && (webrtc::field_trial::FindFullName(
|
| "WebRTC-MediaCodecVideoEncoder-AutomaticResize") == "Enabled");
|
| ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled");
|
| @@ -518,6 +533,8 @@ int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
|
| gof_.SetGofInfoVP9(webrtc::TemporalStructureMode::kTemporalStructureMode1);
|
| tl0_pic_idx_ = static_cast<uint8_t>(rand());
|
| gof_idx_ = 0;
|
| + last_frame_received_ms_ = -1;
|
| + frames_received_since_last_key_ = kMinKeyFrameInterval;
|
|
|
| // We enforce no extra stride/padding in the format creation step.
|
| jobject j_video_codec_enum = JavaEnumFromIndex(
|
| @@ -585,6 +602,23 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
|
| return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
| }
|
|
|
| + bool send_key_frame = false;
|
| + if (codecType_ == kVideoCodecVP8 && codec_mode_ == webrtc::kRealtimeVideo) {
|
| + ++frames_received_since_last_key_;
|
| + int64_t now_ms = GetCurrentTimeMs();
|
| + if (last_frame_received_ms_ != -1 &&
|
| + (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) {
|
| + // Add limit to prevent triggering a key for every frame for very low
|
| + // framerates (e.g. if frame diff > kFrameDiffThresholdMs).
|
| + if (frames_received_since_last_key_ > kMinKeyFrameInterval) {
|
| + ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_);
|
| + send_key_frame = true;
|
| + }
|
| + frames_received_since_last_key_ = 0;
|
| + }
|
| + last_frame_received_ms_ = now_ms;
|
| + }
|
| +
|
| frames_received_++;
|
| if (!DeliverPendingOutputs(jni)) {
|
| if (!ResetCodecOnCodecThread())
|
| @@ -651,7 +685,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
|
| // Save time when input frame is sent to the encoder input.
|
| frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
|
|
|
| - const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta;
|
| + const bool key_frame =
|
| + frame_types->front() != webrtc::kVideoFrameDelta || send_key_frame;
|
| bool encode_status = true;
|
| if (!input_frame.native_handle()) {
|
| int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_,
|
|
|