Histograms for H264EncoderImpl/H264DecoderImpl
initialization and errors.
The stats are counts using enumeration, an instance of
H264EncoderImpl/H264DecoderImpl will report at most 1 Init
and 1 Error for its entire lifetime. This is to avoid
spamming reports if initialization or coding fails and it
retries in a loop. The Init stats will give us an idea of
usage counts for the encoder/decoder. The Error stats will
give us an idea of how many of these usages encounters some
type of problem, such as encode or decode errors.
- WebRTC.Video.H264EncoderImpl.Event:
* kH264EncoderEventInit: Occurs at InitEncode.
* kH264EncoderEventError: Occurs if any type of error
occurs during initialization or encoding.
- WebRTC.Video.H264DecoderImpl.Event:
* kH264DecoderEventInit: Occurs at InitDecode.
* kH264DecoderEventError: Occurs if any type of error
occurs during initialization, AVGetBuffer2 or decoding.
Chromium sibling CL:
https://codereview.chromium.org/1719273002/
BUG=chromium:500605, chromium:468365
Review URL: https://codereview.webrtc.org/1716173002
Cr-Commit-Position: refs/heads/master@{#11736}
This commit is contained in:
@ -24,6 +24,7 @@ extern "C" {
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/keep_ref_until_done.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -34,6 +35,13 @@ const size_t kYPlaneIndex = 0;
|
||||
const size_t kUPlaneIndex = 1;
|
||||
const size_t kVPlaneIndex = 2;
|
||||
|
||||
// Used by histograms. Values of entries should not be changed.
|
||||
enum H264DecoderImplEvent {
|
||||
kH264DecoderEventInit = 0,
|
||||
kH264DecoderEventError = 1,
|
||||
kH264DecoderEventMax = 16,
|
||||
};
|
||||
|
||||
#if defined(WEBRTC_INITIALIZE_FFMPEG)
|
||||
|
||||
rtc::CriticalSection ffmpeg_init_lock;
|
||||
@ -109,6 +117,7 @@ int H264DecoderImpl::AVGetBuffer2(
|
||||
static_cast<unsigned int>(height), 0, nullptr);
|
||||
if (ret < 0) {
|
||||
LOG(LS_ERROR) << "Invalid picture size " << width << "x" << height;
|
||||
decoder->ReportError();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -158,7 +167,9 @@ void H264DecoderImpl::AVFreeBuffer2(void* opaque, uint8_t* data) {
|
||||
}
|
||||
|
||||
H264DecoderImpl::H264DecoderImpl() : pool_(true),
|
||||
decoded_image_callback_(nullptr) {
|
||||
decoded_image_callback_(nullptr),
|
||||
has_reported_init_(false),
|
||||
has_reported_error_(false) {
|
||||
}
|
||||
|
||||
H264DecoderImpl::~H264DecoderImpl() {
|
||||
@ -167,8 +178,10 @@ H264DecoderImpl::~H264DecoderImpl() {
|
||||
|
||||
int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores) {
|
||||
ReportInit();
|
||||
if (codec_settings &&
|
||||
codec_settings->codecType != kVideoCodecH264) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
|
||||
@ -186,8 +199,10 @@ int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
||||
|
||||
// Release necessary in case of re-initializing.
|
||||
int32_t ret = Release();
|
||||
if (ret != WEBRTC_VIDEO_CODEC_OK)
|
||||
if (ret != WEBRTC_VIDEO_CODEC_OK) {
|
||||
ReportError();
|
||||
return ret;
|
||||
}
|
||||
RTC_DCHECK(!av_context_);
|
||||
|
||||
// Initialize AVCodecContext.
|
||||
@ -222,12 +237,14 @@ int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
||||
// been compiled/initialized with the correct set of codecs.
|
||||
LOG(LS_ERROR) << "FFmpeg H.264 decoder not found.";
|
||||
Release();
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
int res = avcodec_open2(av_context_.get(), codec, nullptr);
|
||||
if (res < 0) {
|
||||
LOG(LS_ERROR) << "avcodec_open2 error: " << res;
|
||||
Release();
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
|
||||
@ -252,17 +269,23 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
|
||||
const RTPFragmentationHeader* /*fragmentation*/,
|
||||
const CodecSpecificInfo* codec_specific_info,
|
||||
int64_t /*render_time_ms*/) {
|
||||
if (!IsInitialized())
|
||||
if (!IsInitialized()) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||
}
|
||||
if (!decoded_image_callback_) {
|
||||
LOG(LS_WARNING) << "InitDecode() has been called, but a callback function "
|
||||
"has not been set with RegisterDecodeCompleteCallback()";
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||
}
|
||||
if (!input_image._buffer || !input_image._length)
|
||||
if (!input_image._buffer || !input_image._length) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
if (codec_specific_info &&
|
||||
codec_specific_info->codecType != kVideoCodecH264) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
|
||||
@ -282,6 +305,7 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
|
||||
packet.data = input_image._buffer;
|
||||
if (input_image._length >
|
||||
static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
packet.size = static_cast<int>(input_image._length);
|
||||
@ -294,12 +318,14 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
|
||||
&packet);
|
||||
if (result < 0) {
|
||||
LOG(LS_ERROR) << "avcodec_decode_video2 error: " << result;
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
// |result| is number of bytes used, which should be all of them.
|
||||
if (result != packet.size) {
|
||||
LOG(LS_ERROR) << "avcodec_decode_video2 consumed " << result << " bytes "
|
||||
"when " << packet.size << " bytes were expected.";
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
|
||||
@ -349,4 +375,22 @@ bool H264DecoderImpl::IsInitialized() const {
|
||||
return av_context_ != nullptr;
|
||||
}
|
||||
|
||||
void H264DecoderImpl::ReportInit() {
|
||||
if (has_reported_init_)
|
||||
return;
|
||||
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264DecoderImpl.Event",
|
||||
kH264DecoderEventInit,
|
||||
kH264DecoderEventMax);
|
||||
has_reported_init_ = true;
|
||||
}
|
||||
|
||||
void H264DecoderImpl::ReportError() {
|
||||
if (has_reported_error_)
|
||||
return;
|
||||
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264DecoderImpl.Event",
|
||||
kH264DecoderEventError,
|
||||
kH264DecoderEventMax);
|
||||
has_reported_error_ = true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -62,11 +62,18 @@ class H264DecoderImpl : public H264Decoder {
|
||||
|
||||
bool IsInitialized() const;
|
||||
|
||||
// Reports statistics with histograms.
|
||||
void ReportInit();
|
||||
void ReportError();
|
||||
|
||||
I420BufferPool pool_;
|
||||
rtc::scoped_ptr<AVCodecContext, AVCodecContextDeleter> av_context_;
|
||||
rtc::scoped_ptr<AVFrame, AVFrameDeleter> av_frame_;
|
||||
|
||||
DecodedImageCallback* decoded_image_callback_;
|
||||
|
||||
bool has_reported_init_;
|
||||
bool has_reported_error_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -27,6 +28,13 @@ namespace {
|
||||
|
||||
const bool kOpenH264EncoderDetailedLogging = false;
|
||||
|
||||
// Used by histograms. Values of entries should not be changed.
|
||||
enum H264EncoderImplEvent {
|
||||
kH264EncoderEventInit = 0,
|
||||
kH264EncoderEventError = 1,
|
||||
kH264EncoderEventMax = 16,
|
||||
};
|
||||
|
||||
int NumberOfThreads(int width, int height, int number_of_cores) {
|
||||
// TODO(hbos): In Chromium, multiple threads do not work with sandbox on Mac,
|
||||
// see crbug.com/583348. Until further investigated, only use one thread.
|
||||
@ -141,7 +149,9 @@ static void RtpFragmentize(EncodedImage* encoded_image,
|
||||
|
||||
H264EncoderImpl::H264EncoderImpl()
|
||||
: openh264_encoder_(nullptr),
|
||||
encoded_image_callback_(nullptr) {
|
||||
encoded_image_callback_(nullptr),
|
||||
has_reported_init_(false),
|
||||
has_reported_error_(false) {
|
||||
}
|
||||
|
||||
H264EncoderImpl::~H264EncoderImpl() {
|
||||
@ -151,18 +161,26 @@ H264EncoderImpl::~H264EncoderImpl() {
|
||||
int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
||||
int32_t number_of_cores,
|
||||
size_t /*max_payload_size*/) {
|
||||
ReportInit();
|
||||
if (!codec_settings ||
|
||||
codec_settings->codecType != kVideoCodecH264) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
if (codec_settings->maxFramerate == 0)
|
||||
if (codec_settings->maxFramerate == 0) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
if (codec_settings->width < 1 || codec_settings->height < 1)
|
||||
}
|
||||
if (codec_settings->width < 1 || codec_settings->height < 1) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
|
||||
int32_t release_ret = Release();
|
||||
if (release_ret != WEBRTC_VIDEO_CODEC_OK)
|
||||
if (release_ret != WEBRTC_VIDEO_CODEC_OK) {
|
||||
ReportError();
|
||||
return release_ret;
|
||||
}
|
||||
RTC_DCHECK(!openh264_encoder_);
|
||||
|
||||
// Create encoder.
|
||||
@ -170,6 +188,7 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
||||
// Failed to create encoder.
|
||||
LOG(LS_ERROR) << "Failed to create OpenH264 encoder";
|
||||
RTC_DCHECK(!openh264_encoder_);
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
RTC_DCHECK(openh264_encoder_);
|
||||
@ -196,6 +215,7 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
||||
} else if (codec_settings_.mode == kScreensharing) {
|
||||
init_params.iUsageType = SCREEN_CONTENT_REAL_TIME;
|
||||
} else {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
init_params.iPicWidth = codec_settings_.width;
|
||||
@ -236,6 +256,7 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
||||
if (openh264_encoder_->InitializeExt(&init_params) != 0) {
|
||||
LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder";
|
||||
Release();
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
int video_format = EVideoFormatType::videoFormatI420;
|
||||
@ -299,13 +320,18 @@ int32_t H264EncoderImpl::SetRates(uint32_t bitrate, uint32_t framerate) {
|
||||
int32_t H264EncoderImpl::Encode(
|
||||
const VideoFrame& frame, const CodecSpecificInfo* codec_specific_info,
|
||||
const std::vector<FrameType>* frame_types) {
|
||||
if (!IsInitialized())
|
||||
if (!IsInitialized()) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||
if (frame.IsZeroSize())
|
||||
}
|
||||
if (frame.IsZeroSize()) {
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
||||
}
|
||||
if (!encoded_image_callback_) {
|
||||
LOG(LS_WARNING) << "InitEncode() has been called, but a callback function "
|
||||
<< "has not been set with RegisterEncodeCompleteCallback()";
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||
}
|
||||
if (frame.width() != codec_settings_.width ||
|
||||
@ -313,6 +339,7 @@ int32_t H264EncoderImpl::Encode(
|
||||
LOG(LS_WARNING) << "Encoder initialized for " << codec_settings_.width
|
||||
<< "x" << codec_settings_.height << " but trying to encode "
|
||||
<< frame.width() << "x" << frame.height() << " frame.";
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERR_SIZE;
|
||||
}
|
||||
|
||||
@ -357,6 +384,7 @@ int32_t H264EncoderImpl::Encode(
|
||||
if (enc_ret != 0) {
|
||||
LOG(LS_ERROR) << "OpenH264 frame encoding failed, EncodeFrame returned "
|
||||
<< enc_ret << ".";
|
||||
ReportError();
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
|
||||
@ -389,6 +417,24 @@ bool H264EncoderImpl::IsInitialized() const {
|
||||
return openh264_encoder_ != nullptr;
|
||||
}
|
||||
|
||||
void H264EncoderImpl::ReportInit() {
|
||||
if (has_reported_init_)
|
||||
return;
|
||||
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
|
||||
kH264EncoderEventInit,
|
||||
kH264EncoderEventMax);
|
||||
has_reported_init_ = true;
|
||||
}
|
||||
|
||||
void H264EncoderImpl::ReportError() {
|
||||
if (has_reported_error_)
|
||||
return;
|
||||
RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
|
||||
kH264EncoderEventError,
|
||||
kH264EncoderEventMax);
|
||||
has_reported_error_ = true;
|
||||
}
|
||||
|
||||
int32_t H264EncoderImpl::SetChannelParameters(
|
||||
uint32_t packet_loss, int64_t rtt) {
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
|
||||
@ -57,12 +57,19 @@ class H264EncoderImpl : public H264Encoder {
|
||||
private:
|
||||
bool IsInitialized() const;
|
||||
|
||||
// Reports statistics with histograms.
|
||||
void ReportInit();
|
||||
void ReportError();
|
||||
|
||||
ISVCEncoder* openh264_encoder_;
|
||||
VideoCodec codec_settings_;
|
||||
|
||||
EncodedImage encoded_image_;
|
||||
rtc::scoped_ptr<uint8_t[]> encoded_image_buffer_;
|
||||
EncodedImageCallback* encoded_image_callback_;
|
||||
|
||||
bool has_reported_init_;
|
||||
bool has_reported_error_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user