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

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: Remove empty lines. 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') | webrtc/video/video_encoder.cc » ('J')
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..b75ba8fc5608d5a5295041697f7b942b01706256 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;
magjed_webrtc 2016/08/23 12:09:50 Now it will fall back to software the fourth time,
sakal 2016/08/23 12:26:51 Resetting the encoder is fairly quick so 3 resets
} // 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_;
+ 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;
magjed_webrtc 2016/08/23 12:09:50 Is it possible to remove |software_fallback_needed
sakal 2016/08/23 12:26:51 There would be some trouble. The codec might not b
+ 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);
@@ -852,6 +875,9 @@ bool MediaCodecVideoEncoder::EncodeTextureOnCodecThread(JNIEnv* jni,
int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread(
webrtc::EncodedImageCallback* callback) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
+ if (software_fallback_needed_) {
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
callback_ = callback;
@@ -883,6 +909,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 &&
« no previous file with comments | « no previous file | webrtc/video/video_encoder.cc » ('j') | webrtc/video/video_encoder.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698