1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/receiver.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker
14*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
15*d9f75844SAndroid Build Coastguard Worker #include <cstdlib>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/video/encoded_image.h"
21*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/encoded_frame.h"
22*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/internal_defines.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/jitter_buffer_common.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
27*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h"
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker enum { kMaxReceiverDelayMs = 10000 };
32*d9f75844SAndroid Build Coastguard Worker
VCMReceiver(VCMTiming * timing,Clock * clock,const FieldTrialsView & field_trials)33*d9f75844SAndroid Build Coastguard Worker VCMReceiver::VCMReceiver(VCMTiming* timing,
34*d9f75844SAndroid Build Coastguard Worker Clock* clock,
35*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials)
36*d9f75844SAndroid Build Coastguard Worker : VCMReceiver::VCMReceiver(timing,
37*d9f75844SAndroid Build Coastguard Worker clock,
38*d9f75844SAndroid Build Coastguard Worker absl::WrapUnique(EventWrapper::Create()),
39*d9f75844SAndroid Build Coastguard Worker absl::WrapUnique(EventWrapper::Create()),
40*d9f75844SAndroid Build Coastguard Worker field_trials) {}
41*d9f75844SAndroid Build Coastguard Worker
VCMReceiver(VCMTiming * timing,Clock * clock,std::unique_ptr<EventWrapper> receiver_event,std::unique_ptr<EventWrapper> jitter_buffer_event,const FieldTrialsView & field_trials)42*d9f75844SAndroid Build Coastguard Worker VCMReceiver::VCMReceiver(VCMTiming* timing,
43*d9f75844SAndroid Build Coastguard Worker Clock* clock,
44*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<EventWrapper> receiver_event,
45*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<EventWrapper> jitter_buffer_event,
46*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials)
47*d9f75844SAndroid Build Coastguard Worker : clock_(clock),
48*d9f75844SAndroid Build Coastguard Worker jitter_buffer_(clock_, std::move(jitter_buffer_event), field_trials),
49*d9f75844SAndroid Build Coastguard Worker timing_(timing),
50*d9f75844SAndroid Build Coastguard Worker render_wait_event_(std::move(receiver_event)),
51*d9f75844SAndroid Build Coastguard Worker max_video_delay_ms_(kMaxVideoDelayMs) {
52*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.Start();
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker
~VCMReceiver()55*d9f75844SAndroid Build Coastguard Worker VCMReceiver::~VCMReceiver() {
56*d9f75844SAndroid Build Coastguard Worker render_wait_event_->Set();
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker
InsertPacket(const VCMPacket & packet)59*d9f75844SAndroid Build Coastguard Worker int32_t VCMReceiver::InsertPacket(const VCMPacket& packet) {
60*d9f75844SAndroid Build Coastguard Worker // Insert the packet into the jitter buffer. The packet can either be empty or
61*d9f75844SAndroid Build Coastguard Worker // contain media at this point.
62*d9f75844SAndroid Build Coastguard Worker bool retransmitted = false;
63*d9f75844SAndroid Build Coastguard Worker const VCMFrameBufferEnum ret =
64*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.InsertPacket(packet, &retransmitted);
65*d9f75844SAndroid Build Coastguard Worker if (ret == kOldPacket) {
66*d9f75844SAndroid Build Coastguard Worker return VCM_OK;
67*d9f75844SAndroid Build Coastguard Worker } else if (ret == kFlushIndicator) {
68*d9f75844SAndroid Build Coastguard Worker return VCM_FLUSH_INDICATOR;
69*d9f75844SAndroid Build Coastguard Worker } else if (ret < 0) {
70*d9f75844SAndroid Build Coastguard Worker return VCM_JITTER_BUFFER_ERROR;
71*d9f75844SAndroid Build Coastguard Worker }
72*d9f75844SAndroid Build Coastguard Worker if (ret == kCompleteSession && !retransmitted) {
73*d9f75844SAndroid Build Coastguard Worker // We don't want to include timestamps which have suffered from
74*d9f75844SAndroid Build Coastguard Worker // retransmission here, since we compensate with extra retransmission
75*d9f75844SAndroid Build Coastguard Worker // delay within the jitter estimate.
76*d9f75844SAndroid Build Coastguard Worker timing_->IncomingTimestamp(packet.timestamp, clock_->CurrentTime());
77*d9f75844SAndroid Build Coastguard Worker }
78*d9f75844SAndroid Build Coastguard Worker return VCM_OK;
79*d9f75844SAndroid Build Coastguard Worker }
80*d9f75844SAndroid Build Coastguard Worker
FrameForDecoding(uint16_t max_wait_time_ms,bool prefer_late_decoding)81*d9f75844SAndroid Build Coastguard Worker VCMEncodedFrame* VCMReceiver::FrameForDecoding(uint16_t max_wait_time_ms,
82*d9f75844SAndroid Build Coastguard Worker bool prefer_late_decoding) {
83*d9f75844SAndroid Build Coastguard Worker const int64_t start_time_ms = clock_->TimeInMilliseconds();
84*d9f75844SAndroid Build Coastguard Worker uint32_t frame_timestamp = 0;
85*d9f75844SAndroid Build Coastguard Worker int min_playout_delay_ms = -1;
86*d9f75844SAndroid Build Coastguard Worker int max_playout_delay_ms = -1;
87*d9f75844SAndroid Build Coastguard Worker int64_t render_time_ms = 0;
88*d9f75844SAndroid Build Coastguard Worker // Exhaust wait time to get a complete frame for decoding.
89*d9f75844SAndroid Build Coastguard Worker VCMEncodedFrame* found_frame =
90*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.NextCompleteFrame(max_wait_time_ms);
91*d9f75844SAndroid Build Coastguard Worker
92*d9f75844SAndroid Build Coastguard Worker if (found_frame) {
93*d9f75844SAndroid Build Coastguard Worker frame_timestamp = found_frame->Timestamp();
94*d9f75844SAndroid Build Coastguard Worker min_playout_delay_ms = found_frame->EncodedImage().playout_delay_.min_ms;
95*d9f75844SAndroid Build Coastguard Worker max_playout_delay_ms = found_frame->EncodedImage().playout_delay_.max_ms;
96*d9f75844SAndroid Build Coastguard Worker } else {
97*d9f75844SAndroid Build Coastguard Worker return nullptr;
98*d9f75844SAndroid Build Coastguard Worker }
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker if (min_playout_delay_ms >= 0)
101*d9f75844SAndroid Build Coastguard Worker timing_->set_min_playout_delay(TimeDelta::Millis(min_playout_delay_ms));
102*d9f75844SAndroid Build Coastguard Worker
103*d9f75844SAndroid Build Coastguard Worker if (max_playout_delay_ms >= 0)
104*d9f75844SAndroid Build Coastguard Worker timing_->set_max_playout_delay(TimeDelta::Millis(max_playout_delay_ms));
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker // We have a frame - Set timing and render timestamp.
107*d9f75844SAndroid Build Coastguard Worker timing_->SetJitterDelay(
108*d9f75844SAndroid Build Coastguard Worker TimeDelta::Millis(jitter_buffer_.EstimatedJitterMs()));
109*d9f75844SAndroid Build Coastguard Worker const Timestamp now = clock_->CurrentTime();
110*d9f75844SAndroid Build Coastguard Worker const int64_t now_ms = now.ms();
111*d9f75844SAndroid Build Coastguard Worker timing_->UpdateCurrentDelay(frame_timestamp);
112*d9f75844SAndroid Build Coastguard Worker render_time_ms = timing_->RenderTime(frame_timestamp, now).ms();
113*d9f75844SAndroid Build Coastguard Worker // Check render timing.
114*d9f75844SAndroid Build Coastguard Worker bool timing_error = false;
115*d9f75844SAndroid Build Coastguard Worker // Assume that render timing errors are due to changes in the video stream.
116*d9f75844SAndroid Build Coastguard Worker if (render_time_ms < 0) {
117*d9f75844SAndroid Build Coastguard Worker timing_error = true;
118*d9f75844SAndroid Build Coastguard Worker } else if (std::abs(render_time_ms - now_ms) > max_video_delay_ms_) {
119*d9f75844SAndroid Build Coastguard Worker int frame_delay = static_cast<int>(std::abs(render_time_ms - now_ms));
120*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
121*d9f75844SAndroid Build Coastguard Worker << "A frame about to be decoded is out of the configured "
122*d9f75844SAndroid Build Coastguard Worker "delay bounds ("
123*d9f75844SAndroid Build Coastguard Worker << frame_delay << " > " << max_video_delay_ms_
124*d9f75844SAndroid Build Coastguard Worker << "). Resetting the video jitter buffer.";
125*d9f75844SAndroid Build Coastguard Worker timing_error = true;
126*d9f75844SAndroid Build Coastguard Worker } else if (static_cast<int>(timing_->TargetVideoDelay().ms()) >
127*d9f75844SAndroid Build Coastguard Worker max_video_delay_ms_) {
128*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "The video target delay has grown larger than "
129*d9f75844SAndroid Build Coastguard Worker << max_video_delay_ms_
130*d9f75844SAndroid Build Coastguard Worker << " ms. Resetting jitter buffer.";
131*d9f75844SAndroid Build Coastguard Worker timing_error = true;
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker
134*d9f75844SAndroid Build Coastguard Worker if (timing_error) {
135*d9f75844SAndroid Build Coastguard Worker // Timing error => reset timing and flush the jitter buffer.
136*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.Flush();
137*d9f75844SAndroid Build Coastguard Worker timing_->Reset();
138*d9f75844SAndroid Build Coastguard Worker return NULL;
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker if (prefer_late_decoding) {
142*d9f75844SAndroid Build Coastguard Worker // Decode frame as close as possible to the render timestamp.
143*d9f75844SAndroid Build Coastguard Worker const int32_t available_wait_time =
144*d9f75844SAndroid Build Coastguard Worker max_wait_time_ms -
145*d9f75844SAndroid Build Coastguard Worker static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms);
146*d9f75844SAndroid Build Coastguard Worker uint16_t new_max_wait_time =
147*d9f75844SAndroid Build Coastguard Worker static_cast<uint16_t>(VCM_MAX(available_wait_time, 0));
148*d9f75844SAndroid Build Coastguard Worker uint32_t wait_time_ms = rtc::saturated_cast<uint32_t>(
149*d9f75844SAndroid Build Coastguard Worker timing_
150*d9f75844SAndroid Build Coastguard Worker ->MaxWaitingTime(Timestamp::Millis(render_time_ms),
151*d9f75844SAndroid Build Coastguard Worker clock_->CurrentTime(),
152*d9f75844SAndroid Build Coastguard Worker /*too_many_frames_queued=*/false)
153*d9f75844SAndroid Build Coastguard Worker .ms());
154*d9f75844SAndroid Build Coastguard Worker if (new_max_wait_time < wait_time_ms) {
155*d9f75844SAndroid Build Coastguard Worker // We're not allowed to wait until the frame is supposed to be rendered,
156*d9f75844SAndroid Build Coastguard Worker // waiting as long as we're allowed to avoid busy looping, and then return
157*d9f75844SAndroid Build Coastguard Worker // NULL. Next call to this function might return the frame.
158*d9f75844SAndroid Build Coastguard Worker render_wait_event_->Wait(new_max_wait_time);
159*d9f75844SAndroid Build Coastguard Worker return NULL;
160*d9f75844SAndroid Build Coastguard Worker }
161*d9f75844SAndroid Build Coastguard Worker // Wait until it's time to render.
162*d9f75844SAndroid Build Coastguard Worker render_wait_event_->Wait(wait_time_ms);
163*d9f75844SAndroid Build Coastguard Worker }
164*d9f75844SAndroid Build Coastguard Worker
165*d9f75844SAndroid Build Coastguard Worker // Extract the frame from the jitter buffer and set the render time.
166*d9f75844SAndroid Build Coastguard Worker VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp);
167*d9f75844SAndroid Build Coastguard Worker if (frame == NULL) {
168*d9f75844SAndroid Build Coastguard Worker return NULL;
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker frame->SetRenderTime(render_time_ms);
171*d9f75844SAndroid Build Coastguard Worker TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame->Timestamp(), "SetRenderTS",
172*d9f75844SAndroid Build Coastguard Worker "render_time", frame->RenderTimeMs());
173*d9f75844SAndroid Build Coastguard Worker return frame;
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker
ReleaseFrame(VCMEncodedFrame * frame)176*d9f75844SAndroid Build Coastguard Worker void VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame) {
177*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.ReleaseFrame(frame);
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker
SetNackSettings(size_t max_nack_list_size,int max_packet_age_to_nack,int max_incomplete_time_ms)180*d9f75844SAndroid Build Coastguard Worker void VCMReceiver::SetNackSettings(size_t max_nack_list_size,
181*d9f75844SAndroid Build Coastguard Worker int max_packet_age_to_nack,
182*d9f75844SAndroid Build Coastguard Worker int max_incomplete_time_ms) {
183*d9f75844SAndroid Build Coastguard Worker jitter_buffer_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
184*d9f75844SAndroid Build Coastguard Worker max_incomplete_time_ms);
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker
NackList(bool * request_key_frame)187*d9f75844SAndroid Build Coastguard Worker std::vector<uint16_t> VCMReceiver::NackList(bool* request_key_frame) {
188*d9f75844SAndroid Build Coastguard Worker return jitter_buffer_.GetNackList(request_key_frame);
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker
191*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
192