OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/receiver.h" | 11 #include "webrtc/modules/video_coding/receiver.h" |
12 | 12 |
13 #include <assert.h> | 13 #include <assert.h> |
14 | 14 |
15 #include <cstdlib> | 15 #include <cstdlib> |
16 #include <utility> | 16 #include <utility> |
| 17 #include <vector> |
17 | 18 |
18 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
19 #include "webrtc/base/trace_event.h" | 20 #include "webrtc/base/trace_event.h" |
20 #include "webrtc/modules/video_coding/encoded_frame.h" | 21 #include "webrtc/modules/video_coding/encoded_frame.h" |
21 #include "webrtc/modules/video_coding/internal_defines.h" | 22 #include "webrtc/modules/video_coding/internal_defines.h" |
22 #include "webrtc/modules/video_coding/media_opt_util.h" | 23 #include "webrtc/modules/video_coding/media_opt_util.h" |
23 #include "webrtc/system_wrappers/include/clock.h" | 24 #include "webrtc/system_wrappers/include/clock.h" |
24 | 25 |
25 namespace webrtc { | 26 namespace webrtc { |
26 | 27 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 void VCMReceiver::UpdateRtt(int64_t rtt) { | 66 void VCMReceiver::UpdateRtt(int64_t rtt) { |
66 jitter_buffer_.UpdateRtt(rtt); | 67 jitter_buffer_.UpdateRtt(rtt); |
67 } | 68 } |
68 | 69 |
69 int32_t VCMReceiver::InsertPacket(const VCMPacket& packet, | 70 int32_t VCMReceiver::InsertPacket(const VCMPacket& packet, |
70 uint16_t frame_width, | 71 uint16_t frame_width, |
71 uint16_t frame_height) { | 72 uint16_t frame_height) { |
72 // Insert the packet into the jitter buffer. The packet can either be empty or | 73 // Insert the packet into the jitter buffer. The packet can either be empty or |
73 // contain media at this point. | 74 // contain media at this point. |
74 bool retransmitted = false; | 75 bool retransmitted = false; |
75 const VCMFrameBufferEnum ret = jitter_buffer_.InsertPacket(packet, | 76 const VCMFrameBufferEnum ret = |
76 &retransmitted); | 77 jitter_buffer_.InsertPacket(packet, &retransmitted); |
77 if (ret == kOldPacket) { | 78 if (ret == kOldPacket) { |
78 return VCM_OK; | 79 return VCM_OK; |
79 } else if (ret == kFlushIndicator) { | 80 } else if (ret == kFlushIndicator) { |
80 return VCM_FLUSH_INDICATOR; | 81 return VCM_FLUSH_INDICATOR; |
81 } else if (ret < 0) { | 82 } else if (ret < 0) { |
82 return VCM_JITTER_BUFFER_ERROR; | 83 return VCM_JITTER_BUFFER_ERROR; |
83 } | 84 } |
84 if (ret == kCompleteSession && !retransmitted) { | 85 if (ret == kCompleteSession && !retransmitted) { |
85 // We don't want to include timestamps which have suffered from | 86 // We don't want to include timestamps which have suffered from |
86 // retransmission here, since we compensate with extra retransmission | 87 // retransmission here, since we compensate with extra retransmission |
87 // delay within the jitter estimate. | 88 // delay within the jitter estimate. |
88 timing_->IncomingTimestamp(packet.timestamp, clock_->TimeInMilliseconds()); | 89 timing_->IncomingTimestamp(packet.timestamp, clock_->TimeInMilliseconds()); |
89 } | 90 } |
90 return VCM_OK; | 91 return VCM_OK; |
91 } | 92 } |
92 | 93 |
93 void VCMReceiver::TriggerDecoderShutdown() { | 94 void VCMReceiver::TriggerDecoderShutdown() { |
94 jitter_buffer_.Stop(); | 95 jitter_buffer_.Stop(); |
95 render_wait_event_->Set(); | 96 render_wait_event_->Set(); |
96 } | 97 } |
97 | 98 |
98 VCMEncodedFrame* VCMReceiver::FrameForDecoding(uint16_t max_wait_time_ms, | 99 VCMEncodedFrame* VCMReceiver::FrameForDecoding(uint16_t max_wait_time_ms, |
99 int64_t& next_render_time_ms, | 100 int64_t* next_render_time_ms, |
100 bool prefer_late_decoding) { | 101 bool prefer_late_decoding) { |
101 const int64_t start_time_ms = clock_->TimeInMilliseconds(); | 102 const int64_t start_time_ms = clock_->TimeInMilliseconds(); |
102 uint32_t frame_timestamp = 0; | 103 uint32_t frame_timestamp = 0; |
103 // Exhaust wait time to get a complete frame for decoding. | 104 // Exhaust wait time to get a complete frame for decoding. |
104 bool found_frame = jitter_buffer_.NextCompleteTimestamp( | 105 bool found_frame = |
105 max_wait_time_ms, &frame_timestamp); | 106 jitter_buffer_.NextCompleteTimestamp(max_wait_time_ms, &frame_timestamp); |
106 | 107 |
107 if (!found_frame) | 108 if (!found_frame) |
108 found_frame = jitter_buffer_.NextMaybeIncompleteTimestamp(&frame_timestamp); | 109 found_frame = jitter_buffer_.NextMaybeIncompleteTimestamp(&frame_timestamp); |
109 | 110 |
110 if (!found_frame) | 111 if (!found_frame) |
111 return NULL; | 112 return NULL; |
112 | 113 |
113 // We have a frame - Set timing and render timestamp. | 114 // We have a frame - Set timing and render timestamp. |
114 timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs()); | 115 timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs()); |
115 const int64_t now_ms = clock_->TimeInMilliseconds(); | 116 const int64_t now_ms = clock_->TimeInMilliseconds(); |
116 timing_->UpdateCurrentDelay(frame_timestamp); | 117 timing_->UpdateCurrentDelay(frame_timestamp); |
117 next_render_time_ms = timing_->RenderTimeMs(frame_timestamp, now_ms); | 118 *next_render_time_ms = timing_->RenderTimeMs(frame_timestamp, now_ms); |
118 // Check render timing. | 119 // Check render timing. |
119 bool timing_error = false; | 120 bool timing_error = false; |
120 // Assume that render timing errors are due to changes in the video stream. | 121 // Assume that render timing errors are due to changes in the video stream. |
121 if (next_render_time_ms < 0) { | 122 if (*next_render_time_ms < 0) { |
122 timing_error = true; | 123 timing_error = true; |
123 } else if (std::abs(next_render_time_ms - now_ms) > max_video_delay_ms_) { | 124 } else if (std::abs(*next_render_time_ms - now_ms) > max_video_delay_ms_) { |
124 int frame_delay = static_cast<int>(std::abs(next_render_time_ms - now_ms)); | 125 int frame_delay = static_cast<int>(std::abs(*next_render_time_ms - now_ms)); |
125 LOG(LS_WARNING) << "A frame about to be decoded is out of the configured " | 126 LOG(LS_WARNING) << "A frame about to be decoded is out of the configured " |
126 << "delay bounds (" << frame_delay << " > " | 127 << "delay bounds (" << frame_delay << " > " |
127 << max_video_delay_ms_ | 128 << max_video_delay_ms_ |
128 << "). Resetting the video jitter buffer."; | 129 << "). Resetting the video jitter buffer."; |
129 timing_error = true; | 130 timing_error = true; |
130 } else if (static_cast<int>(timing_->TargetVideoDelay()) > | 131 } else if (static_cast<int>(timing_->TargetVideoDelay()) > |
131 max_video_delay_ms_) { | 132 max_video_delay_ms_) { |
132 LOG(LS_WARNING) << "The video target delay has grown larger than " | 133 LOG(LS_WARNING) << "The video target delay has grown larger than " |
133 << max_video_delay_ms_ << " ms. Resetting jitter buffer."; | 134 << max_video_delay_ms_ << " ms. Resetting jitter buffer."; |
134 timing_error = true; | 135 timing_error = true; |
135 } | 136 } |
136 | 137 |
137 if (timing_error) { | 138 if (timing_error) { |
138 // Timing error => reset timing and flush the jitter buffer. | 139 // Timing error => reset timing and flush the jitter buffer. |
139 jitter_buffer_.Flush(); | 140 jitter_buffer_.Flush(); |
140 timing_->Reset(); | 141 timing_->Reset(); |
141 return NULL; | 142 return NULL; |
142 } | 143 } |
143 | 144 |
144 if (prefer_late_decoding) { | 145 if (prefer_late_decoding) { |
145 // Decode frame as close as possible to the render timestamp. | 146 // Decode frame as close as possible to the render timestamp. |
146 const int32_t available_wait_time = max_wait_time_ms - | 147 const int32_t available_wait_time = |
| 148 max_wait_time_ms - |
147 static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms); | 149 static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms); |
148 uint16_t new_max_wait_time = static_cast<uint16_t>( | 150 uint16_t new_max_wait_time = |
149 VCM_MAX(available_wait_time, 0)); | 151 static_cast<uint16_t>(VCM_MAX(available_wait_time, 0)); |
150 uint32_t wait_time_ms = timing_->MaxWaitingTime( | 152 uint32_t wait_time_ms = timing_->MaxWaitingTime( |
151 next_render_time_ms, clock_->TimeInMilliseconds()); | 153 *next_render_time_ms, clock_->TimeInMilliseconds()); |
152 if (new_max_wait_time < wait_time_ms) { | 154 if (new_max_wait_time < wait_time_ms) { |
153 // We're not allowed to wait until the frame is supposed to be rendered, | 155 // We're not allowed to wait until the frame is supposed to be rendered, |
154 // waiting as long as we're allowed to avoid busy looping, and then return | 156 // waiting as long as we're allowed to avoid busy looping, and then return |
155 // NULL. Next call to this function might return the frame. | 157 // NULL. Next call to this function might return the frame. |
156 render_wait_event_->Wait(new_max_wait_time); | 158 render_wait_event_->Wait(new_max_wait_time); |
157 return NULL; | 159 return NULL; |
158 } | 160 } |
159 // Wait until it's time to render. | 161 // Wait until it's time to render. |
160 render_wait_event_->Wait(wait_time_ms); | 162 render_wait_event_->Wait(wait_time_ms); |
161 } | 163 } |
162 | 164 |
163 // Extract the frame from the jitter buffer and set the render time. | 165 // Extract the frame from the jitter buffer and set the render time. |
164 VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp); | 166 VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp); |
165 if (frame == NULL) { | 167 if (frame == NULL) { |
166 return NULL; | 168 return NULL; |
167 } | 169 } |
168 frame->SetRenderTime(next_render_time_ms); | 170 frame->SetRenderTime(*next_render_time_ms); |
169 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame->TimeStamp(), | 171 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame->TimeStamp(), "SetRenderTS", |
170 "SetRenderTS", "render_time", next_render_time_ms); | 172 "render_time", *next_render_time_ms); |
171 if (!frame->Complete()) { | 173 if (!frame->Complete()) { |
172 // Update stats for incomplete frames. | 174 // Update stats for incomplete frames. |
173 bool retransmitted = false; | 175 bool retransmitted = false; |
174 const int64_t last_packet_time_ms = | 176 const int64_t last_packet_time_ms = |
175 jitter_buffer_.LastPacketTime(frame, &retransmitted); | 177 jitter_buffer_.LastPacketTime(frame, &retransmitted); |
176 if (last_packet_time_ms >= 0 && !retransmitted) { | 178 if (last_packet_time_ms >= 0 && !retransmitted) { |
177 // We don't want to include timestamps which have suffered from | 179 // We don't want to include timestamps which have suffered from |
178 // retransmission here, since we compensate with extra retransmission | 180 // retransmission here, since we compensate with extra retransmission |
179 // delay within the jitter estimate. | 181 // delay within the jitter estimate. |
180 timing_->IncomingTimestamp(frame_timestamp, last_packet_time_ms); | 182 timing_->IncomingTimestamp(frame_timestamp, last_packet_time_ms); |
181 } | 183 } |
182 } | 184 } |
183 return frame; | 185 return frame; |
184 } | 186 } |
185 | 187 |
186 void VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame) { | 188 void VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame) { |
187 jitter_buffer_.ReleaseFrame(frame); | 189 jitter_buffer_.ReleaseFrame(frame); |
188 } | 190 } |
189 | 191 |
190 void VCMReceiver::ReceiveStatistics(uint32_t* bitrate, | 192 void VCMReceiver::ReceiveStatistics(uint32_t* bitrate, uint32_t* framerate) { |
191 uint32_t* framerate) { | |
192 assert(bitrate); | 193 assert(bitrate); |
193 assert(framerate); | 194 assert(framerate); |
194 jitter_buffer_.IncomingRateStatistics(framerate, bitrate); | 195 jitter_buffer_.IncomingRateStatistics(framerate, bitrate); |
195 } | 196 } |
196 | 197 |
197 uint32_t VCMReceiver::DiscardedPackets() const { | 198 uint32_t VCMReceiver::DiscardedPackets() const { |
198 return jitter_buffer_.num_discarded_packets(); | 199 return jitter_buffer_.num_discarded_packets(); |
199 } | 200 } |
200 | 201 |
201 void VCMReceiver::SetNackMode(VCMNackMode nackMode, | 202 void VCMReceiver::SetNackMode(VCMNackMode nackMode, |
202 int64_t low_rtt_nack_threshold_ms, | 203 int64_t low_rtt_nack_threshold_ms, |
203 int64_t high_rtt_nack_threshold_ms) { | 204 int64_t high_rtt_nack_threshold_ms) { |
204 CriticalSectionScoped cs(crit_sect_); | 205 CriticalSectionScoped cs(crit_sect_); |
205 // Default to always having NACK enabled in hybrid mode. | 206 // Default to always having NACK enabled in hybrid mode. |
206 jitter_buffer_.SetNackMode(nackMode, low_rtt_nack_threshold_ms, | 207 jitter_buffer_.SetNackMode(nackMode, low_rtt_nack_threshold_ms, |
207 high_rtt_nack_threshold_ms); | 208 high_rtt_nack_threshold_ms); |
208 } | 209 } |
209 | 210 |
210 void VCMReceiver::SetNackSettings(size_t max_nack_list_size, | 211 void VCMReceiver::SetNackSettings(size_t max_nack_list_size, |
211 int max_packet_age_to_nack, | 212 int max_packet_age_to_nack, |
212 int max_incomplete_time_ms) { | 213 int max_incomplete_time_ms) { |
213 jitter_buffer_.SetNackSettings(max_nack_list_size, | 214 jitter_buffer_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, |
214 max_packet_age_to_nack, | |
215 max_incomplete_time_ms); | 215 max_incomplete_time_ms); |
216 } | 216 } |
217 | 217 |
218 VCMNackMode VCMReceiver::NackMode() const { | 218 VCMNackMode VCMReceiver::NackMode() const { |
219 CriticalSectionScoped cs(crit_sect_); | 219 CriticalSectionScoped cs(crit_sect_); |
220 return jitter_buffer_.nack_mode(); | 220 return jitter_buffer_.nack_mode(); |
221 } | 221 } |
222 | 222 |
223 std::vector<uint16_t> VCMReceiver::NackList(bool* request_key_frame) { | 223 std::vector<uint16_t> VCMReceiver::NackList(bool* request_key_frame) { |
224 return jitter_buffer_.GetNackList(request_key_frame); | 224 return jitter_buffer_.GetNackList(request_key_frame); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 uint32_t render_end = timing_->RenderTimeMs(timestamp_end, now_ms); | 260 uint32_t render_end = timing_->RenderTimeMs(timestamp_end, now_ms); |
261 return render_end - render_start; | 261 return render_end - render_start; |
262 } | 262 } |
263 | 263 |
264 void VCMReceiver::RegisterStatsCallback( | 264 void VCMReceiver::RegisterStatsCallback( |
265 VCMReceiveStatisticsCallback* callback) { | 265 VCMReceiveStatisticsCallback* callback) { |
266 jitter_buffer_.RegisterStatsCallback(callback); | 266 jitter_buffer_.RegisterStatsCallback(callback); |
267 } | 267 } |
268 | 268 |
269 } // namespace webrtc | 269 } // namespace webrtc |
OLD | NEW |