webrtc_m130/webrtc/video/video_stream_decoder.cc
tommi d0a71ba1ae Updates to VCMDecodedFrameCallback, VideoReceiver and a few related classes/tests.
* The _receiveCallback member of VCMDecodedFrameCallback does actually not require locking now that the threading model is slightly clearer. Documentation and checks have been added.
* UserReceiveCallback() never returns null and must always be called on the decoder thread. Checks have been added and the two test suites that were failing to set this callback, have been fixed and a new mock class added.  (looks like sakal@ may have hit some issues with flaky tests there).
* Changed VcmPayloadSink to use move semantics which I suspect was the intention at the time the code was written (when we didn't have move semantics).
* Added thread checker to a couple of classes and started adding thread checks for known behavior.  There's more to be  done there.
* Remove the |_decoder| member variable in VideoReceiver. It is not needed and as it could be used, left us open to a race.
* TODOs added for places where we can reduce locking. I suspect that we can get away with not needing a lock around _codecDataBase in VideoReceiver once we've got a clear picture of the threading model and ensured that all adhere to it.

BUG=webrtc:7328

Review-Url: https://codereview.webrtc.org/2744013002
Cr-Commit-Position: refs/heads/master@{#17226}
2017-03-14 11:16:20 +00:00

141 lines
5.6 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 "webrtc/video/video_stream_decoder.h"
#include <algorithm>
#include <map>
#include <vector>
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/common_video/include/frame_callback.h"
#include "webrtc/modules/video_coding/video_coding_impl.h"
#include "webrtc/system_wrappers/include/metrics.h"
#include "webrtc/video/call_stats.h"
#include "webrtc/video/payload_router.h"
#include "webrtc/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),
last_rtt_ms_(0) {
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);
video_receiver_->RegisterDecoderTimingCallback(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_->RegisterDecoderTimingCallback(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) {
receive_stats_callback_->OnDecodedFrame(qp);
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::OnDecoderTiming(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::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::OnCompleteFrame(bool is_keyframe, size_t size_bytes) {}
void VideoStreamDecoder::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
video_receiver_->SetReceiveChannelParameters(max_rtt_ms);
rtc::CritScope lock(&crit_);
last_rtt_ms_ = avg_rtt_ms;
}
} // namespace webrtc