Chromium Code Reviews| 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 |