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:
@ -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).
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user