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 |
(...skipping 24 matching lines...) Expand all Loading... | |
35 const FrameKey& f2) const { | 35 const FrameKey& f2) const { |
36 // first = picture id | 36 // first = picture id |
37 // second = spatial layer | 37 // second = spatial layer |
38 if (f1.first == f2.first) | 38 if (f1.first == f2.first) |
39 return f1.second < f2.second; | 39 return f1.second < f2.second; |
40 return AheadOf(f2.first, f1.first); | 40 return AheadOf(f2.first, f1.first); |
41 } | 41 } |
42 | 42 |
43 FrameBuffer::FrameBuffer(Clock* clock, | 43 FrameBuffer::FrameBuffer(Clock* clock, |
44 VCMJitterEstimator* jitter_estimator, | 44 VCMJitterEstimator* jitter_estimator, |
45 const VCMTiming* timing) | 45 VCMTiming* timing) |
46 : clock_(clock), | 46 : clock_(clock), |
47 frame_inserted_event_(false, false), | 47 frame_inserted_event_(false, false), |
48 jitter_estimator_(jitter_estimator), | 48 jitter_estimator_(jitter_estimator), |
49 timing_(timing), | 49 timing_(timing), |
50 inter_frame_delay_(clock_->TimeInMilliseconds()), | |
50 newest_picture_id_(-1), | 51 newest_picture_id_(-1), |
51 stopped_(false) {} | 52 stopped_(false), |
53 protection_mode_(kProtectionNack) {} | |
52 | 54 |
53 std::unique_ptr<FrameObject> FrameBuffer::NextFrame(int64_t max_wait_time_ms) { | 55 std::unique_ptr<FrameObject> FrameBuffer::NextFrame(int64_t max_wait_time_ms) { |
54 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms; | 56 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms; |
55 int64_t now = clock_->TimeInMilliseconds(); | 57 int64_t now = clock_->TimeInMilliseconds(); |
56 int64_t wait_ms = max_wait_time_ms; | 58 int64_t wait_ms = max_wait_time_ms; |
57 while (true) { | 59 while (true) { |
58 std::map<FrameKey, std::unique_ptr<FrameObject>, FrameComp>::iterator | 60 std::map<FrameKey, std::unique_ptr<FrameObject>, FrameComp>::iterator |
59 next_frame; | 61 next_frame_it; |
60 { | 62 { |
61 rtc::CritScope lock(&crit_); | 63 rtc::CritScope lock(&crit_); |
62 frame_inserted_event_.Reset(); | 64 frame_inserted_event_.Reset(); |
63 if (stopped_) | 65 if (stopped_) |
64 return std::unique_ptr<FrameObject>(); | 66 return std::unique_ptr<FrameObject>(); |
65 | 67 |
66 now = clock_->TimeInMilliseconds(); | 68 now = clock_->TimeInMilliseconds(); |
67 wait_ms = max_wait_time_ms; | 69 wait_ms = max_wait_time_ms; |
68 next_frame = frames_.end(); | 70 next_frame_it = frames_.end(); |
69 for (auto frame_it = frames_.begin(); frame_it != frames_.end(); | 71 for (auto frame_it = frames_.begin(); frame_it != frames_.end(); |
70 ++frame_it) { | 72 ++frame_it) { |
71 const FrameObject& frame = *frame_it->second; | 73 const FrameObject& frame = *frame_it->second; |
72 if (IsContinuous(frame)) { | 74 if (IsContinuous(frame)) { |
73 next_frame = frame_it; | 75 next_frame_it = frame_it; |
74 int64_t render_time = timing_->RenderTimeMs(frame.timestamp, now); | 76 int64_t render_time = |
77 next_frame_it->second->RenderTime() == -1 | |
78 ? timing_->RenderTimeMs(frame.timestamp, now) | |
79 : next_frame_it->second->RenderTime(); | |
75 wait_ms = timing_->MaxWaitingTime(render_time, now); | 80 wait_ms = timing_->MaxWaitingTime(render_time, now); |
81 frame_it->second->SetRenderTime(render_time); | |
76 | 82 |
77 // This will cause the frame buffer to prefer high framerate rather | 83 // This will cause the frame buffer to prefer high framerate rather |
78 // than high resolution in the case of the decoder not decoding fast | 84 // than high resolution in the case of the decoder not decoding fast |
79 // enough and the stream has multiple spatial and temporal layers. | 85 // enough and the stream has multiple spatial and temporal layers. |
80 if (wait_ms == 0) | 86 if (wait_ms == 0) |
81 continue; | 87 continue; |
82 | 88 |
83 break; | 89 break; |
84 } | 90 } |
85 } | 91 } |
86 } | 92 } |
87 | 93 |
88 // If the timout occures, return. Otherwise a new frame has been inserted | |
89 // and the best frame to decode next will be selected again. | |
90 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now); | 94 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now); |
91 wait_ms = std::max<int64_t>(wait_ms, 0); | 95 wait_ms = std::max<int64_t>(wait_ms, 0); |
96 // If the timeout occurs, return. Otherwise a new frame has been inserted | |
97 // and the best frame to decode next will be selected again. | |
92 if (!frame_inserted_event_.Wait(wait_ms)) { | 98 if (!frame_inserted_event_.Wait(wait_ms)) { |
93 rtc::CritScope lock(&crit_); | 99 rtc::CritScope lock(&crit_); |
94 if (next_frame != frames_.end()) { | 100 if (next_frame_it != frames_.end()) { |
95 // TODO(philipel): update jitter estimator with correct values. | 101 int64_t received_timestamp = next_frame_it->second->ReceivedTime(); |
96 jitter_estimator_->UpdateEstimate(100, 100); | 102 uint32_t timestamp = next_frame_it->second->Timestamp(); |
97 | 103 |
98 decoded_frames_.insert(next_frame->first); | 104 int64_t frame_delay; |
99 std::unique_ptr<FrameObject> frame = std::move(next_frame->second); | 105 if (inter_frame_delay_.CalculateDelay(timestamp, &frame_delay, |
100 frames_.erase(frames_.begin(), ++next_frame); | 106 received_timestamp)) { |
107 jitter_estimator_->UpdateEstimate(frame_delay, | |
108 next_frame_it->second->size); | |
109 } | |
110 float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0; | |
stefan-webrtc
2016/08/02 11:54:40
I think it'd be good to verify this with a unittes
philipel
2016/08/02 14:05:45
Done.
| |
111 timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult)); | |
112 timing_->UpdateCurrentDelay(next_frame_it->second->RenderTime(), | |
113 clock_->TimeInMilliseconds()); | |
114 | |
115 decoded_frames_.insert(next_frame_it->first); | |
116 std::unique_ptr<FrameObject> frame = std::move(next_frame_it->second); | |
117 frames_.erase(frames_.begin(), ++next_frame_it); | |
101 return frame; | 118 return frame; |
102 } else { | 119 } else { |
103 return std::unique_ptr<FrameObject>(); | 120 return std::unique_ptr<FrameObject>(); |
104 } | 121 } |
105 } | 122 } |
106 } | 123 } |
107 } | 124 } |
108 | 125 |
126 void FrameBuffer::SetProtectionMode(VCMVideoProtection mode) { | |
127 rtc::CritScope lock(&crit_); | |
128 protection_mode_ = mode; | |
129 } | |
130 | |
109 void FrameBuffer::Start() { | 131 void FrameBuffer::Start() { |
110 rtc::CritScope lock(&crit_); | 132 rtc::CritScope lock(&crit_); |
111 stopped_ = false; | 133 stopped_ = false; |
112 } | 134 } |
113 | 135 |
114 void FrameBuffer::Stop() { | 136 void FrameBuffer::Stop() { |
115 rtc::CritScope lock(&crit_); | 137 rtc::CritScope lock(&crit_); |
116 stopped_ = true; | 138 stopped_ = true; |
117 frame_inserted_event_.Set(); | 139 frame_inserted_event_.Set(); |
118 } | 140 } |
119 | 141 |
120 void FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { | 142 void FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { |
121 rtc::CritScope lock(&crit_); | 143 rtc::CritScope lock(&crit_); |
144 // If |newest_picture_id_| is -1 then this is the first frame we received. | |
122 if (newest_picture_id_ == -1) | 145 if (newest_picture_id_ == -1) |
123 newest_picture_id_ = frame->picture_id; | 146 newest_picture_id_ = frame->picture_id; |
124 | 147 |
125 if (AheadOf<uint16_t>(frame->picture_id, newest_picture_id_)) | 148 if (AheadOf<uint16_t>(frame->picture_id, newest_picture_id_)) |
126 newest_picture_id_ = frame->picture_id; | 149 newest_picture_id_ = frame->picture_id; |
127 | 150 |
128 // Remove frames as long as we have too many, |kMaxNumHistoryFrames|. | 151 // Remove frames as long as we have too many, |kMaxNumHistoryFrames|. |
129 while (decoded_frames_.size() > kMaxNumHistoryFrames) | 152 while (decoded_frames_.size() > kMaxNumHistoryFrames) |
130 decoded_frames_.erase(decoded_frames_.begin()); | 153 decoded_frames_.erase(decoded_frames_.begin()); |
131 | 154 |
132 // Remove frames that are too old, |kMaxNumHistoryFrames|. | 155 // Remove frames that are too old. |
133 uint16_t old_picture_id = Subtract<1 << 16>(newest_picture_id_, kMaxFrameAge); | 156 uint16_t old_picture_id = Subtract<1 << 16>(newest_picture_id_, kMaxFrameAge); |
134 auto old_decoded_it = | 157 auto old_decoded_it = |
135 decoded_frames_.lower_bound(FrameKey(old_picture_id, 0)); | 158 decoded_frames_.lower_bound(FrameKey(old_picture_id, 0)); |
136 decoded_frames_.erase(decoded_frames_.begin(), old_decoded_it); | 159 decoded_frames_.erase(decoded_frames_.begin(), old_decoded_it); |
137 | 160 |
138 FrameKey key(frame->picture_id, frame->spatial_layer); | 161 FrameKey key(frame->picture_id, frame->spatial_layer); |
139 frames_[key] = std::move(frame); | 162 frames_[key] = std::move(frame); |
140 frame_inserted_event_.Set(); | 163 frame_inserted_event_.Set(); |
141 } | 164 } |
142 | 165 |
(...skipping 19 matching lines...) Expand all Loading... | |
162 FrameKey ref_key(frame.picture_id, frame.spatial_layer - 1); | 185 FrameKey ref_key(frame.picture_id, frame.spatial_layer - 1); |
163 if (decoded_frames_.find(ref_key) == decoded_frames_.end()) | 186 if (decoded_frames_.find(ref_key) == decoded_frames_.end()) |
164 return false; | 187 return false; |
165 } | 188 } |
166 | 189 |
167 return true; | 190 return true; |
168 } | 191 } |
169 | 192 |
170 } // namespace video_coding | 193 } // namespace video_coding |
171 } // namespace webrtc | 194 } // namespace webrtc |
OLD | NEW |