Expose codec implementation names in stats.
Used to distinguish between software/hardware encoders/decoders and
other implementation differences. Useful for tracking quality
regressions related to specific implementations.
BUG=webrtc:4897
R=hta@webrtc.org, mflodman@webrtc.org, stefan@webrtc.org
Review URL: https://codereview.webrtc.org/1406903002 .
Cr-Commit-Position: refs/heads/master@{#11084}
diff --git a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
index 49b84aa..7ebcd20 100644
--- a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
@@ -95,6 +95,8 @@
// rtc::MessageHandler implementation.
void OnMessage(rtc::Message* msg) override;
+ const char* ImplementationName() const override;
+
private:
// CHECK-fail if not running on |codec_thread_|.
void CheckOnCodecThread();
@@ -906,5 +908,9 @@
delete decoder;
}
+const char* MediaCodecVideoDecoder::ImplementationName() const {
+ return "MediaCodec";
+}
+
} // namespace webrtc_jni
diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
index c6c7594..b36dc0b 100644
--- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
@@ -109,6 +109,11 @@
int GetTargetFramerate() override;
bool SupportsNativeHandle() const override { return true; }
+ const char* ImplementationName() const override;
+
+ private:
+ // CHECK-fail if not running on |codec_thread_|.
+ void CheckOnCodecThread();
private:
// ResetCodecOnCodecThread() calls ReleaseOnCodecThread() and
@@ -1068,8 +1073,12 @@
return scale_ ? quality_scaler_.GetTargetFramerate() : -1;
}
+const char* MediaCodecVideoEncoder::ImplementationName() const {
+ return "MediaCodec";
+}
+
MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory()
- : egl_context_ (nullptr) {
+ : egl_context_(nullptr) {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder");
diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc
index 893e586..b514b42 100644
--- a/talk/app/webrtc/statscollector.cc
+++ b/talk/app/webrtc/statscollector.cc
@@ -201,6 +201,8 @@
void ExtractStats(const cricket::VideoReceiverInfo& info, StatsReport* report) {
ExtractCommonReceiveProperties(info, report);
+ report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
+ info.decoder_implementation_name);
report->AddInt64(StatsReport::kStatsValueNameBytesReceived,
info.bytes_rcvd);
report->AddInt64(StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
@@ -233,6 +235,8 @@
void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
ExtractCommonSendProperties(info, report);
+ report->AddString(StatsReport::kStatsValueNameCodecImplementationName,
+ info.encoder_implementation_name);
report->AddBoolean(StatsReport::kStatsValueNameBandwidthLimitedResolution,
(info.adapt_reason & 0x2) > 0);
report->AddBoolean(StatsReport::kStatsValueNameCpuLimitedResolution,
diff --git a/talk/app/webrtc/statstypes.cc b/talk/app/webrtc/statstypes.cc
index e45833c..19cb1f5 100644
--- a/talk/app/webrtc/statstypes.cc
+++ b/talk/app/webrtc/statstypes.cc
@@ -408,6 +408,8 @@
return "state";
case kStatsValueNameDataChannelId:
return "datachannelid";
+ case kStatsValueNameCodecImplementationName:
+ return "codecImplementationName";
// 'goog' prefixed constants.
case kStatsValueNameAccelerateRate:
@@ -592,9 +594,6 @@
return "googViewLimitedResolution";
case kStatsValueNameWritable:
return "googWritable";
- default:
- RTC_DCHECK(false);
- break;
}
return nullptr;
diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h
index 7fa9f32..60439b9 100644
--- a/talk/app/webrtc/statstypes.h
+++ b/talk/app/webrtc/statstypes.h
@@ -120,6 +120,7 @@
kStatsValueNameAudioOutputLevel,
kStatsValueNameBytesReceived,
kStatsValueNameBytesSent,
+ kStatsValueNameCodecImplementationName,
kStatsValueNameDataChannelId,
kStatsValueNamePacketsLost,
kStatsValueNamePacketsReceived,
diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h
index 0a59019..f6fb77d 100644
--- a/talk/media/base/mediachannel.h
+++ b/talk/media/base/mediachannel.h
@@ -783,6 +783,7 @@
}
std::vector<SsrcGroup> ssrc_groups;
+ std::string encoder_implementation_name;
int packets_cached;
int firs_rcvd;
int plis_rcvd;
@@ -828,6 +829,7 @@
}
std::vector<SsrcGroup> ssrc_groups;
+ std::string decoder_implementation_name;
int packets_concealed;
int firs_sent;
int plis_sent;
diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc
index 5deee96..55c0742 100644
--- a/talk/media/webrtc/webrtcvideoengine2.cc
+++ b/talk/media/webrtc/webrtcvideoengine2.cc
@@ -2125,6 +2125,7 @@
if (stats.bw_limited_resolution)
info.adapt_reason |= CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH;
+ info.encoder_implementation_name = stats.encoder_implementation_name;
info.ssrc_groups = ssrc_groups_;
info.framerate_input = stats.input_frame_rate;
info.framerate_sent = stats.encode_frame_rate;
@@ -2517,6 +2518,7 @@
info.ssrc_groups = ssrc_groups_;
info.add_ssrc(config_.rtp.remote_ssrc);
webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
+ info.decoder_implementation_name = stats.decoder_implementation_name;
info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
stats.rtp_stats.transmitted.header_bytes +
stats.rtp_stats.transmitted.padding_bytes;
diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
index bd88b9c..6aca234 100644
--- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -2445,6 +2445,18 @@
EXPECT_EQ(kVp8Codec.name, info.senders[0].codec_name);
}
+TEST_F(WebRtcVideoChannel2Test, GetStatsReportsEncoderImplementationName) {
+ FakeVideoSendStream* stream = AddSendStream();
+ webrtc::VideoSendStream::Stats stats;
+ stats.encoder_implementation_name = "encoder_implementation_name";
+ stream->SetStats(stats);
+
+ cricket::VideoMediaInfo info;
+ ASSERT_TRUE(channel_->GetStats(&info));
+ EXPECT_EQ(stats.encoder_implementation_name,
+ info.senders[0].encoder_implementation_name);
+}
+
TEST_F(WebRtcVideoChannel2Test, GetStatsReportsCpuOveruseMetrics) {
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoSendStream::Stats stats;
@@ -2677,6 +2689,7 @@
TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesDecodeStatsCorrectly) {
FakeVideoReceiveStream* stream = AddRecvStream();
webrtc::VideoReceiveStream::Stats stats;
+ stats.decoder_implementation_name = "decoder_implementation_name";
stats.decode_ms = 2;
stats.max_decode_ms = 3;
stats.current_delay_ms = 4;
@@ -2688,6 +2701,8 @@
cricket::VideoMediaInfo info;
ASSERT_TRUE(channel_->GetStats(&info));
+ EXPECT_EQ(stats.decoder_implementation_name,
+ info.receivers[0].decoder_implementation_name);
EXPECT_EQ(stats.decode_ms, info.receivers[0].decode_ms);
EXPECT_EQ(stats.max_decode_ms, info.receivers[0].max_decode_ms);
EXPECT_EQ(stats.current_delay_ms, info.receivers[0].current_delay_ms);
diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.cc b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.cc
index 6d9a4c1..a0bbb9e 100644
--- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.cc
+++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.cc
@@ -266,6 +266,10 @@
}
}
+const char* H264VideoToolboxDecoder::ImplementationName() const {
+ return "VideoToolbox";
+}
+
} // namespace webrtc
#endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h
index f54ddb9..6d64307 100644
--- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h
+++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h
@@ -45,6 +45,8 @@
int Reset() override;
+ const char* ImplementationName() const override;
+
private:
int ResetDecompressionSession();
void ConfigureDecompressionSession();
diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
index d677f8b..f47f39c 100644
--- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
+++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc
@@ -434,6 +434,10 @@
}
}
+const char* H264VideoToolboxEncoder::ImplementationName() const {
+ return "VideoToolbox";
+}
+
} // namespace webrtc
#endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED)
diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h
index f4fb86f..269e041 100644
--- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h
+++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h
@@ -48,6 +48,8 @@
int Release() override;
+ const char* ImplementationName() const override;
+
private:
int ResetCompressionSession();
void ConfigureCompressionSession();
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
index 605b4d1..a608c10 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
@@ -301,6 +301,10 @@
return WEBRTC_VIDEO_CODEC_OK;
}
+const char* VP8EncoderImpl::ImplementationName() const {
+ return "libvpx";
+}
+
void VP8EncoderImpl::SetStreamState(bool send_stream,
int stream_idx) {
if (send_stream && !send_stream_[stream_idx]) {
@@ -1398,6 +1402,10 @@
return WEBRTC_VIDEO_CODEC_OK;
}
+const char* VP8DecoderImpl::ImplementationName() const {
+ return "libvpx";
+}
+
int VP8DecoderImpl::CopyReference(VP8DecoderImpl* copy) {
// The type of frame to copy should be set in ref_frame_->frame_type
// before the call to this function.
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
index 597fb77..e673ad4 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
@@ -58,6 +58,8 @@
void OnDroppedFrame() override {}
+ const char* ImplementationName() const override;
+
private:
void SetupTemporalLayers(int num_streams, int num_temporal_layers,
const VideoCodec& codec);
@@ -135,6 +137,8 @@
int Release() override;
int Reset() override;
+ const char* ImplementationName() const override;
+
private:
// Copy reference image from this _decoder to the _decoder in copyTo. Set
// which frame type to copy in _refFrame->frame_type before the call to
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
index 21096bd..a00af64 100644
--- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -809,6 +809,10 @@
return WEBRTC_VIDEO_CODEC_OK;
}
+const char* VP9EncoderImpl::ImplementationName() const {
+ return "libvpx";
+}
+
VP9Decoder* VP9Decoder::Create() {
return new VP9DecoderImpl();
}
@@ -980,4 +984,9 @@
inited_ = false;
return WEBRTC_VIDEO_CODEC_OK;
}
+
+const char* VP9DecoderImpl::ImplementationName() const {
+ return "libvpx";
+}
+
} // namespace webrtc
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
index 9a48e74..91475c9 100644
--- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -47,6 +47,8 @@
void OnDroppedFrame() override {}
+ const char* ImplementationName() const override;
+
struct LayerFrameRefSettings {
int8_t upd_buf = -1; // -1 - no update, 0..7 - update buffer 0..7
int8_t ref_buf1 = -1; // -1 - no reference, 0..7 - reference buffer 0..7
@@ -148,6 +150,8 @@
int Reset() override;
+ const char* ImplementationName() const override;
+
private:
int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp);
diff --git a/webrtc/modules/video_coding/generic_decoder.cc b/webrtc/modules/video_coding/generic_decoder.cc
index dc78ec2..3c72509 100644
--- a/webrtc/modules/video_coding/generic_decoder.cc
+++ b/webrtc/modules/video_coding/generic_decoder.cc
@@ -19,15 +19,12 @@
VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing,
Clock* clock)
-:
-_critSect(CriticalSectionWrapper::CreateCriticalSection()),
-_clock(clock),
-_receiveCallback(NULL),
-_timing(timing),
-_timestampMap(kDecoderFrameMemoryLength),
-_lastReceivedPictureID(0)
-{
-}
+ : _critSect(CriticalSectionWrapper::CreateCriticalSection()),
+ _clock(clock),
+ _receiveCallback(NULL),
+ _timing(timing),
+ _timestampMap(kDecoderFrameMemoryLength),
+ _lastReceivedPictureID(0) {}
VCMDecodedFrameCallback::~VCMDecodedFrameCallback()
{
@@ -115,6 +112,13 @@
return _lastReceivedPictureID;
}
+void VCMDecodedFrameCallback::OnDecoderImplementationName(
+ const char* implementation_name) {
+ CriticalSectionScoped cs(_critSect);
+ if (_receiveCallback)
+ _receiveCallback->OnDecoderImplementationName(implementation_name);
+}
+
void VCMDecodedFrameCallback::Map(uint32_t timestamp,
VCMFrameInformation* frameInfo) {
CriticalSectionScoped cs(_critSect);
@@ -164,6 +168,7 @@
frame.FragmentationHeader(),
frame.CodecSpecific(), frame.RenderTimeMs());
+ _callback->OnDecoderImplementationName(_decoder->ImplementationName());
if (ret < WEBRTC_VIDEO_CODEC_OK)
{
LOG(LS_WARNING) << "Failed to decode frame with timestamp "
diff --git a/webrtc/modules/video_coding/generic_decoder.h b/webrtc/modules/video_coding/generic_decoder.h
index 40a9845..b23462f 100644
--- a/webrtc/modules/video_coding/generic_decoder.h
+++ b/webrtc/modules/video_coding/generic_decoder.h
@@ -46,6 +46,7 @@
virtual int32_t ReceivedDecodedFrame(const uint64_t pictureId);
uint64_t LastReceivedPictureID() const;
+ void OnDecoderImplementationName(const char* implementation_name);
void Map(uint32_t timestamp, VCMFrameInformation* frameInfo);
int32_t Pop(uint32_t timestamp);
@@ -54,9 +55,9 @@
// Protect |_receiveCallback| and |_timestampMap|.
CriticalSectionWrapper* _critSect;
Clock* _clock;
- VCMReceiveCallback* _receiveCallback; // Guarded by |_critSect|.
+ VCMReceiveCallback* _receiveCallback GUARDED_BY(_critSect);
VCMTiming& _timing;
- VCMTimestampMap _timestampMap; // Guarded by |_critSect|.
+ VCMTimestampMap _timestampMap GUARDED_BY(_critSect);
uint64_t _lastReceivedPictureID;
};
diff --git a/webrtc/modules/video_coding/generic_encoder.cc b/webrtc/modules/video_coding/generic_encoder.cc
index c8180f3..ae5284b 100644
--- a/webrtc/modules/video_coding/generic_encoder.cc
+++ b/webrtc/modules/video_coding/generic_encoder.cc
@@ -150,6 +150,12 @@
vcm_encoded_frame_callback_->SetRotation(rotation_);
int32_t result = encoder_->Encode(inputFrame, codecSpecificInfo, &frameTypes);
+
+ if (vcm_encoded_frame_callback_) {
+ vcm_encoded_frame_callback_->SignalLastEncoderImplementationUsed(
+ encoder_->ImplementationName());
+ }
+
if (is_screenshare_ &&
result == WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT) {
// Target bitrate exceeded, encoder state has been reset - try again.
@@ -224,7 +230,7 @@
***************************/
VCMEncodedFrameCallback::VCMEncodedFrameCallback(
EncodedImageCallback* post_encode_callback)
- : _sendCallback(),
+ : send_callback_(),
_mediaOpt(NULL),
_payloadType(0),
_internalSource(false),
@@ -250,27 +256,25 @@
int32_t
VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
{
- _sendCallback = transport;
+ send_callback_ = transport;
return VCM_OK;
}
int32_t VCMEncodedFrameCallback::Encoded(
- const EncodedImage& encodedImage,
+ const EncodedImage& encoded_image,
const CodecSpecificInfo* codecSpecificInfo,
const RTPFragmentationHeader* fragmentationHeader) {
TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded",
- "timestamp", encodedImage._timeStamp);
- RTC_DCHECK(encodedImage._frameType == kVideoFrameKey ||
- encodedImage._frameType == kVideoFrameDelta);
- post_encode_callback_->Encoded(encodedImage, NULL, NULL);
+ "timestamp", encoded_image._timeStamp);
+ post_encode_callback_->Encoded(encoded_image, NULL, NULL);
- if (_sendCallback == NULL) {
+ if (send_callback_ == NULL) {
return VCM_UNINITIALIZED;
}
#ifdef DEBUG_ENCODER_BIT_STREAM
if (_bitStreamAfterEncoder != NULL) {
- fwrite(encodedImage._buffer, 1, encodedImage._length,
+ fwrite(encoded_image._buffer, 1, encoded_image._length,
_bitStreamAfterEncoder);
}
#endif
@@ -283,25 +287,29 @@
}
rtpVideoHeader.rotation = _rotation;
- int32_t callbackReturn = _sendCallback->SendData(
- _payloadType, encodedImage, *fragmentationHeader, rtpVideoHeaderPtr);
+ int32_t callbackReturn = send_callback_->SendData(
+ _payloadType, encoded_image, *fragmentationHeader, rtpVideoHeaderPtr);
if (callbackReturn < 0) {
return callbackReturn;
}
if (_mediaOpt != NULL) {
- _mediaOpt->UpdateWithEncodedData(encodedImage);
+ _mediaOpt->UpdateWithEncodedData(encoded_image);
if (_internalSource)
return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame.
}
return VCM_OK;
}
-void
-VCMEncodedFrameCallback::SetMediaOpt(
- media_optimization::MediaOptimization *mediaOpt)
-{
- _mediaOpt = mediaOpt;
+void VCMEncodedFrameCallback::SetMediaOpt(
+ media_optimization::MediaOptimization* mediaOpt) {
+ _mediaOpt = mediaOpt;
+}
+
+void VCMEncodedFrameCallback::SignalLastEncoderImplementationUsed(
+ const char* implementation_name) {
+ if (send_callback_)
+ send_callback_->OnEncoderImplementationName(implementation_name);
}
} // namespace webrtc
diff --git a/webrtc/modules/video_coding/generic_encoder.h b/webrtc/modules/video_coding/generic_encoder.h
index 0d8ad50..5346b63 100644
--- a/webrtc/modules/video_coding/generic_encoder.h
+++ b/webrtc/modules/video_coding/generic_encoder.h
@@ -62,9 +62,11 @@
void SetInternalSource(bool internalSource) { _internalSource = internalSource; };
void SetRotation(VideoRotation rotation) { _rotation = rotation; }
+ void SignalLastEncoderImplementationUsed(
+ const char* encoder_implementation_name);
private:
- VCMPacketizationCallback* _sendCallback;
+ VCMPacketizationCallback* send_callback_;
media_optimization::MediaOptimization* _mediaOpt;
uint8_t _payloadType;
bool _internalSource;
diff --git a/webrtc/modules/video_coding/include/video_coding_defines.h b/webrtc/modules/video_coding/include/video_coding_defines.h
index 1b72144..d057b55 100644
--- a/webrtc/modules/video_coding/include/video_coding_defines.h
+++ b/webrtc/modules/video_coding/include/video_coding_defines.h
@@ -62,6 +62,8 @@
const RTPFragmentationHeader& fragmentationHeader,
const RTPVideoHeader* rtpVideoHdr) = 0;
+ virtual void OnEncoderImplementationName(const char* implementation_name) {}
+
protected:
virtual ~VCMPacketizationCallback() {
}
@@ -77,6 +79,7 @@
}
// Called when the current receive codec changes.
virtual void OnIncomingPayloadType(int payload_type) {}
+ virtual void OnDecoderImplementationName(const char* implementation_name) {}
protected:
virtual ~VCMReceiveCallback() {
diff --git a/webrtc/modules/video_coding/video_receiver.cc b/webrtc/modules/video_coding/video_receiver.cc
index f7ac4bc..f074832 100644
--- a/webrtc/modules/video_coding/video_receiver.cc
+++ b/webrtc/modules/video_coding/video_receiver.cc
@@ -287,43 +287,37 @@
VCMEncodedFrame* frame = _receiver.FrameForDecoding(
maxWaitTimeMs, nextRenderTimeMs, prefer_late_decoding);
- if (frame == NULL) {
+ if (!frame)
return VCM_FRAME_NOT_READY;
- } else {
- CriticalSectionScoped cs(_receiveCritSect);
- // If this frame was too late, we should adjust the delay accordingly
- _timing.UpdateCurrentDelay(frame->RenderTimeMs(),
- clock_->TimeInMilliseconds());
+ CriticalSectionScoped cs(_receiveCritSect);
- if (pre_decode_image_callback_) {
- EncodedImage encoded_image(frame->EncodedImage());
- int qp = -1;
- if (qp_parser_.GetQp(*frame, &qp)) {
- encoded_image.qp_ = qp;
- }
- pre_decode_image_callback_->Encoded(
- encoded_image, frame->CodecSpecific(), NULL);
+ // If this frame was too late, we should adjust the delay accordingly
+ _timing.UpdateCurrentDelay(frame->RenderTimeMs(),
+ clock_->TimeInMilliseconds());
+
+ if (pre_decode_image_callback_) {
+ EncodedImage encoded_image(frame->EncodedImage());
+ int qp = -1;
+ if (qp_parser_.GetQp(*frame, &qp)) {
+ encoded_image.qp_ = qp;
}
+ pre_decode_image_callback_->Encoded(encoded_image, frame->CodecSpecific(),
+ NULL);
+ }
#ifdef DEBUG_DECODER_BIT_STREAM
- if (_bitStreamBeforeDecoder != NULL) {
- // Write bit stream to file for debugging purposes
- if (fwrite(
- frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) !=
- frame->Length()) {
- return -1;
- }
- }
-#endif
- const int32_t ret = Decode(*frame);
- _receiver.ReleaseFrame(frame);
- frame = NULL;
- if (ret != VCM_OK) {
- return ret;
+ if (_bitStreamBeforeDecoder != NULL) {
+ // Write bit stream to file for debugging purposes
+ if (fwrite(frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) !=
+ frame->Length()) {
+ return -1;
}
}
- return VCM_OK;
+#endif
+ const int32_t ret = Decode(*frame);
+ _receiver.ReleaseFrame(frame);
+ return ret;
}
int32_t VideoReceiver::RequestSliceLossIndication(
diff --git a/webrtc/test/fake_decoder.cc b/webrtc/test/fake_decoder.cc
index 63316e0..dbdd580 100644
--- a/webrtc/test/fake_decoder.cc
+++ b/webrtc/test/fake_decoder.cc
@@ -53,10 +53,16 @@
int32_t FakeDecoder::Release() {
return WEBRTC_VIDEO_CODEC_OK;
}
+
int32_t FakeDecoder::Reset() {
return WEBRTC_VIDEO_CODEC_OK;
}
+const char* FakeDecoder::kImplementationName = "fake_decoder";
+const char* FakeDecoder::ImplementationName() const {
+ return kImplementationName;
+}
+
int32_t FakeH264Decoder::Decode(const EncodedImage& input,
bool missing_frames,
const RTPFragmentationHeader* fragmentation,
diff --git a/webrtc/test/fake_decoder.h b/webrtc/test/fake_decoder.h
index 20f6bbf..0da961d 100644
--- a/webrtc/test/fake_decoder.h
+++ b/webrtc/test/fake_decoder.h
@@ -39,6 +39,10 @@
int32_t Release() override;
int32_t Reset() override;
+ const char* ImplementationName() const override;
+
+ static const char* kImplementationName;
+
private:
VideoCodec config_;
VideoFrame frame_;
diff --git a/webrtc/test/fake_encoder.cc b/webrtc/test/fake_encoder.cc
index 165fd3e..72df40f 100644
--- a/webrtc/test/fake_encoder.cc
+++ b/webrtc/test/fake_encoder.cc
@@ -132,6 +132,11 @@
return 0;
}
+const char* FakeEncoder::kImplementationName = "fake_encoder";
+const char* FakeEncoder::ImplementationName() const {
+ return kImplementationName;
+}
+
FakeH264Encoder::FakeH264Encoder(Clock* clock)
: FakeEncoder(clock), callback_(NULL), idr_counter_(0) {
FakeEncoder::RegisterEncodeCompleteCallback(this);
diff --git a/webrtc/test/fake_encoder.h b/webrtc/test/fake_encoder.h
index 88ff9d4..6bff00e 100644
--- a/webrtc/test/fake_encoder.h
+++ b/webrtc/test/fake_encoder.h
@@ -39,6 +39,9 @@
int32_t Release() override;
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override;
+ const char* ImplementationName() const override;
+
+ static const char* kImplementationName;
protected:
Clock* const clock_;
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 46741b0..bd9c198 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -2383,6 +2383,9 @@
receive_stats_filled_["IncomingRate"] |=
stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
+ send_stats_filled_["DecoderImplementationName"] |=
+ stats.decoder_implementation_name ==
+ test::FakeDecoder::kImplementationName;
receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
stats.render_delay_ms >= kExpectedRenderDelayMs;
@@ -2438,6 +2441,10 @@
send_stats_filled_["CpuOveruseMetrics"] |=
stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
+ send_stats_filled_["EncoderImplementationName"] |=
+ stats.encoder_implementation_name ==
+ test::FakeEncoder::kImplementationName;
+
for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
stats.substreams.begin();
it != stats.substreams.end(); ++it) {
diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc
index 329905d..c13c807 100644
--- a/webrtc/video/receive_statistics_proxy.cc
+++ b/webrtc/video/receive_statistics_proxy.cc
@@ -80,6 +80,11 @@
stats_.current_payload_type = payload_type;
}
+void ReceiveStatisticsProxy::OnDecoderImplementationName(
+ const char* implementation_name) {
+ rtc::CritScope lock(&crit_);
+ stats_.decoder_implementation_name = implementation_name;
+}
void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
unsigned int bitrate_bps) {
rtc::CritScope lock(&crit_);
diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h
index 91f4105..87cb950 100644
--- a/webrtc/video/receive_statistics_proxy.h
+++ b/webrtc/video/receive_statistics_proxy.h
@@ -45,6 +45,7 @@
void OnDecodedFrame();
void OnRenderedFrame(int width, int height);
void OnIncomingPayloadType(int payload_type);
+ void OnDecoderImplementationName(const char* implementation_name);
void OnIncomingRate(unsigned int framerate, unsigned int bitrate_bps);
void OnDecoderTiming(int decode_ms,
int max_decode_ms,
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index f5e7e3d..c198ad2 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -161,6 +161,12 @@
}
}
+void SendStatisticsProxy::OnEncoderImplementationName(
+ const char* implementation_name) {
+ rtc::CritScope lock(&crit_);
+ stats_.encoder_implementation_name = implementation_name;
+}
+
void SendStatisticsProxy::OnOutgoingRate(uint32_t framerate, uint32_t bitrate) {
rtc::CritScope lock(&crit_);
stats_.encode_frame_rate = framerate;
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index e9e89f6..7f6df06 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -58,6 +58,7 @@
// From VideoEncoderRateObserver.
void OnSetRates(uint32_t bitrate_bps, int framerate) override;
+ void OnEncoderImplementationName(const char* implementation_name);
void OnOutgoingRate(uint32_t framerate, uint32_t bitrate);
void OnSuspendChange(bool is_suspended);
void OnInactiveSsrc(uint32_t ssrc);
diff --git a/webrtc/video/video_decoder.cc b/webrtc/video/video_decoder.cc
index 2a0151d..d699175 100644
--- a/webrtc/video/video_decoder.cc
+++ b/webrtc/video/video_decoder.cc
@@ -76,6 +76,9 @@
}
if (callback_ != nullptr)
fallback_decoder_->RegisterDecodeCompleteCallback(callback_);
+ fallback_implementation_name_ =
+ std::string(fallback_decoder_->ImplementationName()) +
+ " (fallback from: " + decoder_->ImplementationName() + ")";
return true;
}
@@ -137,4 +140,10 @@
return decoder_->PrefersLateDecoding();
}
+const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const {
+ if (fallback_decoder_)
+ return fallback_implementation_name_.c_str();
+ return decoder_->ImplementationName();
+}
+
} // namespace webrtc
diff --git a/webrtc/video/video_decoder_unittest.cc b/webrtc/video/video_decoder_unittest.cc
index 422aca0..4d54a3e 100644
--- a/webrtc/video/video_decoder_unittest.cc
+++ b/webrtc/video/video_decoder_unittest.cc
@@ -53,6 +53,11 @@
++reset_count_;
return WEBRTC_VIDEO_CODEC_OK;
}
+
+ const char* ImplementationName() const override {
+ return "fake-decoder";
+ }
+
int init_decode_count_ = 0;
int decode_count_ = 0;
int32_t decode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
@@ -144,7 +149,7 @@
}
// TODO(pbos): Fake a VP8 frame well enough to actually receive a callback from
-// the software encoder.
+// the software decoder.
TEST_F(VideoDecoderSoftwareFallbackWrapperTest,
ForwardsRegisterDecodeCompleteCallback) {
class FakeDecodedImageCallback : public DecodedImageCallback {
@@ -168,4 +173,19 @@
EXPECT_EQ(&callback2, fake_decoder_.decode_complete_callback_);
}
+TEST_F(VideoDecoderSoftwareFallbackWrapperTest,
+ ReportsFallbackImplementationName) {
+ VideoCodec codec = {};
+ fallback_wrapper_.InitDecode(&codec, 2);
+
+ fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ EncodedImage encoded_image;
+ fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
+ // Hard coded expected value since libvpx is the software implementation name
+ // for VP8. Change accordingly if the underlying implementation does.
+ EXPECT_STREQ("libvpx (fallback from: fake-decoder)",
+ fallback_wrapper_.ImplementationName());
+ fallback_wrapper_.Release();
+}
+
} // namespace webrtc
diff --git a/webrtc/video/video_encoder.cc b/webrtc/video/video_encoder.cc
index 6410e39..e85e3d97 100644
--- a/webrtc/video/video_encoder.cc
+++ b/webrtc/video/video_encoder.cc
@@ -76,6 +76,9 @@
if (channel_parameters_set_)
fallback_encoder_->SetChannelParameters(packet_loss_, rtt_);
+ fallback_implementation_name_ =
+ std::string(fallback_encoder_->ImplementationName()) +
+ " (fallback from: " + encoder_->ImplementationName() + ")";
// Since we're switching to the fallback encoder, Release the real encoder. It
// may be re-initialized via InitEncode later, and it will continue to get
// Set calls for rates and channel parameters in the meantime.
@@ -182,6 +185,12 @@
return encoder_->SupportsNativeHandle();
}
+const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
+ if (fallback_encoder_)
+ return fallback_implementation_name_.c_str();
+ return encoder_->ImplementationName();
+}
+
int VideoEncoderSoftwareFallbackWrapper::GetTargetFramerate() {
if (fallback_encoder_)
return fallback_encoder_->GetTargetFramerate();
diff --git a/webrtc/video/video_encoder_unittest.cc b/webrtc/video/video_encoder_unittest.cc
index b800a74..0f28f89 100644
--- a/webrtc/video/video_encoder_unittest.cc
+++ b/webrtc/video/video_encoder_unittest.cc
@@ -67,6 +67,10 @@
return false;
}
+ const char* ImplementationName() const override {
+ return "fake-encoder";
+ }
+
int init_encode_count_ = 0;
int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
@@ -259,4 +263,13 @@
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
}
+TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
+ ReportsFallbackImplementationName) {
+ UtilizeFallbackEncoder();
+ // Hard coded expected value since libvpx is the software implementation name
+ // for VP8. Change accordingly if the underlying implementation does.
+ EXPECT_STREQ("libvpx (fallback from: fake-encoder)",
+ fallback_wrapper_.ImplementationName());
+}
+
} // namespace webrtc
diff --git a/webrtc/video/vie_channel.cc b/webrtc/video/vie_channel.cc
index 6e2406a..e39ffbf 100644
--- a/webrtc/video/vie_channel.cc
+++ b/webrtc/video/vie_channel.cc
@@ -983,6 +983,12 @@
receive_stats_callback_->OnIncomingPayloadType(payload_type);
}
+void ViEChannel::OnDecoderImplementationName(const char* implementation_name) {
+ CriticalSectionScoped cs(crit_.get());
+ if (receive_stats_callback_)
+ receive_stats_callback_->OnDecoderImplementationName(implementation_name);
+}
+
void ViEChannel::OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) {
CriticalSectionScoped cs(crit_.get());
if (receive_stats_callback_)
diff --git a/webrtc/video/vie_channel.h b/webrtc/video/vie_channel.h
index 8f99260..25d06b9 100644
--- a/webrtc/video/vie_channel.h
+++ b/webrtc/video/vie_channel.h
@@ -230,6 +230,7 @@
// Implements VCMReceiveCallback.
void OnIncomingPayloadType(int payload_type) override;
+ void OnDecoderImplementationName(const char* implementation_name) override;
// Implements VCMReceiveStatisticsCallback.
void OnReceiveRatesUpdated(uint32_t bit_rate, uint32_t frame_rate) override;
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
index 803825c..a147b24 100644
--- a/webrtc/video/vie_encoder.cc
+++ b/webrtc/video/vie_encoder.cc
@@ -472,6 +472,12 @@
: -1;
}
+void ViEEncoder::OnEncoderImplementationName(
+ const char* implementation_name) {
+ if (stats_proxy_)
+ stats_proxy_->OnEncoderImplementationName(implementation_name);
+}
+
int32_t ViEEncoder::SendStatistics(const uint32_t bit_rate,
const uint32_t frame_rate) {
if (stats_proxy_)
diff --git a/webrtc/video/vie_encoder.h b/webrtc/video/vie_encoder.h
index b86287c..a15fd89 100644
--- a/webrtc/video/vie_encoder.h
+++ b/webrtc/video/vie_encoder.h
@@ -112,6 +112,7 @@
const EncodedImage& encoded_image,
const RTPFragmentationHeader& fragmentation_header,
const RTPVideoHeader* rtp_video_hdr) override;
+ void OnEncoderImplementationName(const char* implementation_name) override;
// Implements VideoSendStatisticsCallback.
int32_t SendStatistics(const uint32_t bit_rate,
diff --git a/webrtc/video_decoder.h b/webrtc/video_decoder.h
index 30e2779..3cd94e8 100644
--- a/webrtc/video_decoder.h
+++ b/webrtc/video_decoder.h
@@ -11,6 +11,7 @@
#ifndef WEBRTC_VIDEO_DECODER_H_
#define WEBRTC_VIDEO_DECODER_H_
+#include <string>
#include <vector>
#include "webrtc/common_types.h"
@@ -78,6 +79,8 @@
// That is, it can not decode infinite number of frames before the decoded
// frame is consumed.
virtual bool PrefersLateDecoding() const { return true; }
+
+ virtual const char* ImplementationName() const { return "unknown"; }
};
// Class used to wrap external VideoDecoders to provide a fallback option on
@@ -104,6 +107,8 @@
int32_t Reset() override;
bool PrefersLateDecoding() const override;
+ const char* ImplementationName() const override;
+
private:
bool InitFallbackDecoder();
@@ -112,6 +117,7 @@
VideoCodec codec_settings_;
int32_t number_of_cores_;
+ std::string fallback_implementation_name_;
rtc::scoped_ptr<VideoDecoder> fallback_decoder_;
DecodedImageCallback* callback_;
};
diff --git a/webrtc/video_encoder.h b/webrtc/video_encoder.h
index f255336..9e7e4d7 100644
--- a/webrtc/video_encoder.h
+++ b/webrtc/video_encoder.h
@@ -11,6 +11,7 @@
#ifndef WEBRTC_VIDEO_ENCODER_H_
#define WEBRTC_VIDEO_ENCODER_H_
+#include <string>
#include <vector>
#include "webrtc/common_types.h"
@@ -124,6 +125,7 @@
virtual void OnDroppedFrame() {}
virtual int GetTargetFramerate() { return -1; }
virtual bool SupportsNativeHandle() const { return false; }
+ virtual const char* ImplementationName() const { return "unknown"; }
};
// Class used to wrap external VideoEncoders to provide a fallback option on
@@ -151,6 +153,7 @@
void OnDroppedFrame() override;
int GetTargetFramerate() override;
bool SupportsNativeHandle() const override;
+ const char* ImplementationName() const override;
private:
bool InitFallbackEncoder();
@@ -175,6 +178,7 @@
webrtc::VideoEncoder* const encoder_;
rtc::scoped_ptr<webrtc::VideoEncoder> fallback_encoder_;
+ std::string fallback_implementation_name_;
EncodedImageCallback* callback_;
};
} // namespace webrtc
diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h
index cd1434c..51d8426 100644
--- a/webrtc/video_receive_stream.h
+++ b/webrtc/video_receive_stream.h
@@ -51,6 +51,7 @@
int render_frame_rate = 0;
// Decoder stats.
+ std::string decoder_implementation_name = "unknown";
FrameCounts frame_counts;
int decode_ms = 0;
int max_decode_ms = 0;
diff --git a/webrtc/video_send_stream.h b/webrtc/video_send_stream.h
index b5f8c9a..83a96d3 100644
--- a/webrtc/video_send_stream.h
+++ b/webrtc/video_send_stream.h
@@ -62,6 +62,7 @@
};
struct Stats {
+ std::string encoder_implementation_name = "unknown";
int input_frame_rate = 0;
int encode_frame_rate = 0;
int avg_encode_time_ms = 0;