Add stats for average QP per frame for VP8 (for received video streams):
"WebRTC.Video.Decoded.VP8.Qp"
BUG=chromium:512752
Review URL: https://codereview.webrtc.org/1340623002
Cr-Commit-Position: refs/heads/master@{#10349}
diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
index d2ec552..3bbf682 100644
--- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
@@ -795,8 +795,11 @@
header.fragmentationLength[0] = image->_length;
header.fragmentationPlType[0] = 0;
header.fragmentationTimeDiff[0] = 0;
- if (scale_)
- quality_scaler_.ReportQP(webrtc::vp8::GetQP(payload));
+ if (scale_) {
+ int qp;
+ if (webrtc::vp8::GetQp(payload, payload_size, &qp))
+ quality_scaler_.ReportQP(qp);
+ }
} else if (codecType_ == kVideoCodecH264) {
if (scale_) {
h264_bitstream_parser_.ParseBitstream(payload, payload_size);
diff --git a/webrtc/modules/video_coding/BUILD.gn b/webrtc/modules/video_coding/BUILD.gn
index e05ab85..7b3449c 100644
--- a/webrtc/modules/video_coding/BUILD.gn
+++ b/webrtc/modules/video_coding/BUILD.gn
@@ -96,8 +96,10 @@
"utility/frame_dropper.cc",
"utility/include/frame_dropper.h",
"utility/include/moving_average.h",
+ "utility/include/qp_parser.h",
"utility/include/quality_scaler.h",
"utility/include/vp8_header_parser.h",
+ "utility/qp_parser.cc",
"utility/quality_scaler.cc",
"utility/vp8_header_parser.cc",
]
diff --git a/webrtc/modules/video_coding/main/interface/video_coding.h b/webrtc/modules/video_coding/main/interface/video_coding.h
index 7fd2627..889be69 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding.h
@@ -132,7 +132,7 @@
// to have. Usually MTU - overhead.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterSendCodec(const VideoCodec* sendCodec,
uint32_t numberOfCores,
uint32_t maxPayloadSize) = 0;
@@ -154,7 +154,7 @@
// - currentSendCodec : Address where the sendCodec will be written.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
//
// NOTE: The returned codec information is not guaranteed to be current when
// the call returns. This method acquires a lock that is aligned with
@@ -180,7 +180,7 @@
// - payloadType : The payload type bound which this encoder is bound to.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterExternalEncoder(VideoEncoder* externalEncoder,
uint8_t payloadType,
bool internalSource = false) = 0;
@@ -232,7 +232,7 @@
// scenario
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t SetReceiveChannelParameters(int64_t rtt) = 0;
// Register a transport callback which will be called to deliver the encoded data and
@@ -242,7 +242,7 @@
// - transport : The callback object to register.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterTransportCallback(VCMPacketizationCallback* transport) = 0;
// Register video output information callback which will be called to deliver information
@@ -253,7 +253,7 @@
// - outputInformation : The callback object to register.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterSendStatisticsCallback(
VCMSendStatisticsCallback* sendStats) = 0;
@@ -264,7 +264,7 @@
// - protection : The callback object to register.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterProtectionCallback(VCMProtectionCallback* protection) = 0;
// Enable or disable a video protection method.
@@ -275,7 +275,7 @@
// it should be disabled.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t SetVideoProtection(VCMVideoProtection videoProtection,
bool enable) = 0;
@@ -289,7 +289,7 @@
// - codecSpecificInfo : Extra codec information, e.g., pre-parsed in-band signaling.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t AddVideoFrame(
const VideoFrame& videoFrame,
const VideoContentMetrics* contentMetrics = NULL,
@@ -298,7 +298,7 @@
// Next frame encoded should be an intra frame (keyframe).
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t IntraFrameRequest(int stream_index) = 0;
// Frame Dropper enable. Can be used to disable the frame dropping when the encoder
@@ -310,7 +310,7 @@
// - enable : True to enable the setting, false to disable it.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t EnableFrameDropper(bool enable) = 0;
@@ -329,7 +329,7 @@
// to be decoded until the first key frame has been decoded.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec,
int32_t numberOfCores,
bool requireKeyFrame = false) = 0;
@@ -346,7 +346,7 @@
// object can make sure to render at a given time in ms.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterExternalDecoder(VideoDecoder* externalDecoder,
uint8_t payloadType,
bool internalRenderTiming) = 0;
@@ -360,7 +360,7 @@
// De-register with a NULL pointer.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterReceiveCallback(VCMReceiveCallback* receiveCallback) = 0;
// Register a receive statistics callback which will be called to deliver information
@@ -371,7 +371,7 @@
// - receiveStats : The callback object to register.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterReceiveStatisticsCallback(
VCMReceiveStatisticsCallback* receiveStats) = 0;
@@ -383,7 +383,7 @@
// - decoderTiming : The callback object to register.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterDecoderTimingCallback(
VCMDecoderTimingCallback* decoderTiming) = 0;
@@ -396,7 +396,7 @@
// De-register with a NULL pointer.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t RegisterFrameTypeCallback(
VCMFrameTypeCallback* frameTypeCallback) = 0;
@@ -407,7 +407,7 @@
// - callback : The callback to be registered in the VCM.
//
// Return value : VCM_OK, on success.
- // <0, on error.
+ // <0, on error.
virtual int32_t RegisterPacketRequestCallback(
VCMPacketRequestCallback* callback) = 0;
@@ -416,7 +416,7 @@
// Should be called as often as possible to get the most out of the decoder.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t Decode(uint16_t maxWaitTimeMs = 200) = 0;
// Registers a callback which conveys the size of the render buffer.
@@ -426,7 +426,7 @@
// Reset the decoder state to the initial state.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t ResetDecoder() = 0;
// API to get the codec which is currently used for decoding by the module.
@@ -435,7 +435,7 @@
// - currentReceiveCodec : Settings for the codec to be registered.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t ReceiveCodec(VideoCodec* currentReceiveCodec) const = 0;
// API to get the codec type currently used for decoding by the module.
@@ -454,7 +454,7 @@
// - rtpInfo : The parsed header.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t IncomingPacket(const uint8_t* incomingPayload,
size_t payloadLength,
const WebRtcRTPHeader& rtpInfo) = 0;
@@ -467,7 +467,7 @@
// - minPlayoutDelayMs : Additional delay in ms.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) = 0;
// Set the time required by the renderer to render a frame.
@@ -476,7 +476,7 @@
// - timeMS : The time in ms required by the renderer to render a frame.
//
// Return value : VCM_OK, on success.
- // < 0, on error.
+ // < 0, on error.
virtual int32_t SetRenderDelay(uint32_t timeMS) = 0;
// The total delay desired by the VCM. Can be less than the minimum
diff --git a/webrtc/modules/video_coding/main/source/video_coding_impl.h b/webrtc/modules/video_coding/main/source/video_coding_impl.h
index 6813666..2d9dc06 100644
--- a/webrtc/modules/video_coding/main/source/video_coding_impl.h
+++ b/webrtc/modules/video_coding/main/source/video_coding_impl.h
@@ -25,6 +25,7 @@
#include "webrtc/modules/video_coding/main/source/media_optimization.h"
#include "webrtc/modules/video_coding/main/source/receiver.h"
#include "webrtc/modules/video_coding/main/source/timing.h"
+#include "webrtc/modules/video_coding/utility/include/qp_parser.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
@@ -237,6 +238,7 @@
VCMProcessTimer _receiveStatsTimer;
VCMProcessTimer _retransmissionTimer;
VCMProcessTimer _keyRequestTimer;
+ QpParser qp_parser_;
};
} // namespace vcm
diff --git a/webrtc/modules/video_coding/main/source/video_receiver.cc b/webrtc/modules/video_coding/main/source/video_receiver.cc
index 76d2c9f..2e23b5e 100644
--- a/webrtc/modules/video_coding/main/source/video_receiver.cc
+++ b/webrtc/modules/video_coding/main/source/video_receiver.cc
@@ -302,7 +302,12 @@
if (pre_decode_image_callback_) {
EncodedImage encoded_image(frame->EncodedImage());
- pre_decode_image_callback_->Encoded(encoded_image, NULL, NULL);
+ 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
diff --git a/webrtc/modules/video_coding/utility/include/qp_parser.h b/webrtc/modules/video_coding/utility/include/qp_parser.h
new file mode 100644
index 0000000..805b37b
--- /dev/null
+++ b/webrtc/modules/video_coding/utility/include/qp_parser.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_QP_PARSER_H_
+#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_QP_PARSER_H_
+
+#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
+
+namespace webrtc {
+
+class QpParser {
+ public:
+ QpParser() {}
+ ~QpParser() {}
+
+ // Parses an encoded |frame| and extracts the |qp|.
+ // Returns true on success, false otherwise.
+ bool GetQp(const VCMEncodedFrame& frame, int* qp);
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_QP_PARSER_H_
diff --git a/webrtc/modules/video_coding/utility/include/vp8_header_parser.h b/webrtc/modules/video_coding/utility/include/vp8_header_parser.h
index 839e093..88796ec 100644
--- a/webrtc/modules/video_coding/utility/include/vp8_header_parser.h
+++ b/webrtc/modules/video_coding/utility/include/vp8_header_parser.h
@@ -66,7 +66,9 @@
241, 243, 245, 247, 249, 251, 253, 127
};
-int GetQP(uint8_t* buf);
+// Gets the QP, QP range: [0, 127].
+// Returns true on success, false otherwise.
+bool GetQp(const uint8_t* buf, size_t length, int* qp);
} // namespace vp8
diff --git a/webrtc/modules/video_coding/utility/qp_parser.cc b/webrtc/modules/video_coding/utility/qp_parser.cc
new file mode 100644
index 0000000..62ce313
--- /dev/null
+++ b/webrtc/modules/video_coding/utility/qp_parser.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/video_coding/utility/include/qp_parser.h"
+
+#include "webrtc/common_types.h"
+#include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h"
+
+namespace webrtc {
+
+bool QpParser::GetQp(const VCMEncodedFrame& frame, int* qp) {
+ switch (frame.CodecSpecific()->codecType) {
+ case kVideoCodecVP8:
+ // QP range: [0, 127].
+ return vp8::GetQp(frame.Buffer(), frame.Length(), qp);
+ default:
+ return false;
+ }
+}
+
+} // namespace webrtc
diff --git a/webrtc/modules/video_coding/utility/video_coding_utility.gyp b/webrtc/modules/video_coding/utility/video_coding_utility.gyp
index d562848..f0764bb 100644
--- a/webrtc/modules/video_coding/utility/video_coding_utility.gyp
+++ b/webrtc/modules/video_coding/utility/video_coding_utility.gyp
@@ -21,8 +21,10 @@
'frame_dropper.cc',
'include/frame_dropper.h',
'include/moving_average.h',
+ 'include/qp_parser.h',
'include/quality_scaler.h',
'include/vp8_header_parser.h',
+ 'qp_parser.cc',
'quality_scaler.cc',
'vp8_header_parser.cc',
],
diff --git a/webrtc/modules/video_coding/utility/vp8_header_parser.cc b/webrtc/modules/video_coding/utility/vp8_header_parser.cc
index 0b0bfa2..9fcd6e4 100644
--- a/webrtc/modules/video_coding/utility/vp8_header_parser.cc
+++ b/webrtc/modules/video_coding/utility/vp8_header_parser.cc
@@ -12,9 +12,15 @@
#include "webrtc/modules/video_coding/utility/include/vp8_header_parser.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+
namespace webrtc {
namespace vp8 {
+namespace {
+const size_t kCommonPayloadHeaderLength = 3;
+const size_t kKeyPayloadHeaderLength = 10;
+} // namespace
static uint32_t BSwap32(uint32_t x) {
return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
@@ -156,18 +162,26 @@
}
}
-int GetQP(uint8_t* buf) {
+bool GetQp(const uint8_t* buf, size_t length, int* qp) {
+ if (length < kCommonPayloadHeaderLength) {
+ LOG(LS_WARNING) << "Failed to get QP, invalid length.";
+ return false;
+ }
VP8BitReader br;
const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
int key_frame = !(bits & 1);
// Size of first partition in bytes.
- int partition_length = (bits >> 5);
- // Skip past uncompressed header: 10bytes for key, 3bytes for delta frames.
+ uint32_t partition_length = (bits >> 5);
+ size_t header_length = kCommonPayloadHeaderLength;
if (key_frame) {
- buf += 10;
- } else {
- buf += 3;
+ header_length = kKeyPayloadHeaderLength;
}
+ if (header_length + partition_length > length) {
+ LOG(LS_WARNING) << "Failed to get QP, invalid length: " << length;
+ return false;
+ }
+ buf += header_length;
+
VP8InitBitReader(&br, buf, buf + partition_length);
if (key_frame) {
// Color space and pixel type.
@@ -180,7 +194,12 @@
VP8GetValue(&br, 2);
// Base QP.
const int base_q0 = VP8GetValue(&br, 7);
- return base_q0;
+ if (br.eof_ == 1) {
+ LOG(LS_WARNING) << "Failed to get QP, end of file reached.";
+ return false;
+ }
+ *qp = base_q0;
+ return true;
}
} // namespace vp8
diff --git a/webrtc/system_wrappers/interface/metrics.h b/webrtc/system_wrappers/interface/metrics.h
index cb641c0..7ebe3bd 100644
--- a/webrtc/system_wrappers/interface/metrics.h
+++ b/webrtc/system_wrappers/interface/metrics.h
@@ -72,6 +72,9 @@
#define RTC_HISTOGRAM_COUNTS_100(name, sample) RTC_HISTOGRAM_COUNTS( \
name, sample, 1, 100, 50)
+#define RTC_HISTOGRAM_COUNTS_200(name, sample) RTC_HISTOGRAM_COUNTS( \
+ name, sample, 1, 200, 50)
+
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) RTC_HISTOGRAM_COUNTS( \
name, sample, 1, 1000, 50)
diff --git a/webrtc/video/receive_statistics_proxy.cc b/webrtc/video/receive_statistics_proxy.cc
index 6b79e9c..5b456a8 100644
--- a/webrtc/video/receive_statistics_proxy.cc
+++ b/webrtc/video/receive_statistics_proxy.cc
@@ -13,6 +13,7 @@
#include <cmath>
#include "webrtc/base/checks.h"
+#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/metrics.h"
@@ -53,6 +54,10 @@
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedWidthInPixels", width);
RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedHeightInPixels", height);
}
+ int qp = qp_counters_.vp8.Avg(kMinRequiredSamples);
+ if (qp != -1)
+ RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", qp);
+
// TODO(asapersson): DecoderTiming() is call periodically (each 1000ms) and
// not per frame. Change decode time to include every frame.
const int kMinRequiredDecodeSamples = 5;
@@ -180,6 +185,17 @@
stats_.discarded_packets = discarded_packets;
}
+void ReceiveStatisticsProxy::OnPreDecode(
+ const EncodedImage& encoded_image,
+ const CodecSpecificInfo* codec_specific_info) {
+ if (codec_specific_info == nullptr || encoded_image.qp_ == -1) {
+ return;
+ }
+ if (codec_specific_info->codecType == kVideoCodecVP8) {
+ qp_counters_.vp8.Add(encoded_image.qp_);
+ }
+}
+
void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
sum += sample;
++num_samples;
diff --git a/webrtc/video/receive_statistics_proxy.h b/webrtc/video/receive_statistics_proxy.h
index 6e4fd3a..b6741f9 100644
--- a/webrtc/video/receive_statistics_proxy.h
+++ b/webrtc/video/receive_statistics_proxy.h
@@ -30,6 +30,7 @@
class Clock;
class ViECodec;
class ViEDecoderObserver;
+struct CodecSpecificInfo;
class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback,
public RtcpStatisticsCallback,
@@ -54,6 +55,9 @@
int render_delay_ms,
int64_t rtt_ms);
+ void OnPreDecode(const EncodedImage& encoded_image,
+ const CodecSpecificInfo* codec_specific_info);
+
// Overrides VCMReceiveStatisticsCallback.
void OnReceiveRatesUpdated(uint32_t bitRate, uint32_t frameRate) override;
void OnFrameCountsUpdated(const FrameCounts& frame_counts) override;
@@ -82,6 +86,9 @@
int sum;
int num_samples;
};
+ struct QpCounters {
+ SampleCounter vp8;
+ };
void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_);
@@ -98,6 +105,7 @@
SampleCounter decode_time_counter_ GUARDED_BY(crit_);
SampleCounter delay_counter_ GUARDED_BY(crit_);
ReportBlockStats report_block_stats_ GUARDED_BY(crit_);
+ QpCounters qp_counters_; // Only accessed on the decoding thread.
};
} // namespace webrtc
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc
index bbcc66a..e892989 100644
--- a/webrtc/video/video_receive_stream.cc
+++ b/webrtc/video/video_receive_stream.cc
@@ -19,7 +19,6 @@
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video/receive_statistics_proxy.h"
-#include "webrtc/video_encoder.h"
#include "webrtc/video_engine/call_stats.h"
#include "webrtc/video_receive_stream.h"
@@ -277,8 +276,7 @@
incoming_video_stream_->SetExternalCallback(this);
vie_channel_->SetIncomingVideoStream(incoming_video_stream_.get());
- if (config.pre_decode_callback)
- vie_channel_->RegisterPreDecodeImageCallback(&encoded_frame_proxy_);
+ vie_channel_->RegisterPreDecodeImageCallback(this);
vie_channel_->RegisterPreRenderCallback(this);
}
@@ -364,6 +362,21 @@
return 0;
}
+// TODO(asapersson): Consider moving callback from video_encoder.h or
+// creating a different callback.
+int32_t VideoReceiveStream::Encoded(
+ const EncodedImage& encoded_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const RTPFragmentationHeader* fragmentation) {
+ stats_proxy_->OnPreDecode(encoded_image, codec_specific_info);
+ if (config_.pre_decode_callback) {
+ // TODO(asapersson): Remove EncodedFrameCallbackAdapter.
+ encoded_frame_proxy_.Encoded(
+ encoded_image, codec_specific_info, fragmentation);
+ }
+ return 0;
+}
+
void VideoReceiveStream::SignalNetworkState(NetworkState state) {
vie_channel_->SetRTCPMode(state == kNetworkUp ? config_.rtp.rtcp_mode
: RtcpMode::kOff);
diff --git a/webrtc/video/video_receive_stream.h b/webrtc/video/video_receive_stream.h
index 011788d..fbea604 100644
--- a/webrtc/video/video_receive_stream.h
+++ b/webrtc/video/video_receive_stream.h
@@ -22,6 +22,7 @@
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/video/encoded_frame_callback_adapter.h"
#include "webrtc/video/receive_statistics_proxy.h"
+#include "webrtc/video_encoder.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_group.h"
#include "webrtc/video_engine/vie_encoder.h"
@@ -35,7 +36,8 @@
class VideoReceiveStream : public webrtc::VideoReceiveStream,
public I420FrameCallback,
- public VideoRenderCallback {
+ public VideoRenderCallback,
+ public EncodedImageCallback {
public:
VideoReceiveStream(int num_cpu_cores,
ChannelGroup* channel_group,
@@ -63,6 +65,11 @@
int RenderFrame(const uint32_t /*stream_id*/,
const VideoFrame& video_frame) override;
+ // Overrides EncodedImageCallback.
+ int32_t Encoded(const EncodedImage& encoded_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const RTPFragmentationHeader* fragmentation) override;
+
const Config& config() const { return config_; }
void SetSyncChannel(VoiceEngine* voice_engine, int audio_channel_id);
diff --git a/webrtc/video_frame.h b/webrtc/video_frame.h
index 821bfc2..ecc23c9 100644
--- a/webrtc/video_frame.h
+++ b/webrtc/video_frame.h
@@ -199,6 +199,7 @@
size_t _size;
bool _completeFrame = false;
AdaptReason adapt_reason_;
+ int qp_ = -1; // Quantizer value.
};
} // namespace webrtc