Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/video/video_stream_decoder.h"
12 :
13 : #include <algorithm>
14 : #include <map>
15 : #include <vector>
16 :
17 : #include "webrtc/base/checks.h"
18 : #include "webrtc/base/logging.h"
19 : #include "webrtc/common_video/include/frame_callback.h"
20 : #include "webrtc/modules/video_coding/video_coding_impl.h"
21 : #include "webrtc/system_wrappers/include/metrics.h"
22 : #include "webrtc/video/call_stats.h"
23 : #include "webrtc/video/payload_router.h"
24 : #include "webrtc/video/receive_statistics_proxy.h"
25 :
26 : namespace webrtc {
27 :
28 0 : VideoStreamDecoder::VideoStreamDecoder(
29 : vcm::VideoReceiver* video_receiver,
30 : VCMFrameTypeCallback* vcm_frame_type_callback,
31 : VCMPacketRequestCallback* vcm_packet_request_callback,
32 : bool enable_nack,
33 : bool enable_fec,
34 : ReceiveStatisticsProxy* receive_statistics_proxy,
35 : rtc::VideoSinkInterface<VideoFrame>* incoming_video_stream,
36 0 : I420FrameCallback* pre_render_callback)
37 : : video_receiver_(video_receiver),
38 : receive_stats_callback_(receive_statistics_proxy),
39 : incoming_video_stream_(incoming_video_stream),
40 : pre_render_callback_(pre_render_callback),
41 0 : last_rtt_ms_(0) {
42 0 : RTC_DCHECK(video_receiver_);
43 :
44 : static const int kMaxPacketAgeToNack = 450;
45 : static const int kMaxNackListSize = 250;
46 0 : video_receiver_->SetNackSettings(kMaxNackListSize,
47 0 : kMaxPacketAgeToNack, 0);
48 0 : video_receiver_->RegisterReceiveCallback(this);
49 0 : video_receiver_->RegisterFrameTypeCallback(vcm_frame_type_callback);
50 0 : video_receiver_->RegisterReceiveStatisticsCallback(this);
51 0 : video_receiver_->RegisterDecoderTimingCallback(this);
52 :
53 : VCMVideoProtection video_protection =
54 0 : enable_nack ? (enable_fec ? kProtectionNackFEC : kProtectionNack)
55 0 : : kProtectionNone;
56 :
57 0 : VCMDecodeErrorMode decode_error_mode = enable_nack ? kNoErrors : kWithErrors;
58 0 : video_receiver_->SetVideoProtection(video_protection, true);
59 0 : video_receiver_->SetDecodeErrorMode(decode_error_mode);
60 : VCMPacketRequestCallback* packet_request_callback =
61 0 : enable_nack ? vcm_packet_request_callback : nullptr;
62 0 : video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
63 0 : }
64 :
65 0 : VideoStreamDecoder::~VideoStreamDecoder() {
66 : // Unset all the callback pointers that we set in the ctor.
67 0 : video_receiver_->RegisterPacketRequestCallback(nullptr);
68 0 : video_receiver_->RegisterDecoderTimingCallback(nullptr);
69 0 : video_receiver_->RegisterReceiveStatisticsCallback(nullptr);
70 0 : video_receiver_->RegisterFrameTypeCallback(nullptr);
71 0 : video_receiver_->RegisterReceiveStateCallback(nullptr);
72 0 : video_receiver_->RegisterReceiveCallback(nullptr);
73 0 : }
74 :
75 : // Do not acquire the lock of |video_receiver_| in this function. Decode
76 : // callback won't necessarily be called from the decoding thread. The decoding
77 : // thread may have held the lock when calling VideoDecoder::Decode, Reset, or
78 : // Release. Acquiring the same lock in the path of decode callback can deadlock.
79 0 : int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame) { // NOLINT
80 0 : if (pre_render_callback_) {
81 : // Post processing is not supported if the frame is backed by a texture.
82 0 : if (!video_frame.video_frame_buffer()->native_handle()) {
83 0 : pre_render_callback_->FrameCallback(&video_frame);
84 : }
85 : }
86 :
87 0 : incoming_video_stream_->OnFrame(video_frame);
88 :
89 0 : return 0;
90 : }
91 :
92 0 : int32_t VideoStreamDecoder::ReceivedDecodedReferenceFrame(
93 : const uint64_t picture_id) {
94 0 : RTC_NOTREACHED();
95 0 : return 0;
96 : }
97 :
98 0 : void VideoStreamDecoder::OnIncomingPayloadType(int payload_type) {
99 0 : receive_stats_callback_->OnIncomingPayloadType(payload_type);
100 0 : }
101 :
102 0 : void VideoStreamDecoder::OnDecoderImplementationName(
103 : const char* implementation_name) {
104 0 : receive_stats_callback_->OnDecoderImplementationName(implementation_name);
105 0 : }
106 :
107 0 : void VideoStreamDecoder::OnReceiveRatesUpdated(uint32_t bit_rate,
108 : uint32_t frame_rate) {
109 0 : receive_stats_callback_->OnIncomingRate(frame_rate, bit_rate);
110 0 : }
111 :
112 0 : void VideoStreamDecoder::OnDiscardedPacketsUpdated(int discarded_packets) {
113 0 : receive_stats_callback_->OnDiscardedPacketsUpdated(discarded_packets);
114 0 : }
115 :
116 0 : void VideoStreamDecoder::OnFrameCountsUpdated(const FrameCounts& frame_counts) {
117 0 : receive_stats_callback_->OnFrameCountsUpdated(frame_counts);
118 0 : }
119 :
120 0 : void VideoStreamDecoder::OnDecoderTiming(int decode_ms,
121 : int max_decode_ms,
122 : int current_delay_ms,
123 : int target_delay_ms,
124 : int jitter_buffer_ms,
125 : int min_playout_delay_ms,
126 : int render_delay_ms) {
127 0 : int last_rtt = -1;
128 : {
129 0 : rtc::CritScope lock(&crit_);
130 0 : last_rtt = last_rtt_ms_;
131 : }
132 :
133 0 : receive_stats_callback_->OnDecoderTiming(
134 : decode_ms, max_decode_ms, current_delay_ms, target_delay_ms,
135 0 : jitter_buffer_ms, min_playout_delay_ms, render_delay_ms, last_rtt);
136 0 : }
137 :
138 0 : void VideoStreamDecoder::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
139 0 : video_receiver_->SetReceiveChannelParameters(max_rtt_ms);
140 :
141 0 : rtc::CritScope lock(&crit_);
142 0 : last_rtt_ms_ = avg_rtt_ms;
143 0 : }
144 : } // namespace webrtc
|