OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |