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

Side by Side 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, 3 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 unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/video/video_encoder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 #define ALOGV(...) 79 #define ALOGV(...)
80 #endif 80 #endif
81 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER) 81 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER)
82 #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER) 82 #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER)
83 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER) 83 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER)
84 84
85 namespace { 85 namespace {
86 // Maximum time limit between incoming frames before requesting a key frame. 86 // Maximum time limit between incoming frames before requesting a key frame.
87 const size_t kFrameDiffThresholdMs = 1100; 87 const size_t kFrameDiffThresholdMs = 1100;
88 const int kMinKeyFrameInterval = 2; 88 const int kMinKeyFrameInterval = 2;
89 // Maximum number of encoder resets before falling back to a software
90 // implementation.
91 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.
89 } // namespace 92 } // namespace
90 93
91 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses 94 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses
92 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) 95 // Android's MediaCodec SDK API behind the scenes to implement (hopefully)
93 // HW-backed video encode. This C++ class is implemented as a very thin shim, 96 // HW-backed video encode. This C++ class is implemented as a very thin shim,
94 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. 97 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder.
95 // MediaCodecVideoEncoder is created, operated, and destroyed on a single 98 // MediaCodecVideoEncoder is created, operated, and destroyed on a single
96 // thread, currently the libjingle Worker thread. 99 // thread, currently the libjingle Worker thread.
97 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, 100 class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
98 public rtc::MessageHandler { 101 public rtc::MessageHandler {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // EGL context - owned by factory, should not be allocated/destroyed 278 // EGL context - owned by factory, should not be allocated/destroyed
276 // by MediaCodecVideoEncoder. 279 // by MediaCodecVideoEncoder.
277 jobject egl_context_; 280 jobject egl_context_;
278 281
279 // Temporary fix for VP8. 282 // Temporary fix for VP8.
280 // Sends a key frame if frames are largely spaced apart (possibly 283 // Sends a key frame if frames are largely spaced apart (possibly
281 // corresponding to a large image change). 284 // corresponding to a large image change).
282 int64_t last_frame_received_ms_; 285 int64_t last_frame_received_ms_;
283 int frames_received_since_last_key_; 286 int frames_received_since_last_key_;
284 webrtc::VideoCodecMode codec_mode_; 287 webrtc::VideoCodecMode codec_mode_;
288
289 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.
290 int encoder_reset_counter_;
285 }; 291 };
286 292
287 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() { 293 MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
288 // Call Release() to ensure no more callbacks to us after we are deleted. 294 // Call Release() to ensure no more callbacks to us after we are deleted.
289 Release(); 295 Release();
290 } 296 }
291 297
292 MediaCodecVideoEncoder::MediaCodecVideoEncoder( 298 MediaCodecVideoEncoder::MediaCodecVideoEncoder(
293 JNIEnv* jni, VideoCodecType codecType, jobject egl_context) : 299 JNIEnv* jni, VideoCodecType codecType, jobject egl_context) :
294 codecType_(codecType), 300 codecType_(codecType),
295 callback_(NULL), 301 callback_(NULL),
296 codec_thread_(new Thread()), 302 codec_thread_(new Thread()),
297 j_media_codec_video_encoder_class_( 303 j_media_codec_video_encoder_class_(
298 jni, 304 jni,
299 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")), 305 FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")),
300 j_media_codec_video_encoder_( 306 j_media_codec_video_encoder_(
301 jni, 307 jni,
302 jni->NewObject(*j_media_codec_video_encoder_class_, 308 jni->NewObject(*j_media_codec_video_encoder_class_,
303 GetMethodID(jni, 309 GetMethodID(jni,
304 *j_media_codec_video_encoder_class_, 310 *j_media_codec_video_encoder_class_,
305 "<init>", 311 "<init>",
306 "()V"))), 312 "()V"))),
307 inited_(false), 313 inited_(false),
308 use_surface_(false), 314 use_surface_(false),
309 picture_id_(0), 315 picture_id_(0),
310 egl_context_(egl_context) { 316 egl_context_(egl_context),
317 software_fallback_needed_(false),
318 encoder_reset_counter_(0) {
311 ScopedLocalRefFrame local_ref_frame(jni); 319 ScopedLocalRefFrame local_ref_frame(jni);
312 // It would be nice to avoid spinning up a new thread per MediaCodec, and 320 // It would be nice to avoid spinning up a new thread per MediaCodec, and
313 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug 321 // instead re-use e.g. the PeerConnectionFactory's |worker_thread_|, but bug
314 // 2732 means that deadlocks abound. This class synchronously trampolines 322 // 2732 means that deadlocks abound. This class synchronously trampolines
315 // to |codec_thread_|, so if anything else can be coming to _us_ from 323 // to |codec_thread_|, so if anything else can be coming to _us_ from
316 // |codec_thread_|, or from any thread holding the |_sendCritSect| described 324 // |codec_thread_|, or from any thread holding the |_sendCritSect| described
317 // in the bug, we have a problem. For now work around that with a dedicated 325 // in the bug, we have a problem. For now work around that with a dedicated
318 // thread. 326 // thread.
319 codec_thread_->SetName("MediaCodecVideoEncoder", NULL); 327 codec_thread_->SetName("MediaCodecVideoEncoder", NULL);
320 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoEncoder"; 328 RTC_CHECK(codec_thread_->Start()) << "Failed to start MediaCodecVideoEncoder";
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 } 495 }
488 496
489 // Call log statistics here so it's called even if no frames are being 497 // Call log statistics here so it's called even if no frames are being
490 // delivered. 498 // delivered.
491 LogStatistics(false); 499 LogStatistics(false);
492 } 500 }
493 501
494 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { 502 bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() {
495 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 503 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
496 ALOGE << "ResetOnCodecThread"; 504 ALOGE << "ResetOnCodecThread";
497 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK || 505 encoder_reset_counter_++;
498 InitEncodeOnCodecThread(width_, height_, 0, 0, false) != 506 if (ReleaseOnCodecThread() != WEBRTC_VIDEO_CODEC_OK) {
499 WEBRTC_VIDEO_CODEC_OK) { 507 LOG(LS_ERROR) << "Releasing codec failed. Fallback to SW encoder.";
500 // TODO(fischman): wouldn't it be nice if there was a way to gracefully 508 software_fallback_needed_ = true;
501 // degrade to a SW encoder at this point? There isn't one AFAICT :( 509 return false;
502 // https://code.google.com/p/webrtc/issues/detail?id=2920 510 }
511 if (encoder_reset_counter_ > kMaxEncoderResetsBeforeFallback) {
512 LOG(LS_ERROR) << "Codec has failed too many times. Fallback to SW encoder.";
513 software_fallback_needed_ = true;
514 return false;
515 }
516 if (InitEncodeOnCodecThread(width_, height_, 0, 0, false) !=
517 WEBRTC_VIDEO_CODEC_OK) {
518 LOG(LS_ERROR) << "Init encode failed. Fallback to SW encoder.";
519 software_fallback_needed_ = true;
503 return false; 520 return false;
504 } 521 }
505 return true; 522 return true;
506 } 523 }
507 524
508 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread( 525 int32_t MediaCodecVideoEncoder::InitEncodeOnCodecThread(
509 int width, int height, int kbps, int fps, bool use_surface) { 526 int width, int height, int kbps, int fps, bool use_surface) {
510 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 527 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
528 if (software_fallback_needed_) {
529 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
530 }
511 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set."; 531 RTC_CHECK(!use_surface || egl_context_ != nullptr) << "EGL context not set.";
512 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 532 JNIEnv* jni = AttachCurrentThreadIfNeeded();
513 ScopedLocalRefFrame local_ref_frame(jni); 533 ScopedLocalRefFrame local_ref_frame(jni);
514 534
515 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " << 535 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " <<
516 width << " x " << height << ". Bitrate: " << kbps << 536 width << " x " << height << ". Bitrate: " << kbps <<
517 " kbps. Fps: " << fps; 537 " kbps. Fps: " << fps;
518 if (kbps == 0) { 538 if (kbps == 0) {
519 kbps = last_set_bitrate_kbps_; 539 kbps = last_set_bitrate_kbps_;
520 } 540 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 623
604 inited_ = true; 624 inited_ = true;
605 return WEBRTC_VIDEO_CODEC_OK; 625 return WEBRTC_VIDEO_CODEC_OK;
606 } 626 }
607 627
608 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread( 628 int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
609 const webrtc::VideoFrame& frame, 629 const webrtc::VideoFrame& frame,
610 const std::vector<webrtc::FrameType>* frame_types, 630 const std::vector<webrtc::FrameType>* frame_types,
611 const int64_t frame_input_time_ms) { 631 const int64_t frame_input_time_ms) {
612 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 632 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
633 if (software_fallback_needed_) {
634 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
635 }
613 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 636 JNIEnv* jni = AttachCurrentThreadIfNeeded();
614 ScopedLocalRefFrame local_ref_frame(jni); 637 ScopedLocalRefFrame local_ref_frame(jni);
615 638
616 if (!inited_) { 639 if (!inited_) {
617 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 640 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
618 } 641 }
619 642
620 bool send_key_frame = false; 643 bool send_key_frame = false;
621 if (codec_mode_ == webrtc::kRealtimeVideo) { 644 if (codec_mode_ == webrtc::kRealtimeVideo) {
622 ++frames_received_since_last_key_; 645 ++frames_received_since_last_key_;
623 int64_t now_ms = rtc::TimeMillis(); 646 int64_t now_ms = rtc::TimeMillis();
624 if (last_frame_received_ms_ != -1 && 647 if (last_frame_received_ms_ != -1 &&
625 (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) { 648 (now_ms - last_frame_received_ms_) > kFrameDiffThresholdMs) {
626 // Add limit to prevent triggering a key for every frame for very low 649 // Add limit to prevent triggering a key for every frame for very low
627 // framerates (e.g. if frame diff > kFrameDiffThresholdMs). 650 // framerates (e.g. if frame diff > kFrameDiffThresholdMs).
628 if (frames_received_since_last_key_ > kMinKeyFrameInterval) { 651 if (frames_received_since_last_key_ > kMinKeyFrameInterval) {
629 ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_); 652 ALOGD << "Send key, frame diff: " << (now_ms - last_frame_received_ms_);
630 send_key_frame = true; 653 send_key_frame = true;
631 } 654 }
632 frames_received_since_last_key_ = 0; 655 frames_received_since_last_key_ = 0;
633 } 656 }
634 last_frame_received_ms_ = now_ms; 657 last_frame_received_ms_ = now_ms;
635 } 658 }
636 659
637 frames_received_++; 660 frames_received_++;
638 if (!DeliverPendingOutputs(jni)) { 661 if (!DeliverPendingOutputs(jni)) {
639 if (!ResetCodecOnCodecThread()) 662 if (!ResetCodecOnCodecThread())
640 return WEBRTC_VIDEO_CODEC_ERROR; 663 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
664 : WEBRTC_VIDEO_CODEC_ERROR;
641 } 665 }
642 if (frames_encoded_ < kMaxEncodedLogFrames) { 666 if (frames_encoded_ < kMaxEncodedLogFrames) {
643 ALOGD << "Encoder frame in # " << (frames_received_ - 1) 667 ALOGD << "Encoder frame in # " << (frames_received_ - 1)
644 << ". TS: " << (int)(current_timestamp_us_ / 1000) 668 << ". TS: " << (int)(current_timestamp_us_ / 1000)
645 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_ 669 << ". Q: " << input_frame_infos_.size() << ". Fps: " << last_set_fps_
646 << ". Kbps: " << last_set_bitrate_kbps_; 670 << ". Kbps: " << last_set_bitrate_kbps_;
647 } 671 }
648 672
649 if (drop_next_input_frame_) { 673 if (drop_next_input_frame_) {
650 ALOGW << "Encoder drop frame - failed callback."; 674 ALOGW << "Encoder drop frame - failed callback.";
(...skipping 13 matching lines...) Expand all
664 << " frames in the queue, dropping" 688 << " frames in the queue, dropping"
665 << ". TS: " << (int)(current_timestamp_us_ / 1000) 689 << ". TS: " << (int)(current_timestamp_us_ / 1000)
666 << ". Fps: " << last_set_fps_ 690 << ". Fps: " << last_set_fps_
667 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_; 691 << ". Consecutive drops: " << consecutive_full_queue_frame_drops_;
668 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; 692 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
669 consecutive_full_queue_frame_drops_++; 693 consecutive_full_queue_frame_drops_++;
670 if (consecutive_full_queue_frame_drops_ >= 694 if (consecutive_full_queue_frame_drops_ >=
671 ENCODER_STALL_FRAMEDROP_THRESHOLD) { 695 ENCODER_STALL_FRAMEDROP_THRESHOLD) {
672 ALOGE << "Encoder got stuck. Reset."; 696 ALOGE << "Encoder got stuck. Reset.";
673 ResetCodecOnCodecThread(); 697 ResetCodecOnCodecThread();
674 return WEBRTC_VIDEO_CODEC_ERROR; 698 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
699 : WEBRTC_VIDEO_CODEC_ERROR;
675 } 700 }
676 frames_dropped_media_encoder_++; 701 frames_dropped_media_encoder_++;
677 OnDroppedFrameOnCodecThread(); 702 OnDroppedFrameOnCodecThread();
678 return WEBRTC_VIDEO_CODEC_OK; 703 return WEBRTC_VIDEO_CODEC_OK;
679 } 704 }
680 consecutive_full_queue_frame_drops_ = 0; 705 consecutive_full_queue_frame_drops_ = 0;
681 706
682 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer( 707 rtc::scoped_refptr<webrtc::VideoFrameBuffer> input_buffer(
683 frame.video_frame_buffer()); 708 frame.video_frame_buffer());
684 if (scale_) { 709 if (scale_) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 OnDroppedFrameOnCodecThread(); 750 OnDroppedFrameOnCodecThread();
726 } else { 751 } else {
727 // Input buffers are not ready after codec initialization, HW is still 752 // Input buffers are not ready after codec initialization, HW is still
728 // allocating thme - this is expected and should not result in drop 753 // allocating thme - this is expected and should not result in drop
729 // frame report. 754 // frame report.
730 frames_received_ = 0; 755 frames_received_ = 0;
731 } 756 }
732 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. 757 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
733 } else if (j_input_buffer_index == -2) { 758 } else if (j_input_buffer_index == -2) {
734 ResetCodecOnCodecThread(); 759 ResetCodecOnCodecThread();
735 return WEBRTC_VIDEO_CODEC_ERROR; 760 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
761 : WEBRTC_VIDEO_CODEC_ERROR;
736 } 762 }
737 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, 763 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame,
738 j_input_buffer_index); 764 j_input_buffer_index);
739 } else { 765 } else {
740 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); 766 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame);
741 } 767 }
742 768
743 if (!encode_status) { 769 if (!encode_status) {
744 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp(); 770 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp();
745 ResetCodecOnCodecThread(); 771 ResetCodecOnCodecThread();
746 return WEBRTC_VIDEO_CODEC_ERROR; 772 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
773 : WEBRTC_VIDEO_CODEC_ERROR;
747 } 774 }
748 775
749 // Save input image timestamps for later output. 776 // Save input image timestamps for later output.
750 input_frame_infos_.emplace_back( 777 input_frame_infos_.emplace_back(
751 frame_input_time_ms, input_frame.timestamp(), 778 frame_input_time_ms, input_frame.timestamp(),
752 input_frame.render_time_ms(), input_frame.rotation()); 779 input_frame.render_time_ms(), input_frame.rotation());
753 780
754 last_input_timestamp_ms_ = 781 last_input_timestamp_ms_ =
755 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; 782 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec;
756 783
757 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; 784 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
758 785
759 codec_thread_->Clear(this); 786 codec_thread_->Clear(this);
760 codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this); 787 codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
761 788
762 if (!DeliverPendingOutputs(jni)) { 789 if (!DeliverPendingOutputs(jni)) {
763 ALOGE << "Failed deliver pending outputs."; 790 ALOGE << "Failed deliver pending outputs.";
764 ResetCodecOnCodecThread(); 791 ResetCodecOnCodecThread();
765 return WEBRTC_VIDEO_CODEC_ERROR; 792 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
793 : WEBRTC_VIDEO_CODEC_ERROR;
766 } 794 }
767 return WEBRTC_VIDEO_CODEC_OK; 795 return WEBRTC_VIDEO_CODEC_OK;
768 } 796 }
769 797
770 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread( 798 bool MediaCodecVideoEncoder::MaybeReconfigureEncoderOnCodecThread(
771 const webrtc::VideoFrame& frame) { 799 const webrtc::VideoFrame& frame) {
772 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 800 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
773 801
774 const bool is_texture_frame = 802 const bool is_texture_frame =
775 frame.video_frame_buffer()->native_handle() != nullptr; 803 frame.video_frame_buffer()->native_handle() != nullptr;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 handle->oes_texture_id, 873 handle->oes_texture_id,
846 sampling_matrix, 874 sampling_matrix,
847 current_timestamp_us_); 875 current_timestamp_us_);
848 CHECK_EXCEPTION(jni); 876 CHECK_EXCEPTION(jni);
849 return encode_status; 877 return encode_status;
850 } 878 }
851 879
852 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread( 880 int32_t MediaCodecVideoEncoder::RegisterEncodeCompleteCallbackOnCodecThread(
853 webrtc::EncodedImageCallback* callback) { 881 webrtc::EncodedImageCallback* callback) {
854 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 882 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
883 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.
884 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
885 }
855 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 886 JNIEnv* jni = AttachCurrentThreadIfNeeded();
856 ScopedLocalRefFrame local_ref_frame(jni); 887 ScopedLocalRefFrame local_ref_frame(jni);
857 callback_ = callback; 888 callback_ = callback;
858 return WEBRTC_VIDEO_CODEC_OK; 889 return WEBRTC_VIDEO_CODEC_OK;
859 } 890 }
860 891
861 int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() { 892 int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
862 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 893 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
863 if (!inited_) { 894 if (!inited_) {
864 return WEBRTC_VIDEO_CODEC_OK; 895 return WEBRTC_VIDEO_CODEC_OK;
(...skipping 11 matching lines...) Expand all
876 rtc::MessageQueueManager::Clear(this); 907 rtc::MessageQueueManager::Clear(this);
877 inited_ = false; 908 inited_ = false;
878 use_surface_ = false; 909 use_surface_ = false;
879 ALOGD << "EncoderReleaseOnCodecThread done."; 910 ALOGD << "EncoderReleaseOnCodecThread done.";
880 return WEBRTC_VIDEO_CODEC_OK; 911 return WEBRTC_VIDEO_CODEC_OK;
881 } 912 }
882 913
883 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, 914 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
884 uint32_t frame_rate) { 915 uint32_t frame_rate) {
885 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 916 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
917 if (software_fallback_needed_) {
918 return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
919 }
886 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ? 920 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ?
887 frame_rate : MAX_ALLOWED_VIDEO_FPS; 921 frame_rate : MAX_ALLOWED_VIDEO_FPS;
888 if (last_set_bitrate_kbps_ == new_bit_rate && 922 if (last_set_bitrate_kbps_ == new_bit_rate &&
889 last_set_fps_ == frame_rate) { 923 last_set_fps_ == frame_rate) {
890 return WEBRTC_VIDEO_CODEC_OK; 924 return WEBRTC_VIDEO_CODEC_OK;
891 } 925 }
892 if (scale_) { 926 if (scale_) {
893 quality_scaler_.ReportFramerate(frame_rate); 927 quality_scaler_.ReportFramerate(frame_rate);
894 } 928 }
895 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 929 JNIEnv* jni = AttachCurrentThreadIfNeeded();
896 ScopedLocalRefFrame local_ref_frame(jni); 930 ScopedLocalRefFrame local_ref_frame(jni);
897 if (new_bit_rate > 0) { 931 if (new_bit_rate > 0) {
898 last_set_bitrate_kbps_ = new_bit_rate; 932 last_set_bitrate_kbps_ = new_bit_rate;
899 } 933 }
900 if (frame_rate > 0) { 934 if (frame_rate > 0) {
901 last_set_fps_ = frame_rate; 935 last_set_fps_ = frame_rate;
902 } 936 }
903 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_, 937 bool ret = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
904 j_set_rates_method_, 938 j_set_rates_method_,
905 last_set_bitrate_kbps_, 939 last_set_bitrate_kbps_,
906 last_set_fps_); 940 last_set_fps_);
907 CHECK_EXCEPTION(jni); 941 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.
908 if (!ret) { 942 if (!ret) {
909 ResetCodecOnCodecThread(); 943 ResetCodecOnCodecThread();
910 return WEBRTC_VIDEO_CODEC_ERROR; 944 return software_fallback_needed_ ? WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE
945 : WEBRTC_VIDEO_CODEC_ERROR;
911 } 946 }
912 return WEBRTC_VIDEO_CODEC_OK; 947 return WEBRTC_VIDEO_CODEC_OK;
913 } 948 }
914 949
915 int MediaCodecVideoEncoder::GetOutputBufferInfoIndex( 950 int MediaCodecVideoEncoder::GetOutputBufferInfoIndex(
916 JNIEnv* jni, 951 JNIEnv* jni,
917 jobject j_output_buffer_info) { 952 jobject j_output_buffer_info) {
918 return GetIntField(jni, j_output_buffer_info, j_info_index_field_); 953 return GetIntField(jni, j_output_buffer_info, j_info_index_field_);
919 } 954 }
920 955
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 return supported_codecs_; 1332 return supported_codecs_;
1298 } 1333 }
1299 1334
1300 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( 1335 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(
1301 webrtc::VideoEncoder* encoder) { 1336 webrtc::VideoEncoder* encoder) {
1302 ALOGD << "Destroy video encoder."; 1337 ALOGD << "Destroy video encoder.";
1303 delete encoder; 1338 delete encoder;
1304 } 1339 }
1305 1340
1306 } // namespace webrtc_jni 1341 } // namespace webrtc_jni
OLDNEW
« 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