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) {} |
52 | 53 |
53 std::unique_ptr<FrameObject> FrameBuffer::NextFrame(int64_t max_wait_time_ms) { | 54 std::unique_ptr<FrameObject> FrameBuffer::NextFrame(int64_t max_wait_time_ms) { |
54 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms; | 55 int64_t latest_return_time = clock_->TimeInMilliseconds() + max_wait_time_ms; |
55 int64_t now = clock_->TimeInMilliseconds(); | 56 int64_t now = clock_->TimeInMilliseconds(); |
56 int64_t wait_ms = max_wait_time_ms; | 57 int64_t wait_ms = max_wait_time_ms; |
57 while (true) { | 58 while (true) { |
58 std::map<FrameKey, std::unique_ptr<FrameObject>, FrameComp>::iterator | 59 std::map<FrameKey, std::unique_ptr<FrameObject>, FrameComp>::iterator |
59 next_frame; | 60 next_frame_it; |
60 { | 61 { |
61 rtc::CritScope lock(&crit_); | 62 rtc::CritScope lock(&crit_); |
62 frame_inserted_event_.Reset(); | 63 frame_inserted_event_.Reset(); |
63 if (stopped_) | 64 if (stopped_) |
64 return std::unique_ptr<FrameObject>(); | 65 return std::unique_ptr<FrameObject>(); |
65 | 66 |
66 now = clock_->TimeInMilliseconds(); | 67 now = clock_->TimeInMilliseconds(); |
67 wait_ms = max_wait_time_ms; | 68 wait_ms = max_wait_time_ms; |
68 next_frame = frames_.end(); | 69 next_frame_it = frames_.end(); |
69 for (auto frame_it = frames_.begin(); frame_it != frames_.end(); | 70 for (auto frame_it = frames_.begin(); frame_it != frames_.end(); |
70 ++frame_it) { | 71 ++frame_it) { |
71 const FrameObject& frame = *frame_it->second; | 72 const FrameObject& frame = *frame_it->second; |
72 if (IsContinuous(frame)) { | 73 if (IsContinuous(frame)) { |
73 next_frame = frame_it; | 74 next_frame_it = frame_it; |
74 int64_t render_time = timing_->RenderTimeMs(frame.timestamp, now); | 75 int64_t render_time = |
76 next_frame_it->second->RenderTime() == -1 | |
77 ? timing_->RenderTimeMs(frame.timestamp, now) | |
78 : next_frame_it->second->RenderTime(); | |
75 wait_ms = timing_->MaxWaitingTime(render_time, now); | 79 wait_ms = timing_->MaxWaitingTime(render_time, now); |
80 frame_it->second->SetRenderTime(render_time); | |
76 | 81 |
77 // This will cause the frame buffer to prefer high framerate rather | 82 // This will cause the frame buffer to prefer high framerate rather |
78 // than high resolution in the case of the decoder not decoding fast | 83 // than high resolution in the case of the decoder not decoding fast |
79 // enough and the stream has multiple spatial and temporal layers. | 84 // enough and the stream has multiple spatial and temporal layers. |
80 if (wait_ms == 0) | 85 if (wait_ms == 0) |
81 continue; | 86 continue; |
82 | 87 |
83 break; | 88 break; |
84 } | 89 } |
85 } | 90 } |
86 } | 91 } |
87 | 92 |
93 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now); | |
94 wait_ms = std::max<int64_t>(wait_ms, 0); | |
88 // If the timout occures, return. Otherwise a new frame has been inserted | 95 // If the timout occures, return. Otherwise a new frame has been inserted |
stefan-webrtc
2016/07/12 16:55:38
If the timeout occurs
philipel
2016/07/13 09:21:49
Done.
| |
89 // and the best frame to decode next will be selected again. | 96 // and the best frame to decode next will be selected again. |
90 wait_ms = std::min<int64_t>(wait_ms, latest_return_time - now); | |
91 wait_ms = std::max<int64_t>(wait_ms, 0); | |
92 if (!frame_inserted_event_.Wait(wait_ms)) { | 97 if (!frame_inserted_event_.Wait(wait_ms)) { |
93 rtc::CritScope lock(&crit_); | 98 rtc::CritScope lock(&crit_); |
94 if (next_frame != frames_.end()) { | 99 if (next_frame_it != frames_.end()) { |
95 // TODO(philipel): update jitter estimator with correct values. | 100 int64_t received_timestamp = next_frame_it->second->ReceivedTime(); |
96 jitter_estimator_->UpdateEstimate(100, 100); | 101 uint32_t timestamp = next_frame_it->second->Timestamp(); |
97 | 102 |
98 decoded_frames_.insert(next_frame->first); | 103 int64_t frame_delay; |
99 std::unique_ptr<FrameObject> frame = std::move(next_frame->second); | 104 if (inter_frame_delay_.CalculateDelay(timestamp, &frame_delay, |
100 frames_.erase(frames_.begin(), ++next_frame); | 105 received_timestamp)) { |
106 jitter_estimator_->UpdateEstimate(frame_delay, | |
107 next_frame_it->second->size); | |
108 } | |
109 timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(1.0)); | |
110 timing_->UpdateCurrentDelay(next_frame_it->second->RenderTime(), | |
111 clock_->TimeInMilliseconds()); | |
112 | |
113 decoded_frames_.insert(next_frame_it->first); | |
114 std::unique_ptr<FrameObject> frame = std::move(next_frame_it->second); | |
115 frames_.erase(frames_.begin(), ++next_frame_it); | |
101 return frame; | 116 return frame; |
stefan-webrtc
2016/07/12 16:55:39
Should we update the render time of this frame bef
philipel
2016/07/13 09:21:49
It could? If that's the case then it's going to be
stefan-webrtc
2016/07/14 12:17:30
It can since the inter arrival class might have up
philipel
2016/07/14 15:39:39
Yes and no. That part of the code only waits for a
| |
102 } else { | 117 } else { |
103 return std::unique_ptr<FrameObject>(); | 118 return std::unique_ptr<FrameObject>(); |
104 } | 119 } |
105 } | 120 } |
106 } | 121 } |
107 } | 122 } |
108 | 123 |
109 void FrameBuffer::Start() { | 124 void FrameBuffer::Start() { |
110 rtc::CritScope lock(&crit_); | 125 rtc::CritScope lock(&crit_); |
111 stopped_ = false; | 126 stopped_ = false; |
112 } | 127 } |
113 | 128 |
114 void FrameBuffer::Stop() { | 129 void FrameBuffer::Stop() { |
115 rtc::CritScope lock(&crit_); | 130 rtc::CritScope lock(&crit_); |
116 stopped_ = true; | 131 stopped_ = true; |
117 frame_inserted_event_.Set(); | 132 frame_inserted_event_.Set(); |
118 } | 133 } |
119 | 134 |
120 void FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { | 135 void FrameBuffer::InsertFrame(std::unique_ptr<FrameObject> frame) { |
121 rtc::CritScope lock(&crit_); | 136 rtc::CritScope lock(&crit_); |
122 if (newest_picture_id_ == -1) | 137 // If |newest_picture_id_ is -1 then this is the first frame we received. |
stefan-webrtc
2016/07/12 16:55:38
|newest_picture_id_|
philipel
2016/07/13 09:21:49
Done.
| |
138 if (newest_picture_id_ == -1) { | |
123 newest_picture_id_ = frame->picture_id; | 139 newest_picture_id_ = frame->picture_id; |
140 inter_frame_delay_.Reset(clock_->TimeInMilliseconds()); | |
141 } | |
124 | 142 |
125 if (AheadOf<uint16_t>(frame->picture_id, newest_picture_id_)) | 143 if (AheadOf<uint16_t>(frame->picture_id, newest_picture_id_)) |
126 newest_picture_id_ = frame->picture_id; | 144 newest_picture_id_ = frame->picture_id; |
127 | 145 |
128 // Remove frames as long as we have too many, |kMaxNumHistoryFrames|. | 146 // Remove frames as long as we have too many, |kMaxNumHistoryFrames|. |
129 while (decoded_frames_.size() > kMaxNumHistoryFrames) | 147 while (decoded_frames_.size() > kMaxNumHistoryFrames) |
130 decoded_frames_.erase(decoded_frames_.begin()); | 148 decoded_frames_.erase(decoded_frames_.begin()); |
131 | 149 |
132 // Remove frames that are too old, |kMaxNumHistoryFrames|. | 150 // Remove frames that are too old. |
133 uint16_t old_picture_id = Subtract<1 << 16>(newest_picture_id_, kMaxFrameAge); | 151 uint16_t old_picture_id = Subtract<1 << 16>(newest_picture_id_, kMaxFrameAge); |
134 auto old_decoded_it = | 152 auto old_decoded_it = |
135 decoded_frames_.lower_bound(FrameKey(old_picture_id, 0)); | 153 decoded_frames_.lower_bound(FrameKey(old_picture_id, 0)); |
136 decoded_frames_.erase(decoded_frames_.begin(), old_decoded_it); | 154 decoded_frames_.erase(decoded_frames_.begin(), old_decoded_it); |
137 | 155 |
138 FrameKey key(frame->picture_id, frame->spatial_layer); | 156 FrameKey key(frame->picture_id, frame->spatial_layer); |
139 frames_[key] = std::move(frame); | 157 frames_[key] = std::move(frame); |
140 frame_inserted_event_.Set(); | 158 frame_inserted_event_.Set(); |
141 } | 159 } |
142 | 160 |
(...skipping 19 matching lines...) Expand all Loading... | |
162 FrameKey ref_key(frame.picture_id, frame.spatial_layer - 1); | 180 FrameKey ref_key(frame.picture_id, frame.spatial_layer - 1); |
163 if (decoded_frames_.find(ref_key) == decoded_frames_.end()) | 181 if (decoded_frames_.find(ref_key) == decoded_frames_.end()) |
164 return false; | 182 return false; |
165 } | 183 } |
166 | 184 |
167 return true; | 185 return true; |
168 } | 186 } |
169 | 187 |
170 } // namespace video_coding | 188 } // namespace video_coding |
171 } // namespace webrtc | 189 } // namespace webrtc |
OLD | NEW |