diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc index d2ec552834..3bbf6827f5 100644 --- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc +++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc @@ -795,8 +795,11 @@ bool MediaCodecVideoEncoder::DeliverPendingOutputs(JNIEnv* jni) { 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 e05ab855e8..7b3449c08a 100644 --- a/webrtc/modules/video_coding/BUILD.gn +++ b/webrtc/modules/video_coding/BUILD.gn @@ -96,8 +96,10 @@ source_set("video_coding_utility") { "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 7fd26273f0..889be69303 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 @@ public: // 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 @@ public: // - 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 @@ public: // - 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 @@ public: // 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 @@ public: // - 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 @@ public: // - 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 @@ public: // - 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 @@ public: // 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 @@ public: // - 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 @@ public: // 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 @@ public: // - 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 @@ public: // 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 @@ public: // 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 @@ public: // 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 @@ public: // - 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 @@ public: // - 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 @@ public: // 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 @@ public: // - 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 @@ public: // 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 @@ public: // 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 @@ public: // - 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 @@ public: // - 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 @@ public: // - 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 @@ public: // - 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 6813666bd0..2d9dc06025 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 @@ class VideoReceiver { 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 76d2c9f2db..2e23b5ef69 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 @@ int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { 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 0000000000..805b37b45c --- /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 839e0933fc..88796ecd0e 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 @@ const uint8_t kVP8NewRange[128] = { 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 0000000000..62ce31351e --- /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 d5628489a9..f0764bb7bf 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 0b0bfa235c..9fcd6e4f0c 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 @@ static void ParseFilterHeader(VP8BitReader* br) { } } -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 @@ int GetQP(uint8_t* buf) { 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 cb641c0674..7ebe3bde3d 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 6b79e9ca5e..5b456a817f 100644 --- a/webrtc/video/receive_statistics_proxy.cc +++ b/webrtc/video/receive_statistics_proxy.cc @@ -13,6 +13,7 @@ #include #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 @@ void ReceiveStatisticsProxy::UpdateHistograms() { 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 @@ void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) { 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 6e4fd3a618..b6741f9cde 100644 --- a/webrtc/video/receive_statistics_proxy.h +++ b/webrtc/video/receive_statistics_proxy.h @@ -30,6 +30,7 @@ namespace webrtc { class Clock; class ViECodec; class ViEDecoderObserver; +struct CodecSpecificInfo; class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, public RtcpStatisticsCallback, @@ -54,6 +55,9 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, 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 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, int sum; int num_samples; }; + struct QpCounters { + SampleCounter vp8; + }; void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_); @@ -98,6 +105,7 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, 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 bbcc66aa12..e892989f16 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 @@ VideoReceiveStream::VideoReceiveStream(int num_cpu_cores, 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 @@ int VideoReceiveStream::RenderFrame(const uint32_t /*stream_id*/, 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 011788d6b8..fbea604267 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 @@ namespace internal { 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 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream, 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 821bfc2551..ecc23c94b6 100644 --- a/webrtc/video_frame.h +++ b/webrtc/video_frame.h @@ -199,6 +199,7 @@ class EncodedImage { size_t _size; bool _completeFrame = false; AdaptReason adapt_reason_; + int qp_ = -1; // Quantizer value. }; } // namespace webrtc