| 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 |