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

Unified Diff: webrtc/api/android/jni/androidmediaencoder_jni.cc

Issue 2263043003: Make MediaCodecEncoder fallback to a software encoder on failure. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE immediately. Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/video/video_encoder.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/api/android/jni/androidmediaencoder_jni.cc
diff --git a/webrtc/api/android/jni/androidmediaencoder_jni.cc b/webrtc/api/android/jni/androidmediaencoder_jni.cc
index 8d0d3b54bd512557401dcf652b94d62d930388f4..6d9067e570d14d74d3fc1d20fb507aa034945a60 100644
--- a/webrtc/api/android/jni/androidmediaencoder_jni.cc
+++ b/webrtc/api/android/jni/androidmediaencoder_jni.cc
@@ -86,6 +86,9 @@ namespace {
// Maximum time limit between incoming frames before requesting a key frame.
const size_t kFrameDiffThresholdMs = 1100;
const int kMinKeyFrameInterval = 2;
+// Maximum number of encoder resets before falling back to a software
+// implementation.
+const int kMaxEncoderResetsBeforeFallback = 3;
AlexG 2016/08/23 22:50:31 I don't think this is necessary - similarly to dec
sakal 2016/08/25 11:52:48 Done.
} // namespace
// MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses
@@ -282,6 +285,9 @@ class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
int64_t last_frame_received_ms_;
int frames_received_since_last_key_;
webrtc::VideoCodecMode codec_mode_;
+
+ bool software_fallback_needed_;
AlexG 2016/08/23 22:50:31 suggest to rename it to sw_fallback_required_ so w
sakal 2016/08/25 11:52:48 Done.
+ int encoder_reset_counter_;
};
MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
@@ -307,7 +313,9 @@ MediaCodecVideoEncoder::MediaCodecVideoEncoder(
inited_(false),
use_surface_(false),
picture_id_(0),
- egl_context_(egl_context) {
+ egl_context_(egl_context),
+ software_fallback_needed_(false),
+ encoder_reset_counter_(0) {
ScopedLocalRefFrame local_ref_frame(jni);
// It would be nice to avoid spinning up a new thread per MediaCodec, and
// instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug
@@ -494,12 +502,21 @@ void MediaCodecVideoEncoder::OnMessage(rtc::Message* msg) {
bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
ALOGE << "ResetOnCodecThread";
- if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK ||
- InitEncodeOnCodecThread(width_, height_, 0, 0, false) !=
- WEBRTC_VIDEO_CODEC_OK) {
- // TODO(fischman): wouldn't it be nice if there was a way to gracefully
- // degrade to a SW encoder at this point? There isn't one AFAICT :(
- // https://code.google.com/p/webrtc/issues/detail?id=2920
+ encoder_reset_counter_++;
+ if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK) {
+ LOG(LS_ERROR) << "Releasing codec failed. Fallback to SW encoder.";
+ software_fallback_needed_ = true;
+ return false;
+ }
+ if (encoder_reset_counter_ > kMaxEncoderResetsBeforeFallback) {
+ LOG(LS_ERROR) << "Codec has failed too many times. Fallback to SW encoder.";
+ software_fallback_needed_ = true;
+ return false;
+ }
+ if (InitEncodeOnCodecThread(width_, height_, 0, 0, false) !=
+ WEBRTC_VIDEO_CODEC_OK) {
+ LOG(LS_ERROR) << "Init encode failed. Fallback to SW encoder.";
+ software_fallback_needed_ = true;
return false;
}
return true;
@@ -508,6 +525,9 @@ bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() {
int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
int width, int height, int kbps, int fps, bool use_surface) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
+ if (software_fallback_needed_) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set.";
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
@@ -610,6 +630,9 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
const std::vector<webrtc::FrameType>* frame_types,
const int64_t frame_input_time_ms) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
+ if (software_fallback_needed_) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
@@ -637,7 +660,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
frames_received_++;
if (!DeliverPendingOutputs(jni)) {
if (!ResetCodecOnCodecThread())
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
if (frames_encoded_ < kMaxEncodedLogFrames) {
ALOGD << "Encoder frame in # " << (frames_received_ - 1)
@@ -671,7 +695,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
ENCODER_STALL_FRAMEDROP_THRESHOLD) {
ALOGE << "Encoder got stuck. Reset.";
ResetCodecOnCodecThread();
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
frames_dropped_media_encoder_++;
OnDroppedFrameOnCodecThread();
@@ -732,7 +757,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
} else if (j_input_buffer_index == -2) {
ResetCodecOnCodecThread();
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame,
j_input_buffer_index);
@@ -743,7 +769,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
if (!encode_status) {
ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp();
ResetCodecOnCodecThread();
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
// Save input image timestamps for later output.
@@ -762,7 +789,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
if (!DeliverPendingOutputs(jni)) {
ALOGE << "Failed deliver pending outputs.";
ResetCodecOnCodecThread();
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -852,6 +880,9 @@ bool MediaCodecVideoEncoder::EncodeTextureOnCodecThread(JNIEnv* jni,
int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread(
webrtc::EncodedImageCallback* callback) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
+ if (software_fallback_needed_) {
AlexG 2016/08/23 22:50:31 is this needed?
sakal 2016/08/25 11:52:48 I guess not. I just added it as a safety measure.
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
callback_ = callback;
@@ -883,6 +914,9 @@ int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
uint32_t frame_rate) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
+ if (software_fallback_needed_) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ?
frame_rate : MAX_ALLOWED_VIDEO_FPS;
if (last_set_bitrate_kbps_ == new_bit_rate &&
@@ -907,7 +941,8 @@ int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
CHECK_EXCEPTION(jni);
AlexG 2016/08/23 22:50:31 Replace all CHECK_EXCEPTION(jni) with CheckExcepti
sakal 2016/08/25 11:52:48 Done.
if (!ret) {
ResetCodecOnCodecThread();
- return WEBRTC_VIDEO_CODEC_ERROR;
+ return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
+ : WEBRTC_VIDEO_CODEC_ERROR;
}
return WEBRTC_VIDEO_CODEC_OK;
}
« no previous file with comments | « no previous file | webrtc/video/video_encoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698