Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: webrtc/modules/video_coding/frame_buffer2.cc

Issue 2668743002: Fix race condition in FrameBuffer2 (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/video_coding/frame_buffer2.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 stopped_(false), 47 stopped_(false),
48 protection_mode_(kProtectionNack) {} 48 protection_mode_(kProtectionNack) {}
49 49
50 FrameBuffer::~FrameBuffer() { 50 FrameBuffer::~FrameBuffer() {
51 UpdateHistograms(); 51 UpdateHistograms();
52 } 52 }
53 53
54 FrameBuffer::ReturnReason FrameBuffer::NextFrame( 54 FrameBuffer::ReturnReason FrameBuffer::NextFrame(
55 int64_t max_wait_time_ms, 55 int64_t max_wait_time_ms,
56 std::unique_ptr<FrameObject>* frame_out) { 56 std::unique_ptr<FrameObject>* frame_out) {
57 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms; 57 int64_t latest_return_time_ms =
58 clock_->TimeInMilliseconds() + max_wait_time_ms;
58 int64_t wait_ms = max_wait_time_ms; 59 int64_t wait_ms = max_wait_time_ms;
59 FrameMap::iterator next_frame_it;
60 60
61 do { 61 do {
62 int64_t now_ms = clock_->TimeInMilliseconds(); 62 int64_t now_ms = clock_->TimeInMilliseconds();
63 { 63 {
64 rtc::CritScope lock(&crit_); 64 rtc::CritScope lock(&crit_);
65 new_countinuous_frame_event_.Reset(); 65 new_countinuous_frame_event_.Reset();
66 if (stopped_) 66 if (stopped_)
67 return kStopped; 67 return kStopped;
68 68
69 wait_ms = max_wait_time_ms; 69 wait_ms = max_wait_time_ms;
70 70
71 // Need to hold |crit_| in order to use |frames_|, therefore we 71 // Need to hold |crit_| in order to use |frames_|, therefore we
72 // set it here in the loop instead of outside the loop in order to not 72 // set it here in the loop instead of outside the loop in order to not
73 // acquire the lock unnecesserily. 73 // acquire the lock unnecesserily.
74 next_frame_it = frames_.end(); 74 next_frame_it_ = frames_.end();
75 75
76 // |frame_it| points to the first frame after the 76 // |frame_it| points to the first frame after the
77 // |last_decoded_frame_it_|. 77 // |last_decoded_frame_it_|.
78 auto frame_it = frames_.end(); 78 auto frame_it = frames_.end();
79 if (last_decoded_frame_it_ == frames_.end()) { 79 if (last_decoded_frame_it_ == frames_.end()) {
80 frame_it = frames_.begin(); 80 frame_it = frames_.begin();
81 } else { 81 } else {
82 frame_it = last_decoded_frame_it_; 82 frame_it = last_decoded_frame_it_;
83 ++frame_it; 83 ++frame_it;
84 } 84 }
85 85
86 // |continuous_end_it| points to the first frame after the 86 // |continuous_end_it| points to the first frame after the
87 // |last_continuous_frame_it_|. 87 // |last_continuous_frame_it_|.
88 auto continuous_end_it = last_continuous_frame_it_; 88 auto continuous_end_it = last_continuous_frame_it_;
89 if (continuous_end_it != frames_.end()) 89 if (continuous_end_it != frames_.end())
90 ++continuous_end_it; 90 ++continuous_end_it;
91 91
92 for (; frame_it != continuous_end_it; ++frame_it) { 92 for (; frame_it != continuous_end_it; ++frame_it) {
93 if (!frame_it->second.continuous || 93 if (!frame_it->second.continuous ||
94 frame_it->second.num_missing_decodable > 0) { 94 frame_it->second.num_missing_decodable > 0) {
95 continue; 95 continue;
96 } 96 }
97 97
98 FrameObject* frame = frame_it->second.frame.get(); 98 FrameObject* frame = frame_it->second.frame.get();
99 next_frame_it = frame_it; 99 next_frame_it_ = frame_it;
100 if (frame->RenderTime() == -1) 100 if (frame->RenderTime() == -1)
101 frame->SetRenderTime(timing_->RenderTimeMs(frame->timestamp, now_ms)); 101 frame->SetRenderTime(timing_->RenderTimeMs(frame->timestamp, now_ms));
102 wait_ms = timing_->MaxWaitingTime(frame->RenderTime(), now_ms); 102 wait_ms = timing_->MaxWaitingTime(frame->RenderTime(), now_ms);
103 103
104 // This will cause the frame buffer to prefer high framerate rather 104 // This will cause the frame buffer to prefer high framerate rather
105 // than high resolution in the case of the decoder not decoding fast 105 // than high resolution in the case of the decoder not decoding fast
106 // enough and the stream has multiple spatial and temporal layers. 106 // enough and the stream has multiple spatial and temporal layers.
107 if (wait_ms == 0) 107 if (wait_ms == 0)
108 continue; 108 continue;
109 109
110 break; 110 break;
111 } 111 }
112 } // rtc::Critscope lock(&crit_); 112 } // rtc::Critscope lock(&crit_);
113 113
114 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now_ms); 114 wait_ms = std::min<int64_t>(wait_ms, latest_return_time_ms - now_ms);
115 wait_ms = std::max<int64_t>(wait_ms, 0); 115 wait_ms = std::max<int64_t>(wait_ms, 0);
116 } while (new_countinuous_frame_event_.Wait(wait_ms)); 116 } while (new_countinuous_frame_event_.Wait(wait_ms));
117 117
118 rtc::CritScope lock(&crit_); 118 rtc::CritScope lock(&crit_);
119 if (next_frame_it != frames_.end()) { 119 int64_t now_ms = clock_->TimeInMilliseconds();
120 std::unique_ptr<FrameObject> frame = std::move(next_frame_it->second.frame); 120 if (next_frame_it_ != frames_.end()) {
121 std::unique_ptr<FrameObject> frame =
122 std::move(next_frame_it_->second.frame);
121 123
122 if (!frame->delayed_by_retransmission()) { 124 if (!frame->delayed_by_retransmission()) {
123 int64_t frame_delay; 125 int64_t frame_delay;
124 126
125 if (inter_frame_delay_.CalculateDelay(frame->timestamp, &frame_delay, 127 if (inter_frame_delay_.CalculateDelay(frame->timestamp, &frame_delay,
126 frame->ReceivedTime())) { 128 frame->ReceivedTime())) {
127 jitter_estimator_->UpdateEstimate(frame_delay, frame->size()); 129 jitter_estimator_->UpdateEstimate(frame_delay, frame->size());
128 } 130 }
129 131
130 float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0; 132 float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
131 timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult)); 133 timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
132 timing_->UpdateCurrentDelay(frame->RenderTime(), 134 timing_->UpdateCurrentDelay(frame->RenderTime(), now_ms);
133 clock_->TimeInMilliseconds());
134 } 135 }
135 136
136 UpdateJitterDelay(); 137 UpdateJitterDelay();
137 138
138 PropagateDecodability(next_frame_it->second); 139 PropagateDecodability(next_frame_it_->second);
139 AdvanceLastDecodedFrame(next_frame_it); 140 AdvanceLastDecodedFrame(next_frame_it_);
140 last_decoded_frame_timestamp_ = frame->timestamp; 141 last_decoded_frame_timestamp_ = frame->timestamp;
141 *frame_out = std::move(frame); 142 *frame_out = std::move(frame);
142 return kFrameFound; 143 return kFrameFound;
144 } else if (latest_return_time_ms - now_ms > 0) {
145 // If |next_frame_it_ == frames_.end()| and there is still time left, it
146 // means that the frame buffer was cleared as the thread in this function
147 // was waiting to acquire |crit_| in order to return. Wait for the
148 // remaining time and then return.
149 return NextFrame(latest_return_time_ms - now_ms, frame_out);
143 } else { 150 } else {
144 return kTimeout; 151 return kTimeout;
145 } 152 }
146 } 153 }
147 154
148 void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) { 155 void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) {
149 rtc::CritScope lock(&crit_); 156 rtc::CritScope lock(&crit_);
150 protection_mode_ = mode; 157 protection_mode_ = mode;
151 } 158 }
152 159
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 if (accumulated_delay_samples_ > 0) { 410 if (accumulated_delay_samples_ > 0) {
404 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs", 411 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs",
405 accumulated_delay_ / accumulated_delay_samples_); 412 accumulated_delay_ / accumulated_delay_samples_);
406 } 413 }
407 } 414 }
408 415
409 void FrameBuffer::ClearFramesAndHistory() { 416 void FrameBuffer::ClearFramesAndHistory() {
410 frames_.clear(); 417 frames_.clear();
411 last_decoded_frame_it_ = frames_.end(); 418 last_decoded_frame_it_ = frames_.end();
412 last_continuous_frame_it_ = frames_.end(); 419 last_continuous_frame_it_ = frames_.end();
420 next_frame_it_ = frames_.end();
413 num_frames_history_ = 0; 421 num_frames_history_ = 0;
414 num_frames_buffered_ = 0; 422 num_frames_buffered_ = 0;
415 } 423 }
416 424
417 } // namespace video_coding 425 } // namespace video_coding
418 } // namespace webrtc 426 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/frame_buffer2.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698