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

Side by Side Diff: talk/app/webrtc/java/jni/androidmediaencoder_jni.cc

Issue 1587943004: Add QP statistics logging to Android HW encoder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Address comments Created 4 years, 11 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 | « talk/app/webrtc/java/jni/androidmediadecoder_jni.cc ('k') | no next file » | 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 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 64
65 // H.264 start code length. 65 // H.264 start code length.
66 #define H264_SC_LENGTH 4 66 #define H264_SC_LENGTH 4
67 // Maximum allowed NALUs in one output frame. 67 // Maximum allowed NALUs in one output frame.
68 #define MAX_NALUS_PERFRAME 32 68 #define MAX_NALUS_PERFRAME 32
69 // Maximum supported HW video encoder resolution. 69 // Maximum supported HW video encoder resolution.
70 #define MAX_VIDEO_WIDTH 1280 70 #define MAX_VIDEO_WIDTH 1280
71 #define MAX_VIDEO_HEIGHT 1280 71 #define MAX_VIDEO_HEIGHT 1280
72 // Maximum supported HW video encoder fps. 72 // Maximum supported HW video encoder fps.
73 #define MAX_VIDEO_FPS 30 73 #define MAX_VIDEO_FPS 30
74 // Maximum allowed fps value in SetRates() call.
75 #define MAX_ALLOWED_VIDEO_FPS 60
76 // Maximum allowed frames in encoder input queue.
77 #define MAX_ENCODER_Q_SIZE 2
78 // Maximum allowed latency in ms.
79 #define MAX_ENCODER_LATENCY_MS 70
80
81
82 // Logging macros.
83 #define TAG_ENCODER "MediaCodecVideoEncoder"
84 #ifdef TRACK_BUFFER_TIMING
85 #define ALOGV(...)
86 __android_log_print(ANDROID_LOG_VERBOSE, TAG_ENCODER, __VA_ARGS__)
87 #else
88 #define ALOGV(...)
89 #endif
90 #define ALOGD LOG_TAG(rtc::LS_INFO, TAG_ENCODER)
91 #define ALOGW LOG_TAG(rtc::LS_WARNING, TAG_ENCODER)
92 #define ALOGE LOG_TAG(rtc::LS_ERROR, TAG_ENCODER)
74 93
75 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses 94 // MediaCodecVideoEncoder is a webrtc::VideoEncoder implementation that uses
76 // Android's MediaCodec SDK API behind the scenes to implement (hopefully) 95 // Android's MediaCodec SDK API behind the scenes to implement (hopefully)
77 // 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,
78 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder. 97 // delegating all of the interesting work to org.webrtc.MediaCodecVideoEncoder.
79 // MediaCodecVideoEncoder is created, operated, and destroyed on a single 98 // MediaCodecVideoEncoder is created, operated, and destroyed on a single
80 // thread, currently the libjingle Worker thread. 99 // thread, currently the libjingle Worker thread.
81 class MediaCodecVideoEncoder : public webrtc::VideoEncoder, 100 class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
82 public rtc::MessageHandler { 101 public rtc::MessageHandler {
83 public: 102 public:
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps. 218 int last_set_bitrate_kbps_; // Last-requested bitrate in kbps.
200 int last_set_fps_; // Last-requested frame rate. 219 int last_set_fps_; // Last-requested frame rate.
201 int64_t current_timestamp_us_; // Current frame timestamps in us. 220 int64_t current_timestamp_us_; // Current frame timestamps in us.
202 int frames_received_; // Number of frames received by encoder. 221 int frames_received_; // Number of frames received by encoder.
203 int frames_encoded_; // Number of frames encoded by encoder. 222 int frames_encoded_; // Number of frames encoded by encoder.
204 int frames_dropped_; // Number of frames dropped by encoder. 223 int frames_dropped_; // Number of frames dropped by encoder.
205 int frames_in_queue_; // Number of frames in encoder queue. 224 int frames_in_queue_; // Number of frames in encoder queue.
206 int64_t start_time_ms_; // Start time for statistics. 225 int64_t start_time_ms_; // Start time for statistics.
207 int current_frames_; // Number of frames in the current statistics interval. 226 int current_frames_; // Number of frames in the current statistics interval.
208 int current_bytes_; // Encoded bytes in the current statistics interval. 227 int current_bytes_; // Encoded bytes in the current statistics interval.
228 int current_acc_qp_; // Accumulated QP in the current statistics interval.
209 int current_encoding_time_ms_; // Overall encoding time in the current second 229 int current_encoding_time_ms_; // Overall encoding time in the current second
210 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. 230 int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame.
211 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. 231 int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame.
212 std::vector<int32_t> timestamps_; // Video frames timestamp queue. 232 std::vector<int32_t> timestamps_; // Video frames timestamp queue.
213 std::vector<int64_t> render_times_ms_; // Video frames render time queue. 233 std::vector<int64_t> render_times_ms_; // Video frames render time queue.
214 std::vector<int64_t> frame_rtc_times_ms_; // Time when video frame is sent to 234 std::vector<int64_t> frame_rtc_times_ms_; // Time when video frame is sent to
215 // encoder input. 235 // encoder input.
216 int32_t output_timestamp_; // Last output frame timestamp from timestamps_ Q. 236 int32_t output_timestamp_; // Last output frame timestamp from timestamps_ Q.
217 int64_t output_render_time_ms_; // Last output frame render time from 237 int64_t output_render_time_ms_; // Last output frame render time from
218 // render_times_ms_ queue. 238 // render_times_ms_ queue.
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 480 JNIEnv* jni = AttachCurrentThreadIfNeeded();
461 ScopedLocalRefFrame local_ref_frame(jni); 481 ScopedLocalRefFrame local_ref_frame(jni);
462 482
463 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " << 483 ALOGD << "InitEncodeOnCodecThread Type: " << (int)codecType_ << ", " <<
464 width << " x " << height << ". Bitrate: " << kbps << 484 width << " x " << height << ". Bitrate: " << kbps <<
465 " kbps. Fps: " << fps; 485 " kbps. Fps: " << fps;
466 if (kbps == 0) { 486 if (kbps == 0) {
467 kbps = last_set_bitrate_kbps_; 487 kbps = last_set_bitrate_kbps_;
468 } 488 }
469 if (fps == 0) { 489 if (fps == 0) {
470 fps = last_set_fps_; 490 fps = MAX_VIDEO_FPS;
471 } 491 }
472 492
473 width_ = width; 493 width_ = width;
474 height_ = height; 494 height_ = height;
475 last_set_bitrate_kbps_ = kbps; 495 last_set_bitrate_kbps_ = kbps;
476 last_set_fps_ = fps; 496 last_set_fps_ = (fps < MAX_VIDEO_FPS) ? fps : MAX_VIDEO_FPS;
477 yuv_size_ = width_ * height_ * 3 / 2; 497 yuv_size_ = width_ * height_ * 3 / 2;
478 frames_received_ = 0; 498 frames_received_ = 0;
479 frames_encoded_ = 0; 499 frames_encoded_ = 0;
480 frames_dropped_ = 0; 500 frames_dropped_ = 0;
481 frames_in_queue_ = 0; 501 frames_in_queue_ = 0;
482 current_timestamp_us_ = 0; 502 current_timestamp_us_ = 0;
483 start_time_ms_ = GetCurrentTimeMs(); 503 start_time_ms_ = GetCurrentTimeMs();
484 current_frames_ = 0; 504 current_frames_ = 0;
485 current_bytes_ = 0; 505 current_bytes_ = 0;
506 current_acc_qp_ = 0;
486 current_encoding_time_ms_ = 0; 507 current_encoding_time_ms_ = 0;
487 last_input_timestamp_ms_ = -1; 508 last_input_timestamp_ms_ = -1;
488 last_output_timestamp_ms_ = -1; 509 last_output_timestamp_ms_ = -1;
489 output_timestamp_ = 0; 510 output_timestamp_ = 0;
490 output_render_time_ms_ = 0; 511 output_render_time_ms_ = 0;
491 timestamps_.clear(); 512 timestamps_.clear();
492 render_times_ms_.clear(); 513 render_times_ms_.clear();
493 frame_rtc_times_ms_.clear(); 514 frame_rtc_times_ms_.clear();
494 drop_next_input_frame_ = false; 515 drop_next_input_frame_ = false;
495 use_surface_ = use_surface; 516 use_surface_ = use_surface;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 583
563 if (!inited_) { 584 if (!inited_) {
564 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 585 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
565 } 586 }
566 587
567 frames_received_++; 588 frames_received_++;
568 if (!DeliverPendingOutputs(jni)) { 589 if (!DeliverPendingOutputs(jni)) {
569 if (!ResetCodecOnCodecThread()) 590 if (!ResetCodecOnCodecThread())
570 return WEBRTC_VIDEO_CODEC_ERROR; 591 return WEBRTC_VIDEO_CODEC_ERROR;
571 } 592 }
593 if (frames_encoded_ < kMaxEncodedLogFrames) {
594 ALOGD << "Encoder frame in # " << (frames_received_ - 1) << ". TS: " <<
595 (int)(current_timestamp_us_ / 1000) << ". Q: " << frames_in_queue_ <<
596 ". Fps: " << last_set_fps_ << ". Kbps: " << last_set_bitrate_kbps_;
597 }
572 598
573 if (drop_next_input_frame_) { 599 if (drop_next_input_frame_) {
574 ALOGW << "Encoder drop frame - failed callback."; 600 ALOGW << "Encoder drop frame - failed callback.";
575 drop_next_input_frame_ = false; 601 drop_next_input_frame_ = false;
602 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
603 OnDroppedFrame();
576 return WEBRTC_VIDEO_CODEC_OK; 604 return WEBRTC_VIDEO_CODEC_OK;
577 } 605 }
578 606
579 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count"; 607 RTC_CHECK(frame_types->size() == 1) << "Unexpected stream count";
580 608
609 // Check if we accumulated too many frames in encoder input buffers
610 // or the encoder latency exceeds 70 ms and drop frame if so.
611 if (frames_in_queue_ > 0 && last_input_timestamp_ms_ >= 0) {
612 int encoder_latency_ms = last_input_timestamp_ms_ -
613 last_output_timestamp_ms_;
614 if (frames_in_queue_ > MAX_ENCODER_Q_SIZE ||
615 encoder_latency_ms > MAX_ENCODER_LATENCY_MS) {
616 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms <<
617 " ms. Q size: " << frames_in_queue_;
618 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
619 OnDroppedFrame();
620 return WEBRTC_VIDEO_CODEC_OK;
621 }
622 }
623
581 VideoFrame input_frame = frame; 624 VideoFrame input_frame = frame;
582 if (scale_) { 625 if (scale_) {
583 // Check framerate before spatial resolution change. 626 // Check framerate before spatial resolution change.
584 quality_scaler_.OnEncodeFrame(frame); 627 quality_scaler_.OnEncodeFrame(frame);
585 const webrtc::QualityScaler::Resolution scaled_resolution = 628 const webrtc::QualityScaler::Resolution scaled_resolution =
586 quality_scaler_.GetScaledResolution(); 629 quality_scaler_.GetScaledResolution();
587 if (scaled_resolution.width != frame.width() || 630 if (scaled_resolution.width != frame.width() ||
588 scaled_resolution.height != frame.height()) { 631 scaled_resolution.height != frame.height()) {
589 if (frame.native_handle() != nullptr) { 632 if (frame.native_handle() != nullptr) {
590 rtc::scoped_refptr<webrtc::VideoFrameBuffer> scaled_buffer( 633 rtc::scoped_refptr<webrtc::VideoFrameBuffer> scaled_buffer(
591 static_cast<AndroidTextureBuffer*>( 634 static_cast<AndroidTextureBuffer*>(
592 frame.video_frame_buffer().get())->ScaleAndRotate( 635 frame.video_frame_buffer().get())->ScaleAndRotate(
593 scaled_resolution.width, 636 scaled_resolution.width,
594 scaled_resolution.height, 637 scaled_resolution.height,
595 webrtc::kVideoRotation_0)); 638 webrtc::kVideoRotation_0));
596 input_frame.set_video_frame_buffer(scaled_buffer); 639 input_frame.set_video_frame_buffer(scaled_buffer);
597 } else { 640 } else {
598 input_frame = quality_scaler_.GetScaledFrame(frame); 641 input_frame = quality_scaler_.GetScaledFrame(frame);
599 } 642 }
600 } 643 }
601 } 644 }
602 645
603 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) { 646 if (!MaybeReconfigureEncoderOnCodecThread(input_frame)) {
604 ALOGE << "Failed to reconfigure encoder."; 647 ALOGE << "Failed to reconfigure encoder.";
605 return WEBRTC_VIDEO_CODEC_ERROR; 648 return WEBRTC_VIDEO_CODEC_ERROR;
606 } 649 }
607 650
608 // Check if we accumulated too many frames in encoder input buffers 651 // Save time when input frame is sent to the encoder input.
609 // or the encoder latency exceeds 70 ms and drop frame if so. 652 frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
610 if (frames_in_queue_ > 0 && last_input_timestamp_ms_ >= 0) {
611 int encoder_latency_ms = last_input_timestamp_ms_ -
612 last_output_timestamp_ms_;
613 if (frames_in_queue_ > 2 || encoder_latency_ms > 70) {
614 ALOGD << "Drop frame - encoder is behind by " << encoder_latency_ms <<
615 " ms. Q size: " << frames_in_queue_;
616 frames_dropped_++;
617 // Report dropped frame to quality_scaler_.
618 OnDroppedFrame();
619 return WEBRTC_VIDEO_CODEC_OK;
620 }
621 }
622 653
623 const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta; 654 const bool key_frame = frame_types->front() != webrtc::kVideoFrameDelta;
624 bool encode_status = true; 655 bool encode_status = true;
625 if (!input_frame.native_handle()) { 656 if (!input_frame.native_handle()) {
626 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_, 657 int j_input_buffer_index = jni->CallIntMethod(*j_media_codec_video_encoder_,
627 j_dequeue_input_buffer_method_); 658 j_dequeue_input_buffer_method_);
628 CHECK_EXCEPTION(jni); 659 CHECK_EXCEPTION(jni);
629 if (j_input_buffer_index == -1) { 660 if (j_input_buffer_index == -1) {
630 // Video codec falls behind - no input buffer available. 661 // Video codec falls behind - no input buffer available.
631 ALOGW << "Encoder drop frame - no input buffers available"; 662 ALOGW << "Encoder drop frame - no input buffers available";
632 frames_dropped_++; 663 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
633 // Report dropped frame to quality_scaler_. 664 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
634 OnDroppedFrame();
635 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887. 665 return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
636 } 666 }
637 if (j_input_buffer_index == -2) { 667 if (j_input_buffer_index == -2) {
638 ResetCodecOnCodecThread(); 668 ResetCodecOnCodecThread();
639 return WEBRTC_VIDEO_CODEC_ERROR; 669 return WEBRTC_VIDEO_CODEC_ERROR;
640 } 670 }
641 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame, 671 encode_status = EncodeByteBufferOnCodecThread(jni, key_frame, input_frame,
642 j_input_buffer_index); 672 j_input_buffer_index);
643 } else { 673 } else {
644 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame); 674 encode_status = EncodeTextureOnCodecThread(jni, key_frame, input_frame);
645 } 675 }
646 676
647 if (!encode_status) { 677 if (!encode_status) {
648 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp(); 678 ALOGE << "Failed encode frame with timestamp: " << input_frame.timestamp();
649 ResetCodecOnCodecThread(); 679 ResetCodecOnCodecThread();
650 return WEBRTC_VIDEO_CODEC_ERROR; 680 return WEBRTC_VIDEO_CODEC_ERROR;
651 } 681 }
652 682
653 last_input_timestamp_ms_ = 683 last_input_timestamp_ms_ =
654 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec; 684 current_timestamp_us_ / rtc::kNumMicrosecsPerMillisec;
655 frames_in_queue_++; 685 frames_in_queue_++;
656 686
657 // Save input image timestamps for later output 687 // Save input image timestamps for later output
658 timestamps_.push_back(input_frame.timestamp()); 688 timestamps_.push_back(input_frame.timestamp());
659 render_times_ms_.push_back(input_frame.render_time_ms()); 689 render_times_ms_.push_back(input_frame.render_time_ms());
660 frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
661 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; 690 current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
662 691
663 if (!DeliverPendingOutputs(jni)) { 692 if (!DeliverPendingOutputs(jni)) {
664 ALOGE << "Failed deliver pending outputs."; 693 ALOGE << "Failed deliver pending outputs.";
665 ResetCodecOnCodecThread(); 694 ResetCodecOnCodecThread();
666 return WEBRTC_VIDEO_CODEC_ERROR; 695 return WEBRTC_VIDEO_CODEC_ERROR;
667 } 696 }
668 return WEBRTC_VIDEO_CODEC_OK; 697 return WEBRTC_VIDEO_CODEC_OK;
669 } 698 }
670 699
(...skipping 27 matching lines...) Expand all
698 727
699 return InitEncodeOnCodecThread(width_, height_, 0, 0 , is_texture_frame) == 728 return InitEncodeOnCodecThread(width_, height_, 0, 0 , is_texture_frame) ==
700 WEBRTC_VIDEO_CODEC_OK; 729 WEBRTC_VIDEO_CODEC_OK;
701 } 730 }
702 731
703 bool MediaCodecVideoEncoder::EncodeByteBufferOnCodecThread(JNIEnv* jni, 732 bool MediaCodecVideoEncoder::EncodeByteBufferOnCodecThread(JNIEnv* jni,
704 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index) { 733 bool key_frame, const webrtc::VideoFrame& frame, int input_buffer_index) {
705 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 734 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
706 RTC_CHECK(!use_surface_); 735 RTC_CHECK(!use_surface_);
707 736
708 ALOGV("Encoder frame in # %d. TS: %lld. Q: %d",
709 frames_received_ - 1, current_timestamp_us_ / 1000, frames_in_queue_);
710
711 jobject j_input_buffer = input_buffers_[input_buffer_index]; 737 jobject j_input_buffer = input_buffers_[input_buffer_index];
712 uint8_t* yuv_buffer = 738 uint8_t* yuv_buffer =
713 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer)); 739 reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_input_buffer));
714 CHECK_EXCEPTION(jni); 740 CHECK_EXCEPTION(jni);
715 RTC_CHECK(yuv_buffer) << "Indirect buffer??"; 741 RTC_CHECK(yuv_buffer) << "Indirect buffer??";
716 RTC_CHECK(!libyuv::ConvertFromI420( 742 RTC_CHECK(!libyuv::ConvertFromI420(
717 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane), 743 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane),
718 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane), 744 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane),
719 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane), 745 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane),
720 yuv_buffer, width_, width_, height_, encoder_fourcc_)) 746 yuv_buffer, width_, width_, height_, encoder_fourcc_))
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 rtc::MessageQueueManager::Clear(this); 802 rtc::MessageQueueManager::Clear(this);
777 inited_ = false; 803 inited_ = false;
778 use_surface_ = false; 804 use_surface_ = false;
779 ALOGD << "EncoderReleaseOnCodecThread done."; 805 ALOGD << "EncoderReleaseOnCodecThread done.";
780 return WEBRTC_VIDEO_CODEC_OK; 806 return WEBRTC_VIDEO_CODEC_OK;
781 } 807 }
782 808
783 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate, 809 int32_t MediaCodecVideoEncoder::SetRatesOnCodecThread(uint32_t new_bit_rate,
784 uint32_t frame_rate) { 810 uint32_t frame_rate) {
785 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); 811 RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
812 frame_rate = (frame_rate < MAX_ALLOWED_VIDEO_FPS) ?
813 frame_rate : MAX_ALLOWED_VIDEO_FPS;
786 if (last_set_bitrate_kbps_ == new_bit_rate && 814 if (last_set_bitrate_kbps_ == new_bit_rate &&
787 last_set_fps_ == frame_rate) { 815 last_set_fps_ == frame_rate) {
788 return WEBRTC_VIDEO_CODEC_OK; 816 return WEBRTC_VIDEO_CODEC_OK;
789 } 817 }
790 JNIEnv* jni = AttachCurrentThreadIfNeeded(); 818 JNIEnv* jni = AttachCurrentThreadIfNeeded();
791 ScopedLocalRefFrame local_ref_frame(jni); 819 ScopedLocalRefFrame local_ref_frame(jni);
792 if (new_bit_rate > 0) { 820 if (new_bit_rate > 0) {
793 last_set_bitrate_kbps_ = new_bit_rate; 821 last_set_bitrate_kbps_ = new_bit_rate;
794 } 822 }
795 if (frame_rate > 0) { 823 if (frame_rate > 0) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin()); 896 frame_rtc_times_ms_.erase(frame_rtc_times_ms_.begin());
869 frames_in_queue_--; 897 frames_in_queue_--;
870 } 898 }
871 899
872 // Extract payload. 900 // Extract payload.
873 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer); 901 size_t payload_size = jni->GetDirectBufferCapacity(j_output_buffer);
874 uint8_t* payload = reinterpret_cast<uint8_t*>( 902 uint8_t* payload = reinterpret_cast<uint8_t*>(
875 jni->GetDirectBufferAddress(j_output_buffer)); 903 jni->GetDirectBufferAddress(j_output_buffer));
876 CHECK_EXCEPTION(jni); 904 CHECK_EXCEPTION(jni);
877 905
878 ALOGV("Encoder frame out # %d. Key: %d. Size: %d. TS: %lld." 906 if (frames_encoded_ < kMaxEncodedLogFrames) {
879 " Latency: %lld. EncTime: %lld", 907 ALOGD << "Encoder frame out # " << frames_encoded_ << ". Key: " <<
880 frames_encoded_, key_frame, payload_size, 908 key_frame << ". Size: " << payload_size << ". TS: " <<
881 last_output_timestamp_ms_, 909 (int)last_output_timestamp_ms_ << ". Latency: " <<
882 last_input_timestamp_ms_ - last_output_timestamp_ms_, 910 (int)(last_input_timestamp_ms_ - last_output_timestamp_ms_) <<
883 frame_encoding_time_ms); 911 ". EncTime: " << frame_encoding_time_ms;
884
885 // Calculate and print encoding statistics - every 3 seconds.
886 frames_encoded_++;
887 current_frames_++;
888 current_bytes_ += payload_size;
889 current_encoding_time_ms_ += frame_encoding_time_ms;
890 int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
891 if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
892 current_frames_ > 0) {
893 ALOGD << "Encoded frames: " << frames_encoded_ << ". Bitrate: " <<
894 (current_bytes_ * 8 / statistic_time_ms) <<
895 ", target: " << last_set_bitrate_kbps_ << " kbps, fps: " <<
896 ((current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms)
897 << ", encTime: " <<
898 (current_encoding_time_ms_ / current_frames_) << " for last " <<
899 statistic_time_ms << " ms.";
900 start_time_ms_ = GetCurrentTimeMs();
901 current_frames_ = 0;
902 current_bytes_ = 0;
903 current_encoding_time_ms_ = 0;
904 } 912 }
905 913
906 // Callback - return encoded frame. 914 // Callback - return encoded frame.
907 int32_t callback_status = 0; 915 int32_t callback_status = 0;
908 if (callback_) { 916 if (callback_) {
909 scoped_ptr<webrtc::EncodedImage> image( 917 scoped_ptr<webrtc::EncodedImage> image(
910 new webrtc::EncodedImage(payload, payload_size, payload_size)); 918 new webrtc::EncodedImage(payload, payload_size, payload_size));
911 image->_encodedWidth = width_; 919 image->_encodedWidth = width_;
912 image->_encodedHeight = height_; 920 image->_encodedHeight = height_;
913 image->_timeStamp = output_timestamp_; 921 image->_timeStamp = output_timestamp_;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 webrtc::RTPFragmentationHeader header; 967 webrtc::RTPFragmentationHeader header;
960 memset(&header, 0, sizeof(header)); 968 memset(&header, 0, sizeof(header));
961 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) { 969 if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecVP9) {
962 header.VerifyAndAllocateFragmentationHeader(1); 970 header.VerifyAndAllocateFragmentationHeader(1);
963 header.fragmentationOffset[0] = 0; 971 header.fragmentationOffset[0] = 0;
964 header.fragmentationLength[0] = image->_length; 972 header.fragmentationLength[0] = image->_length;
965 header.fragmentationPlType[0] = 0; 973 header.fragmentationPlType[0] = 0;
966 header.fragmentationTimeDiff[0] = 0; 974 header.fragmentationTimeDiff[0] = 0;
967 if (codecType_ == kVideoCodecVP8 && scale_) { 975 if (codecType_ == kVideoCodecVP8 && scale_) {
968 int qp; 976 int qp;
969 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) 977 if (webrtc::vp8::GetQp(payload, payload_size, &qp)) {
978 current_acc_qp_ += qp;
970 quality_scaler_.ReportQP(qp); 979 quality_scaler_.ReportQP(qp);
980 }
971 } 981 }
972 } else if (codecType_ == kVideoCodecH264) { 982 } else if (codecType_ == kVideoCodecH264) {
973 if (scale_) { 983 if (scale_) {
974 h264_bitstream_parser_.ParseBitstream(payload, payload_size); 984 h264_bitstream_parser_.ParseBitstream(payload, payload_size);
975 int qp; 985 int qp;
976 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) 986 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) {
987 current_acc_qp_ += qp;
977 quality_scaler_.ReportQP(qp); 988 quality_scaler_.ReportQP(qp);
989 }
978 } 990 }
979 // For H.264 search for start codes. 991 // For H.264 search for start codes.
980 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {}; 992 int32_t scPositions[MAX_NALUS_PERFRAME + 1] = {};
981 int32_t scPositionsLength = 0; 993 int32_t scPositionsLength = 0;
982 int32_t scPosition = 0; 994 int32_t scPosition = 0;
983 while (scPositionsLength < MAX_NALUS_PERFRAME) { 995 while (scPositionsLength < MAX_NALUS_PERFRAME) {
984 int32_t naluPosition = NextNaluPosition( 996 int32_t naluPosition = NextNaluPosition(
985 payload + scPosition, payload_size - scPosition); 997 payload + scPosition, payload_size - scPosition);
986 if (naluPosition < 0) { 998 if (naluPosition < 0) {
987 break; 999 break;
(...skipping 27 matching lines...) Expand all
1015 // Return output buffer back to the encoder. 1027 // Return output buffer back to the encoder.
1016 bool success = jni->CallBooleanMethod(*j_media_codec_video_encoder_, 1028 bool success = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
1017 j_release_output_buffer_method_, 1029 j_release_output_buffer_method_,
1018 output_buffer_index); 1030 output_buffer_index);
1019 CHECK_EXCEPTION(jni); 1031 CHECK_EXCEPTION(jni);
1020 if (!success) { 1032 if (!success) {
1021 ResetCodecOnCodecThread(); 1033 ResetCodecOnCodecThread();
1022 return false; 1034 return false;
1023 } 1035 }
1024 1036
1037 // Calculate and print encoding statistics - every 3 seconds.
1038 frames_encoded_++;
1039 current_frames_++;
1040 current_bytes_ += payload_size;
1041 current_encoding_time_ms_ += frame_encoding_time_ms;
1042 int statistic_time_ms = GetCurrentTimeMs() - start_time_ms_;
1043 if (statistic_time_ms >= kMediaCodecStatisticsIntervalMs &&
1044 current_frames_ > 0) {
1045 ALOGD << "Encoded frames: " << frames_encoded_ << ". Bitrate: " <<
1046 (current_bytes_ * 8 / statistic_time_ms) <<
1047 ", target: " << last_set_bitrate_kbps_ << " kbps, fps: " <<
1048 ((current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms)
1049 << ", encTime: " <<
1050 (current_encoding_time_ms_ / current_frames_) << ". QP: " <<
1051 (current_acc_qp_ / current_frames_) << " for last " <<
1052 statistic_time_ms << " ms.";
1053 start_time_ms_ = GetCurrentTimeMs();
1054 current_frames_ = 0;
1055 current_bytes_ = 0;
1056 current_acc_qp_ = 0;
1057 current_encoding_time_ms_ = 0;
1058 }
1059
1025 if (callback_status > 0) { 1060 if (callback_status > 0) {
1026 drop_next_input_frame_ = true; 1061 drop_next_input_frame_ = true;
1027 // Theoretically could handle callback_status<0 here, but unclear what 1062 // Theoretically could handle callback_status<0 here, but unclear what
1028 // that would mean for us. 1063 // that would mean for us.
1029 } 1064 }
1030 } 1065 }
1031 1066
1032 return true; 1067 return true;
1033 } 1068 }
1034 1069
(...skipping 23 matching lines...) Expand all
1058 if (head[3] != 0x01) { // got 000000xx 1093 if (head[3] != 0x01) { // got 000000xx
1059 head++; // xx != 1, continue searching. 1094 head++; // xx != 1, continue searching.
1060 continue; 1095 continue;
1061 } 1096 }
1062 return (int32_t)(head - buffer); 1097 return (int32_t)(head - buffer);
1063 } 1098 }
1064 return -1; 1099 return -1;
1065 } 1100 }
1066 1101
1067 void MediaCodecVideoEncoder::OnDroppedFrame() { 1102 void MediaCodecVideoEncoder::OnDroppedFrame() {
1103 frames_dropped_++;
1104 // Report dropped frame to quality_scaler_.
1068 if (scale_) 1105 if (scale_)
1069 quality_scaler_.ReportDroppedFrame(); 1106 quality_scaler_.ReportDroppedFrame();
1070 } 1107 }
1071 1108
1072 int MediaCodecVideoEncoder::GetTargetFramerate() { 1109 int MediaCodecVideoEncoder::GetTargetFramerate() {
1073 return scale_ ? quality_scaler_.GetTargetFramerate() : -1; 1110 return scale_ ? quality_scaler_.GetTargetFramerate() : -1;
1074 } 1111 }
1075 1112
1076 const char* MediaCodecVideoEncoder::ImplementationName() const { 1113 const char* MediaCodecVideoEncoder::ImplementationName() const {
1077 return "MediaCodec"; 1114 return "MediaCodec";
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 } 1206 }
1170 1207
1171 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder( 1208 void MediaCodecVideoEncoderFactory::DestroyVideoEncoder(
1172 webrtc::VideoEncoder* encoder) { 1209 webrtc::VideoEncoder* encoder) {
1173 ALOGD << "Destroy video encoder."; 1210 ALOGD << "Destroy video encoder.";
1174 delete encoder; 1211 delete encoder;
1175 } 1212 }
1176 1213
1177 } // namespace webrtc_jni 1214 } // namespace webrtc_jni
1178 1215
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/jni/androidmediadecoder_jni.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698