Always on statistics for AndroidMediaEncoder.

Earlier, no statistics were reported if no frames were being delivered
for encoding. This makes statics always be reported regardless of if
there are frames being delivered to the encoder.

Review-Url: https://codereview.webrtc.org/2051403002
Cr-Commit-Position: refs/heads/master@{#13122}
This commit is contained in:
sakal
2016-06-14 01:53:39 -07:00
committed by Commit bot
parent 81d99b3049
commit 1fc4810006
2 changed files with 20 additions and 15 deletions

View File

@ -43,6 +43,8 @@ enum COLOR_FORMATTYPE {
// Arbitrary interval to poll the codec for new outputs. // Arbitrary interval to poll the codec for new outputs.
enum { kMediaCodecPollMs = 10 }; enum { kMediaCodecPollMs = 10 };
// Arbitrary interval to poll at when there should be no more frames.
enum { kMediaCodecPollNoFramesMs = 100 };
// Media codec maximum output buffer ready timeout. // Media codec maximum output buffer ready timeout.
enum { kMediaCodecTimeoutMs = 1000 }; enum { kMediaCodecTimeoutMs = 1000 };
// Interval to print codec statistics (bitrate, fps, encoding/decoding time). // Interval to print codec statistics (bitrate, fps, encoding/decoding time).

View File

@ -226,7 +226,6 @@ class MediaCodecVideoEncoder : public webrtc::VideoEncoder,
int current_encoding_time_ms_; // Overall encoding time in the current second int current_encoding_time_ms_; // Overall encoding time in the current second
int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame. int64_t last_input_timestamp_ms_; // Timestamp of last received yuv frame.
int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame. int64_t last_output_timestamp_ms_; // Timestamp of last encoded frame.
bool output_delivery_loop_running_; // Is the onMessage loop running
struct InputFrameInfo { struct InputFrameInfo {
InputFrameInfo(int64_t encode_start_time, InputFrameInfo(int64_t encode_start_time,
@ -307,7 +306,6 @@ MediaCodecVideoEncoder::MediaCodecVideoEncoder(
inited_(false), inited_(false),
use_surface_(false), use_surface_(false),
picture_id_(0), picture_id_(0),
output_delivery_loop_running_(false),
egl_context_(egl_context) { egl_context_(egl_context) {
ScopedLocalRefFrame local_ref_frame(jni); ScopedLocalRefFrame local_ref_frame(jni);
// It would be nice to avoid spinning up a new thread per MediaCodec, and // It would be nice to avoid spinning up a new thread per MediaCodec, and
@ -472,12 +470,16 @@ void MediaCodecVideoEncoder::OnMessage(rtc::Message* msg) {
// about it and let the next app-called API method reveal the borkedness. // about it and let the next app-called API method reveal the borkedness.
DeliverPendingOutputs(jni); DeliverPendingOutputs(jni);
// If there aren't more frames to deliver, we can stop the loop // If there aren't more frames to deliver, we can start polling at lower rate.
if (!input_frame_infos_.empty()) { if (input_frame_infos_.empty()) {
codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this); codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollNoFramesMs, this);
} else { } else {
output_delivery_loop_running_ = false; codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
} }
// Call log statistics here so it's called even if no frames are being
// delivered.
LogStatistics(false);
} }
bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() { bool MediaCodecVideoEncoder::ResetCodecOnCodecThread() {
@ -737,10 +739,8 @@ int32_t MediaCodecVideoEncoder::EncodeOnCodecThread(
current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_; current_timestamp_us_ += rtc::kNumMicrosecsPerSec / last_set_fps_;
if (!output_delivery_loop_running_) { codec_thread_->Clear(this);
output_delivery_loop_running_ = true; codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
codec_thread_->PostDelayed(RTC_FROM_HERE, kMediaCodecPollMs, this);
}
if (!DeliverPendingOutputs(jni)) { if (!DeliverPendingOutputs(jni)) {
ALOGE << "Failed deliver pending outputs."; ALOGE << "Failed deliver pending outputs.";
@ -859,7 +859,6 @@ int32_t MediaCodecVideoEncoder::ReleaseOnCodecThread() {
rtc::MessageQueueManager::Clear(this); rtc::MessageQueueManager::Clear(this);
inited_ = false; inited_ = false;
use_surface_ = false; use_surface_ = false;
output_delivery_loop_running_ = false;
ALOGD << "EncoderReleaseOnCodecThread done."; ALOGD << "EncoderReleaseOnCodecThread done.";
return WEBRTC_VIDEO_CODEC_OK; return WEBRTC_VIDEO_CODEC_OK;
} }
@ -923,6 +922,7 @@ jlong MediaCodecVideoEncoder::GetOutputBufferInfoPresentationTimestampUs(
bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
RTC_DCHECK(codec_thread_checker_.CalledOnValidThread()); RTC_DCHECK(codec_thread_checker_.CalledOnValidThread());
while (true) { while (true) {
jobject j_output_buffer_info = jni->CallObjectMethod( jobject j_output_buffer_info = jni->CallObjectMethod(
*j_media_codec_video_encoder_, j_dequeue_output_buffer_method_); *j_media_codec_video_encoder_, j_dequeue_output_buffer_method_);
@ -1118,8 +1118,11 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) {
void MediaCodecVideoEncoder::LogStatistics(bool force_log) { void MediaCodecVideoEncoder::LogStatistics(bool force_log) {
int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_; int statistic_time_ms = rtc::TimeMillis() - stat_start_time_ms_;
if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log) && if ((statistic_time_ms >= kMediaCodecStatisticsIntervalMs || force_log)
current_frames_ > 0 && statistic_time_ms > 0) { && statistic_time_ms > 0) {
// Prevent division by zero.
int current_frames_divider = current_frames_ != 0 ? current_frames_ : 1;
int current_bitrate = current_bytes_ * 8 / statistic_time_ms; int current_bitrate = current_bytes_ * 8 / statistic_time_ms;
int current_fps = int current_fps =
(current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms; (current_frames_ * 1000 + statistic_time_ms / 2) / statistic_time_ms;
@ -1127,8 +1130,8 @@ void MediaCodecVideoEncoder::LogStatistics(bool force_log) {
". Bitrate: " << current_bitrate << ". Bitrate: " << current_bitrate <<
", target: " << last_set_bitrate_kbps_ << " kbps" << ", target: " << last_set_bitrate_kbps_ << " kbps" <<
", fps: " << current_fps << ", fps: " << current_fps <<
", encTime: " << (current_encoding_time_ms_ / current_frames_) << ", encTime: " << (current_encoding_time_ms_ / current_frames_divider) <<
". QP: " << (current_acc_qp_ / current_frames_) << ". QP: " << (current_acc_qp_ / current_frames_divider) <<
" for last " << statistic_time_ms << " ms."; " for last " << statistic_time_ms << " ms.";
stat_start_time_ms_ = rtc::TimeMillis(); stat_start_time_ms_ = rtc::TimeMillis();
current_frames_ = 0; current_frames_ = 0;