webrtc_m130/video/video_stream_decoder.cc
Ilya Nikolaevskiy 94150ee487 Implement VideoQualityObserver
This class receives data about video frames from ReceiveStatisticsProxy,
calculates spatial and temporal quality metrics and outputs them to UMA
stats. It is all done in a separate class because it will be further
extended to calculate aggregated quality metrics in the future.

Bug: webrtc:9295
Change-Id: Ie36db83e10c0e8da0b9baa392651cb9a67a54a80
Reviewed-on: https://webrtc-review.googlesource.com/78220
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23387}
2018-05-24 14:53:31 +00:00

133 lines
5.3 KiB
C++

/*
* Copyright (c) 2012 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 "video/video_stream_decoder.h"
#include <algorithm>
#include <map>
#include <vector>
#include "common_video/include/frame_callback.h"
#include "modules/video_coding/video_coding_impl.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "system_wrappers/include/metrics.h"
#include "video/call_stats.h"
#include "video/payload_router.h"
#include "video/receive_statistics_proxy.h"
namespace webrtc {
VideoStreamDecoder::VideoStreamDecoder(
vcm::VideoReceiver* video_receiver,
VCMFrameTypeCallback* vcm_frame_type_callback,
VCMPacketRequestCallback* vcm_packet_request_callback,
bool enable_nack,
bool enable_fec,
ReceiveStatisticsProxy* receive_statistics_proxy,
rtc::VideoSinkInterface<VideoFrame>* incoming_video_stream)
: video_receiver_(video_receiver),
receive_stats_callback_(receive_statistics_proxy),
incoming_video_stream_(incoming_video_stream) {
RTC_DCHECK(video_receiver_);
static const int kMaxPacketAgeToNack = 450;
static const int kMaxNackListSize = 250;
video_receiver_->SetNackSettings(kMaxNackListSize,
kMaxPacketAgeToNack, 0);
video_receiver_->RegisterReceiveCallback(this);
video_receiver_->RegisterFrameTypeCallback(vcm_frame_type_callback);
video_receiver_->RegisterReceiveStatisticsCallback(this);
VCMVideoProtection video_protection =
enable_nack ? (enable_fec ? kProtectionNackFEC : kProtectionNack)
: kProtectionNone;
VCMDecodeErrorMode decode_error_mode = enable_nack ? kNoErrors : kWithErrors;
video_receiver_->SetVideoProtection(video_protection, true);
video_receiver_->SetDecodeErrorMode(decode_error_mode);
VCMPacketRequestCallback* packet_request_callback =
enable_nack ? vcm_packet_request_callback : nullptr;
video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
}
VideoStreamDecoder::~VideoStreamDecoder() {
// Note: There's an assumption at this point that the decoder thread is
// *not* running. If it was, then there could be a race for each of these
// callbacks.
// Unset all the callback pointers that we set in the ctor.
video_receiver_->RegisterPacketRequestCallback(nullptr);
video_receiver_->RegisterReceiveStatisticsCallback(nullptr);
video_receiver_->RegisterFrameTypeCallback(nullptr);
video_receiver_->RegisterReceiveCallback(nullptr);
}
// Do not acquire the lock of |video_receiver_| in this function. Decode
// callback won't necessarily be called from the decoding thread. The decoding
// thread may have held the lock when calling VideoDecoder::Decode, Reset, or
// Release. Acquiring the same lock in the path of decode callback can deadlock.
int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame,
rtc::Optional<uint8_t> qp,
VideoContentType content_type) {
receive_stats_callback_->OnDecodedFrame(qp, video_frame.width(),
video_frame.height(), content_type);
incoming_video_stream_->OnFrame(video_frame);
return 0;
}
int32_t VideoStreamDecoder::ReceivedDecodedReferenceFrame(
const uint64_t picture_id) {
RTC_NOTREACHED();
return 0;
}
void VideoStreamDecoder::OnIncomingPayloadType(int payload_type) {
receive_stats_callback_->OnIncomingPayloadType(payload_type);
}
void VideoStreamDecoder::OnDecoderImplementationName(
const char* implementation_name) {
receive_stats_callback_->OnDecoderImplementationName(implementation_name);
}
void VideoStreamDecoder::OnReceiveRatesUpdated(uint32_t bit_rate,
uint32_t frame_rate) {
receive_stats_callback_->OnIncomingRate(frame_rate, bit_rate);
}
void VideoStreamDecoder::OnDiscardedPacketsUpdated(int discarded_packets) {
receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets);
}
void VideoStreamDecoder::OnFrameCountsUpdated(const FrameCounts& frame_counts) {
receive_stats_callback_->OnFrameCountsUpdated(frame_counts);
}
void VideoStreamDecoder::OnFrameBufferTimingsUpdated(int decode_ms,
int max_decode_ms,
int current_delay_ms,
int target_delay_ms,
int jitter_buffer_ms,
int min_playout_delay_ms,
int render_delay_ms) {}
void VideoStreamDecoder::OnTimingFrameInfoUpdated(const TimingFrameInfo& info) {
}
void VideoStreamDecoder::OnCompleteFrame(bool is_keyframe,
size_t size_bytes,
VideoContentType content_type) {}
void VideoStreamDecoder::UpdateRtt(int64_t max_rtt_ms) {
video_receiver_->SetReceiveChannelParameters(max_rtt_ms);
}
} // namespace webrtc