Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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/frame_buffer2.h" | 11 #include "webrtc/modules/video_coding/frame_buffer2.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <cstring> | 14 #include <cstring> |
| 15 #include <queue> | 15 #include <queue> |
| 16 | 16 |
| 17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
| 19 #include "webrtc/base/trace_event.h" | |
| 19 #include "webrtc/modules/video_coding/include/video_coding_defines.h" | 20 #include "webrtc/modules/video_coding/include/video_coding_defines.h" |
| 20 #include "webrtc/modules/video_coding/jitter_estimator.h" | 21 #include "webrtc/modules/video_coding/jitter_estimator.h" |
| 21 #include "webrtc/modules/video_coding/timing.h" | 22 #include "webrtc/modules/video_coding/timing.h" |
| 22 #include "webrtc/system_wrappers/include/clock.h" | 23 #include "webrtc/system_wrappers/include/clock.h" |
| 23 #include "webrtc/system_wrappers/include/metrics.h" | 24 #include "webrtc/system_wrappers/include/metrics.h" |
| 24 | 25 |
| 25 namespace webrtc { | 26 namespace webrtc { |
| 26 namespace video_coding { | 27 namespace video_coding { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 48 num_frames_buffered_(0), | 49 num_frames_buffered_(0), |
| 49 stopped_(false), | 50 stopped_(false), |
| 50 protection_mode_(kProtectionNack), | 51 protection_mode_(kProtectionNack), |
| 51 stats_callback_(stats_callback) {} | 52 stats_callback_(stats_callback) {} |
| 52 | 53 |
| 53 FrameBuffer::~FrameBuffer() {} | 54 FrameBuffer::~FrameBuffer() {} |
| 54 | 55 |
| 55 FrameBuffer::ReturnReason FrameBuffer::NextFrame( | 56 FrameBuffer::ReturnReason FrameBuffer::NextFrame( |
| 56 int64_t max_wait_time_ms, | 57 int64_t max_wait_time_ms, |
| 57 std::unique_ptr<FrameObject>* frame_out) { | 58 std::unique_ptr<FrameObject>* frame_out) { |
| 59 TRACE_EVENT0("webrtc", "FrameBuffer::NextFrame"); | |
|
philipel
2017/03/03 12:08:34
If tracing is done in interest of profiling perfor
tommi
2017/03/03 13:07:58
Both wall clock time and cpu time are useful when
| |
| 58 int64_t latest_return_time_ms = | 60 int64_t latest_return_time_ms = |
| 59 clock_->TimeInMilliseconds() + max_wait_time_ms; | 61 clock_->TimeInMilliseconds() + max_wait_time_ms; |
| 60 int64_t wait_ms = max_wait_time_ms; | 62 int64_t wait_ms = max_wait_time_ms; |
| 61 | 63 |
| 62 do { | 64 do { |
| 63 int64_t now_ms = clock_->TimeInMilliseconds(); | 65 int64_t now_ms = clock_->TimeInMilliseconds(); |
| 64 { | 66 { |
| 65 rtc::CritScope lock(&crit_); | 67 rtc::CritScope lock(&crit_); |
| 66 new_countinuous_frame_event_.Reset(); | 68 new_countinuous_frame_event_.Reset(); |
| 67 if (stopped_) | 69 if (stopped_) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 // means that the frame buffer was cleared as the thread in this function | 149 // means that the frame buffer was cleared as the thread in this function |
| 148 // was waiting to acquire |crit_| in order to return. Wait for the | 150 // was waiting to acquire |crit_| in order to return. Wait for the |
| 149 // remaining time and then return. | 151 // remaining time and then return. |
| 150 return NextFrame(latest_return_time_ms - now_ms, frame_out); | 152 return NextFrame(latest_return_time_ms - now_ms, frame_out); |
| 151 } else { | 153 } else { |
| 152 return kTimeout; | 154 return kTimeout; |
| 153 } | 155 } |
| 154 } | 156 } |
| 155 | 157 |
| 156 void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) { | 158 void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) { |
| 159 TRACE_EVENT0("webrtc", "FrameBuffer::SetProtectionMode"); | |
| 157 rtc::CritScope lock(&crit_); | 160 rtc::CritScope lock(&crit_); |
| 158 protection_mode_ = mode; | 161 protection_mode_ = mode; |
| 159 } | 162 } |
| 160 | 163 |
| 161 void FrameBuffer::Start() { | 164 void FrameBuffer::Start() { |
| 165 TRACE_EVENT0("webrtc", "FrameBuffer::Start"); | |
| 162 rtc::CritScope lock(&crit_); | 166 rtc::CritScope lock(&crit_); |
| 163 stopped_ = false; | 167 stopped_ = false; |
| 164 } | 168 } |
| 165 | 169 |
| 166 void FrameBuffer::Stop() { | 170 void FrameBuffer::Stop() { |
| 171 TRACE_EVENT0("webrtc", "FrameBuffer::Stop"); | |
| 167 rtc::CritScope lock(&crit_); | 172 rtc::CritScope lock(&crit_); |
| 168 stopped_ = true; | 173 stopped_ = true; |
| 169 new_countinuous_frame_event_.Set(); | 174 new_countinuous_frame_event_.Set(); |
| 170 } | 175 } |
| 171 | 176 |
| 172 int FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { | 177 int FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { |
| 178 TRACE_EVENT0("webrtc", "FrameBuffer::InsertFrame"); | |
| 173 rtc::CritScope lock(&crit_); | 179 rtc::CritScope lock(&crit_); |
| 174 RTC_DCHECK(frame); | 180 RTC_DCHECK(frame); |
| 175 | 181 |
| 176 if (stats_callback_) | 182 if (stats_callback_) |
| 177 stats_callback_->OnCompleteFrame(frame->num_references == 0, frame->size()); | 183 stats_callback_->OnCompleteFrame(frame->num_references == 0, frame->size()); |
| 178 | 184 |
| 179 FrameKey key(frame->picture_id, frame->spatial_layer); | 185 FrameKey key(frame->picture_id, frame->spatial_layer); |
| 180 int last_continuous_picture_id = | 186 int last_continuous_picture_id = |
| 181 last_continuous_frame_it_ == frames_.end() | 187 last_continuous_frame_it_ == frames_.end() |
| 182 ? -1 | 188 ? -1 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 // Since we now have new continuous frames there might be a better frame | 251 // Since we now have new continuous frames there might be a better frame |
| 246 // to return from NextFrame. Signal that thread so that it again can choose | 252 // to return from NextFrame. Signal that thread so that it again can choose |
| 247 // which frame to return. | 253 // which frame to return. |
| 248 new_countinuous_frame_event_.Set(); | 254 new_countinuous_frame_event_.Set(); |
| 249 } | 255 } |
| 250 | 256 |
| 251 return last_continuous_picture_id; | 257 return last_continuous_picture_id; |
| 252 } | 258 } |
| 253 | 259 |
| 254 void FrameBuffer::PropagateContinuity(FrameMap::iterator start) { | 260 void FrameBuffer::PropagateContinuity(FrameMap::iterator start) { |
| 261 TRACE_EVENT0("webrtc", "FrameBuffer::PropagateContinuity"); | |
| 255 RTC_DCHECK(start->second.continuous); | 262 RTC_DCHECK(start->second.continuous); |
| 256 if (last_continuous_frame_it_ == frames_.end()) | 263 if (last_continuous_frame_it_ == frames_.end()) |
| 257 last_continuous_frame_it_ = start; | 264 last_continuous_frame_it_ = start; |
| 258 | 265 |
| 259 std::queue<FrameMap::iterator> continuous_frames; | 266 std::queue<FrameMap::iterator> continuous_frames; |
| 260 continuous_frames.push(start); | 267 continuous_frames.push(start); |
| 261 | 268 |
| 262 // A simple BFS to traverse continuous frames. | 269 // A simple BFS to traverse continuous frames. |
| 263 while (!continuous_frames.empty()) { | 270 while (!continuous_frames.empty()) { |
| 264 auto frame = continuous_frames.front(); | 271 auto frame = continuous_frames.front(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 275 | 282 |
| 276 if (frame_ref->second.num_missing_continuous == 0) { | 283 if (frame_ref->second.num_missing_continuous == 0) { |
| 277 frame_ref->second.continuous = true; | 284 frame_ref->second.continuous = true; |
| 278 continuous_frames.push(frame_ref); | 285 continuous_frames.push(frame_ref); |
| 279 } | 286 } |
| 280 } | 287 } |
| 281 } | 288 } |
| 282 } | 289 } |
| 283 | 290 |
| 284 void FrameBuffer::PropagateDecodability(const FrameInfo& info) { | 291 void FrameBuffer::PropagateDecodability(const FrameInfo& info) { |
| 292 TRACE_EVENT0("webrtc", "FrameBuffer::PropagateDecodability"); | |
| 285 for (size_t d = 0; d < info.num_dependent_frames; ++d) { | 293 for (size_t d = 0; d < info.num_dependent_frames; ++d) { |
| 286 auto ref_info = frames_.find(info.dependent_frames[d]); | 294 auto ref_info = frames_.find(info.dependent_frames[d]); |
| 287 RTC_DCHECK(ref_info != frames_.end()); | 295 RTC_DCHECK(ref_info != frames_.end()); |
| 288 RTC_DCHECK_GT(ref_info->second.num_missing_decodable, 0U); | 296 RTC_DCHECK_GT(ref_info->second.num_missing_decodable, 0U); |
| 289 --ref_info->second.num_missing_decodable; | 297 --ref_info->second.num_missing_decodable; |
| 290 } | 298 } |
| 291 } | 299 } |
| 292 | 300 |
| 293 void FrameBuffer::AdvanceLastDecodedFrame(FrameMap::iterator decoded) { | 301 void FrameBuffer::AdvanceLastDecodedFrame(FrameMap::iterator decoded) { |
| 302 TRACE_EVENT0("webrtc", "FrameBuffer::AdvanceLastDecodedFrame"); | |
| 294 if (last_decoded_frame_it_ == frames_.end()) { | 303 if (last_decoded_frame_it_ == frames_.end()) { |
| 295 last_decoded_frame_it_ = frames_.begin(); | 304 last_decoded_frame_it_ = frames_.begin(); |
| 296 } else { | 305 } else { |
| 297 RTC_DCHECK(last_decoded_frame_it_->first < decoded->first); | 306 RTC_DCHECK(last_decoded_frame_it_->first < decoded->first); |
| 298 ++last_decoded_frame_it_; | 307 ++last_decoded_frame_it_; |
| 299 } | 308 } |
| 300 --num_frames_buffered_; | 309 --num_frames_buffered_; |
| 301 ++num_frames_history_; | 310 ++num_frames_history_; |
| 302 | 311 |
| 303 // First, delete non-decoded frames from the history. | 312 // First, delete non-decoded frames from the history. |
| 304 while (last_decoded_frame_it_ != decoded) { | 313 while (last_decoded_frame_it_ != decoded) { |
| 305 if (last_decoded_frame_it_->second.frame) | 314 if (last_decoded_frame_it_->second.frame) |
| 306 --num_frames_buffered_; | 315 --num_frames_buffered_; |
| 307 last_decoded_frame_it_ = frames_.erase(last_decoded_frame_it_); | 316 last_decoded_frame_it_ = frames_.erase(last_decoded_frame_it_); |
| 308 } | 317 } |
| 309 | 318 |
| 310 // Then remove old history if we have too much history saved. | 319 // Then remove old history if we have too much history saved. |
| 311 if (num_frames_history_ > kMaxFramesHistory) { | 320 if (num_frames_history_ > kMaxFramesHistory) { |
| 312 frames_.erase(frames_.begin()); | 321 frames_.erase(frames_.begin()); |
| 313 --num_frames_history_; | 322 --num_frames_history_; |
| 314 } | 323 } |
| 315 } | 324 } |
| 316 | 325 |
| 317 bool FrameBuffer::UpdateFrameInfoWithIncomingFrame(const FrameObject& frame, | 326 bool FrameBuffer::UpdateFrameInfoWithIncomingFrame(const FrameObject& frame, |
| 318 FrameMap::iterator info) { | 327 FrameMap::iterator info) { |
| 328 TRACE_EVENT0("webrtc", "FrameBuffer::UpdateFrameInfoWithIncomingFrame"); | |
| 319 FrameKey key(frame.picture_id, frame.spatial_layer); | 329 FrameKey key(frame.picture_id, frame.spatial_layer); |
| 320 info->second.num_missing_continuous = frame.num_references; | 330 info->second.num_missing_continuous = frame.num_references; |
| 321 info->second.num_missing_decodable = frame.num_references; | 331 info->second.num_missing_decodable = frame.num_references; |
| 322 | 332 |
| 323 RTC_DCHECK(last_decoded_frame_it_ == frames_.end() || | 333 RTC_DCHECK(last_decoded_frame_it_ == frames_.end() || |
| 324 last_decoded_frame_it_->first < info->first); | 334 last_decoded_frame_it_->first < info->first); |
| 325 | 335 |
| 326 // Check how many dependencies that have already been fulfilled. | 336 // Check how many dependencies that have already been fulfilled. |
| 327 for (size_t i = 0; i < frame.num_references; ++i) { | 337 for (size_t i = 0; i < frame.num_references; ++i) { |
| 328 FrameKey ref_key(frame.references[i], frame.spatial_layer); | 338 FrameKey ref_key(frame.references[i], frame.spatial_layer); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 ref_info->second.num_missing_decodable); | 391 ref_info->second.num_missing_decodable); |
| 382 } | 392 } |
| 383 | 393 |
| 384 RTC_DCHECK_LE(info->second.num_missing_continuous, | 394 RTC_DCHECK_LE(info->second.num_missing_continuous, |
| 385 info->second.num_missing_decodable); | 395 info->second.num_missing_decodable); |
| 386 | 396 |
| 387 return true; | 397 return true; |
| 388 } | 398 } |
| 389 | 399 |
| 390 void FrameBuffer::UpdateJitterDelay() { | 400 void FrameBuffer::UpdateJitterDelay() { |
| 401 TRACE_EVENT0("webrtc", "FrameBuffer::UpdateJitterDelay"); | |
| 391 if (!stats_callback_) | 402 if (!stats_callback_) |
| 392 return; | 403 return; |
| 393 | 404 |
| 394 int decode_ms; | 405 int decode_ms; |
| 395 int max_decode_ms; | 406 int max_decode_ms; |
| 396 int current_delay_ms; | 407 int current_delay_ms; |
| 397 int target_delay_ms; | 408 int target_delay_ms; |
| 398 int jitter_buffer_ms; | 409 int jitter_buffer_ms; |
| 399 int min_playout_delay_ms; | 410 int min_playout_delay_ms; |
| 400 int render_delay_ms; | 411 int render_delay_ms; |
| 401 if (timing_->GetTimings(&decode_ms, &max_decode_ms, ¤t_delay_ms, | 412 if (timing_->GetTimings(&decode_ms, &max_decode_ms, ¤t_delay_ms, |
| 402 &target_delay_ms, &jitter_buffer_ms, | 413 &target_delay_ms, &jitter_buffer_ms, |
| 403 &min_playout_delay_ms, &render_delay_ms)) { | 414 &min_playout_delay_ms, &render_delay_ms)) { |
| 404 stats_callback_->OnFrameBufferTimingsUpdated( | 415 stats_callback_->OnFrameBufferTimingsUpdated( |
| 405 decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, | 416 decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, |
| 406 jitter_buffer_ms, min_playout_delay_ms, render_delay_ms); | 417 jitter_buffer_ms, min_playout_delay_ms, render_delay_ms); |
| 407 } | 418 } |
| 408 } | 419 } |
| 409 | 420 |
| 410 void FrameBuffer::ClearFramesAndHistory() { | 421 void FrameBuffer::ClearFramesAndHistory() { |
| 422 TRACE_EVENT0("webrtc", "FrameBuffer::UpdateJitterDelay"); | |
| 411 frames_.clear(); | 423 frames_.clear(); |
| 412 last_decoded_frame_it_ = frames_.end(); | 424 last_decoded_frame_it_ = frames_.end(); |
| 413 last_continuous_frame_it_ = frames_.end(); | 425 last_continuous_frame_it_ = frames_.end(); |
| 414 next_frame_it_ = frames_.end(); | 426 next_frame_it_ = frames_.end(); |
| 415 num_frames_history_ = 0; | 427 num_frames_history_ = 0; |
| 416 num_frames_buffered_ = 0; | 428 num_frames_buffered_ = 0; |
| 417 } | 429 } |
| 418 | 430 |
| 419 } // namespace video_coding | 431 } // namespace video_coding |
| 420 } // namespace webrtc | 432 } // namespace webrtc |
| OLD | NEW |