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/packet_buffer.h" | 11 #include "webrtc/modules/video_coding/packet_buffer.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <limits> | 14 #include <limits> |
15 | 15 |
16 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
17 #include "webrtc/modules/video_coding/frame_object.h" | 17 #include "webrtc/modules/video_coding/frame_object.h" |
18 #include "webrtc/modules/video_coding/sequence_number_util.h" | |
19 | 18 |
20 namespace webrtc { | 19 namespace webrtc { |
21 namespace video_coding { | 20 namespace video_coding { |
22 | 21 |
23 PacketBuffer::PacketBuffer(size_t start_buffer_size, | 22 PacketBuffer::PacketBuffer(size_t start_buffer_size, |
24 size_t max_buffer_size, | 23 size_t max_buffer_size, |
25 OnCompleteFrameCallback* frame_callback) | 24 OnCompleteFrameCallback* frame_callback) |
26 : size_(start_buffer_size), | 25 : size_(start_buffer_size), |
27 max_size_(max_buffer_size), | 26 max_size_(max_buffer_size), |
27 first_seq_num_(0), | |
28 last_seq_num_(0), | 28 last_seq_num_(0), |
29 first_seq_num_(0), | 29 first_packet_received_(false), |
30 initialized_(false), | |
31 data_buffer_(start_buffer_size), | 30 data_buffer_(start_buffer_size), |
32 sequence_buffer_(start_buffer_size), | 31 sequence_buffer_(start_buffer_size), |
33 frame_callback_(frame_callback) { | 32 frame_callback_(frame_callback), |
33 last_picture_id_(-1), | |
34 last_unwrap_(-1) { | |
34 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); | 35 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); |
35 // Buffer size must always be a power of 2. | 36 // Buffer size must always be a power of 2. |
36 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); | 37 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); |
37 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); | 38 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); |
38 } | 39 } |
39 | 40 |
40 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { | 41 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { |
41 rtc::CritScope lock(&crit_); | 42 rtc::CritScope lock(&crit_); |
42 uint16_t seq_num = packet.seqNum; | 43 uint16_t seq_num = packet.seqNum; |
43 int index = seq_num % size_; | 44 size_t index = seq_num % size_; |
44 | 45 |
45 if (!initialized_) { | 46 if (!first_packet_received_) { |
46 first_seq_num_ = seq_num - 1; | 47 first_seq_num_ = seq_num - 1; |
47 last_seq_num_ = seq_num; | 48 last_seq_num_ = seq_num; |
48 initialized_ = true; | 49 first_packet_received_ = true; |
49 } | 50 } |
50 | 51 |
51 if (sequence_buffer_[index].used) { | 52 if (sequence_buffer_[index].used) { |
52 // Duplicate packet, do nothing. | 53 // Duplicate packet, do nothing. |
53 if (data_buffer_[index].seqNum == packet.seqNum) | 54 if (data_buffer_[index].seqNum == packet.seqNum) |
54 return true; | 55 return true; |
55 | 56 |
56 // The packet buffer is full, try to expand the buffer. | 57 // The packet buffer is full, try to expand the buffer. |
57 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) { | 58 while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) { |
58 } | 59 } |
59 index = seq_num % size_; | 60 index = seq_num % size_; |
60 | 61 |
61 // Packet buffer is still full. | 62 // Packet buffer is still full. |
62 if (sequence_buffer_[index].used) | 63 if (sequence_buffer_[index].used) |
63 return false; | 64 return false; |
64 } | 65 } |
65 | 66 |
66 if (AheadOf(seq_num, last_seq_num_)) | 67 if (AheadOf(seq_num, last_seq_num_)) |
67 last_seq_num_ = seq_num; | 68 last_seq_num_ = seq_num; |
68 | 69 |
69 sequence_buffer_[index].frame_begin = packet.isFirstPacket; | 70 sequence_buffer_[index].frame_begin = packet.isFirstPacket; |
70 sequence_buffer_[index].frame_end = packet.markerBit; | 71 sequence_buffer_[index].frame_end = packet.markerBit; |
71 sequence_buffer_[index].seq_num = packet.seqNum; | 72 sequence_buffer_[index].seq_num = packet.seqNum; |
72 sequence_buffer_[index].continuous = false; | 73 sequence_buffer_[index].continuous = false; |
74 sequence_buffer_[index].frame_created = false; | |
73 sequence_buffer_[index].used = true; | 75 sequence_buffer_[index].used = true; |
74 data_buffer_[index] = packet; | 76 data_buffer_[index] = packet; |
75 | 77 |
76 FindCompleteFrames(seq_num); | 78 FindFrames(seq_num); |
77 return true; | 79 return true; |
78 } | 80 } |
79 | 81 |
80 void PacketBuffer::ClearTo(uint16_t seq_num) { | 82 void PacketBuffer::ClearTo(uint16_t seq_num) { |
81 rtc::CritScope lock(&crit_); | 83 rtc::CritScope lock(&crit_); |
82 int index = first_seq_num_ % size_; | 84 size_t index = first_seq_num_ % size_; |
83 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) { | 85 while (AheadOf<uint16_t>(seq_num, first_seq_num_ + 1)) { |
84 index = (index + 1) % size_; | 86 index = (index + 1) % size_; |
85 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1); | 87 first_seq_num_ = Add<1 << 16>(first_seq_num_, 1); |
86 sequence_buffer_[index].used = false; | 88 sequence_buffer_[index].used = false; |
87 } | 89 } |
88 } | 90 } |
89 | 91 |
90 bool PacketBuffer::ExpandBufferSize() { | 92 bool PacketBuffer::ExpandBufferSize() { |
91 if (size_ == max_size_) | 93 if (size_ == max_size_) |
92 return false; | 94 return false; |
93 | 95 |
94 size_t new_size = std::min(max_size_, 2 * size_); | 96 size_t new_size = std::min(max_size_, 2 * size_); |
95 std::vector<VCMPacket> new_data_buffer(new_size); | 97 std::vector<VCMPacket> new_data_buffer(new_size); |
96 std::vector<ContinuityInfo> new_sequence_buffer(new_size); | 98 std::vector<ContinuityInfo> new_sequence_buffer(new_size); |
97 for (size_t i = 0; i < size_; ++i) { | 99 for (size_t i = 0; i < size_; ++i) { |
98 if (sequence_buffer_[i].used) { | 100 if (sequence_buffer_[i].used) { |
99 int index = sequence_buffer_[i].seq_num % new_size; | 101 size_t index = sequence_buffer_[i].seq_num % new_size; |
100 new_sequence_buffer[index] = sequence_buffer_[i]; | 102 new_sequence_buffer[index] = sequence_buffer_[i]; |
101 new_data_buffer[index] = data_buffer_[i]; | 103 new_data_buffer[index] = data_buffer_[i]; |
102 } | 104 } |
103 } | 105 } |
104 size_ = new_size; | 106 size_ = new_size; |
105 sequence_buffer_ = std::move(new_sequence_buffer); | 107 sequence_buffer_ = std::move(new_sequence_buffer); |
106 data_buffer_ = std::move(new_data_buffer); | 108 data_buffer_ = std::move(new_data_buffer); |
107 return true; | 109 return true; |
108 } | 110 } |
109 | 111 |
110 bool PacketBuffer::IsContinuous(uint16_t seq_num) const { | 112 bool PacketBuffer::IsContinuous(uint16_t seq_num) const { |
111 int index = seq_num % size_; | 113 size_t index = seq_num % size_; |
112 int prev_index = index > 0 ? index - 1 : size_ - 1; | 114 int prev_index = index > 0 ? index - 1 : size_ - 1; |
115 | |
113 if (!sequence_buffer_[index].used) | 116 if (!sequence_buffer_[index].used) |
114 return false; | 117 return false; |
118 if (sequence_buffer_[index].frame_created) | |
119 return false; | |
115 if (sequence_buffer_[index].frame_begin) | 120 if (sequence_buffer_[index].frame_begin) |
116 return true; | 121 return true; |
117 if (!sequence_buffer_[prev_index].used) | 122 if (!sequence_buffer_[prev_index].used) |
118 return false; | 123 return false; |
124 if (sequence_buffer_[prev_index].seq_num != | |
125 static_cast<uint16_t>(seq_num - 1)) | |
126 return false; | |
119 if (sequence_buffer_[prev_index].continuous) | 127 if (sequence_buffer_[prev_index].continuous) |
120 return true; | 128 return true; |
121 | 129 |
122 return false; | 130 return false; |
123 } | 131 } |
124 | 132 |
125 void PacketBuffer::FindCompleteFrames(uint16_t seq_num) { | 133 void PacketBuffer::FindFrames(uint16_t seq_num) { |
126 int index = seq_num % size_; | 134 size_t index = seq_num % size_; |
127 while (IsContinuous(seq_num)) { | 135 while (IsContinuous(seq_num)) { |
128 sequence_buffer_[index].continuous = true; | 136 sequence_buffer_[index].continuous = true; |
129 | 137 |
130 // If the frame is complete, find the first packet of the frame and | 138 // If all packets of the frame is continuous, find the first packet of the |
131 // create a FrameObject. | 139 // frame and create an RtpFrameObject. |
132 if (sequence_buffer_[index].frame_end) { | 140 if (sequence_buffer_[index].frame_end) { |
133 int rindex = index; | 141 int start_index = index; |
134 uint16_t start_seq_num = seq_num; | 142 uint16_t start_seq_num = seq_num; |
135 while (!sequence_buffer_[rindex].frame_begin) { | 143 |
136 rindex = rindex > 0 ? rindex - 1 : size_ - 1; | 144 while (!sequence_buffer_[start_index].frame_begin) { |
145 sequence_buffer_[start_index].frame_created = true; | |
146 start_index = start_index > 0 ? start_index - 1 : size_ - 1; | |
137 start_seq_num--; | 147 start_seq_num--; |
138 } | 148 } |
149 sequence_buffer_[start_index].frame_created = true; | |
139 | 150 |
140 std::unique_ptr<FrameObject> frame( | 151 std::unique_ptr<RtpFrameObject> frame( |
141 new RtpFrameObject(this, 1, start_seq_num, seq_num)); | 152 new RtpFrameObject(this, start_seq_num, seq_num)); |
142 frame_callback_->OnCompleteFrame(std::move(frame)); | 153 ManageFrame(std::move(frame)); |
143 } | 154 } |
144 | 155 |
145 index = (index + 1) % size_; | 156 index = (index + 1) % size_; |
146 ++seq_num; | 157 ++seq_num; |
147 } | 158 } |
148 } | 159 } |
149 | 160 |
150 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { | 161 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { |
151 rtc::CritScope lock(&crit_); | 162 rtc::CritScope lock(&crit_); |
152 int index = frame->first_packet() % size_; | 163 size_t index = frame->first_packet() % size_; |
153 int end = (frame->last_packet() + 1) % size_; | 164 size_t end = (frame->last_packet() + 1) % size_; |
154 uint16_t seq_num = frame->first_packet(); | 165 uint16_t seq_num = frame->first_packet(); |
155 while (index != end) { | 166 while (index != end) { |
156 if (sequence_buffer_[index].seq_num == seq_num) { | 167 if (sequence_buffer_[index].seq_num == seq_num) |
157 sequence_buffer_[index].used = false; | 168 sequence_buffer_[index].used = false; |
158 sequence_buffer_[index].continuous = false; | 169 |
159 } | |
160 index = (index + 1) % size_; | 170 index = (index + 1) % size_; |
161 ++seq_num; | 171 ++seq_num; |
162 } | 172 } |
163 | 173 |
164 index = first_seq_num_ % size_; | 174 index = first_seq_num_ % size_; |
165 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) && | 175 while (AheadOf<uint16_t>(last_seq_num_, first_seq_num_) && |
166 !sequence_buffer_[index].used) { | 176 !sequence_buffer_[index].used) { |
167 ++first_seq_num_; | 177 ++first_seq_num_; |
168 index = (index + 1) % size_; | 178 index = (index + 1) % size_; |
169 } | 179 } |
170 } | 180 } |
171 | 181 |
172 bool PacketBuffer::GetBitstream(const RtpFrameObject& frame, | 182 bool PacketBuffer::GetBitstream(const RtpFrameObject& frame, |
173 uint8_t* destination) { | 183 uint8_t* destination) { |
174 rtc::CritScope lock(&crit_); | 184 rtc::CritScope lock(&crit_); |
175 | 185 |
176 int index = frame.first_packet() % size_; | 186 size_t index = frame.first_packet() % size_; |
177 int end = (frame.last_packet() + 1) % size_; | 187 size_t end = (frame.last_packet() + 1) % size_; |
178 uint16_t seq_num = frame.first_packet(); | 188 uint16_t seq_num = frame.first_packet(); |
179 while (index != end) { | 189 while (index != end) { |
180 if (!sequence_buffer_[index].used || | 190 if (!sequence_buffer_[index].used || |
181 sequence_buffer_[index].seq_num != seq_num) { | 191 sequence_buffer_[index].seq_num != seq_num) { |
182 return false; | 192 return false; |
183 } | 193 } |
184 | 194 |
185 const uint8_t* source = data_buffer_[index].dataPtr; | 195 const uint8_t* source = data_buffer_[index].dataPtr; |
186 size_t length = data_buffer_[index].sizeBytes; | 196 size_t length = data_buffer_[index].sizeBytes; |
187 memcpy(destination, source, length); | 197 memcpy(destination, source, length); |
188 destination += length; | 198 destination += length; |
189 index = (index + 1) % size_; | 199 index = (index + 1) % size_; |
190 ++seq_num; | 200 ++seq_num; |
191 } | 201 } |
192 return true; | 202 return true; |
193 } | 203 } |
194 | 204 |
205 void PacketBuffer::ManageFrame(std::unique_ptr<RtpFrameObject> frame) { | |
206 size_t start_index = frame->first_packet() % size_; | |
207 VideoCodecType codec_type = data_buffer_[start_index].codec; | |
208 | |
209 if (codec_type == kVideoCodecVP8) { | |
stefan-webrtc
2016/04/07 12:37:04
switch()
philipel
2016/04/07 13:38:42
If I implement a switch case I am forced by the co
stefan-webrtc
2016/04/19 10:38:19
I think that could be a good thing. If a new type
philipel
2016/04/19 11:52:07
Switched to switch case.
| |
210 ManageFrameVp8(std::move(frame)); | |
211 } else if (codec_type == kVideoCodecVP9) { | |
212 // TODO(philipel): ManageFrameVp9(std::move(frame)); | |
213 } else { | |
214 ManageFrameGeneric(std::move(frame)); | |
215 } | |
216 } | |
217 | |
218 void PacketBuffer::RetryStashedFrames() { | |
219 size_t num_stashed_frames = stashed_frames_.size(); | |
220 | |
221 // Clean up stashed frames if there are to many. | |
222 while (stashed_frames_.size() > 10) | |
223 stashed_frames_.pop(); | |
224 | |
225 // Since frames are stashed if there is not enough data to determine their | |
226 // frame references we should at most check |stashed_frames_.size()| in | |
227 // order to not pop and push frames in and endless loop. | |
228 for (size_t i = 0; i < num_stashed_frames && !stashed_frames_.empty(); ++i) { | |
229 std::unique_ptr<RtpFrameObject> frame = std::move(stashed_frames_.front()); | |
230 stashed_frames_.pop(); | |
231 ManageFrame(std::move(frame)); | |
232 } | |
233 } | |
234 | |
235 void PacketBuffer::ManageFrameGeneric( | |
236 std::unique_ptr<RtpFrameObject> frame) { | |
237 size_t index = frame->first_packet() % size_; | |
238 const VCMPacket& packet = data_buffer_[index]; | |
239 | |
240 if (packet.frameType == kVideoFrameKey) | |
241 last_seq_num_for_kf_[frame->last_packet()] = frame->last_packet(); | |
242 | |
243 // Clean up info for old keyframes but make sure to keep info | |
244 // for the last keyframe. | |
245 auto clean_to = last_seq_num_for_kf_.lower_bound(frame->last_packet() - 100); | |
246 if (clean_to != last_seq_num_for_kf_.end() || | |
247 clean_to != (--last_seq_num_for_kf_.end())) { | |
248 last_seq_num_for_kf_.erase(last_seq_num_for_kf_.begin(), clean_to); | |
249 } | |
250 | |
251 // Find the last sequence number of the last frame for the keyframe | |
252 // that this frame indirectly references. | |
253 auto seq_num_it = last_seq_num_for_kf_.upper_bound(frame->last_packet()); | |
254 seq_num_it--; | |
255 | |
256 // Make sure the packet sequence numbers are continuous, otherwise stash | |
257 // this frame. | |
258 if (packet.frameType == kVideoFrameDelta) { | |
259 if (seq_num_it->second != | |
260 static_cast<uint16_t>(frame->first_packet() - 1)) { | |
stefan-webrtc
2016/04/07 12:37:04
I'm reading this as if frame must be next frame af
philipel
2016/04/07 13:38:42
There can be delta frames in between. On line 271
stefan-webrtc
2016/04/19 12:24:29
I was confused about the last_seq_num_for_kf_. I i
philipel
2016/04/19 13:12:01
Renamed it to |last_seq_num_gop_|.
| |
261 stashed_frames_.emplace(std::move(frame)); | |
262 return; | |
263 } | |
264 } | |
265 | |
266 RTC_DCHECK(AheadOrAt(frame->last_packet(), seq_num_it->first)); | |
267 | |
268 frame->picture_id = frame->last_packet(); | |
stefan-webrtc
2016/04/07 12:37:04
I find this a bit strange. Why do we assign a pack
philipel
2016/04/07 13:38:42
Added comment which explains why.
stefan-webrtc
2016/04/19 10:38:19
But maybe last_packet() should return last_picture
philipel
2016/04/19 11:52:07
The function last_packet simply returns the sequen
stefan-webrtc
2016/04/19 12:24:29
Ah, call it last_packet_sequence_number() or last_
philipel
2016/04/19 13:12:01
True, renamed |last_packet()| to |last_seq_num()|
| |
269 frame->num_references = packet.frameType == kVideoFrameDelta; | |
270 frame->references[0] = seq_num_it->second; | |
stefan-webrtc
2016/04/07 12:37:04
Always referring to the key frame? I guess this is
philipel
2016/04/07 13:38:42
Since we update the picture id stored in the map t
| |
271 seq_num_it->second = frame->last_packet(); | |
272 | |
273 last_picture_id_ = frame->picture_id; | |
274 frame_callback_->OnCompleteFrame(std::move(frame)); | |
275 RetryStashedFrames(); | |
276 } | |
277 | |
278 void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { | |
279 size_t index = frame->first_packet() % size_; | |
280 const VCMPacket& packet = data_buffer_[index]; | |
281 const RTPVideoHeaderVP8& codec_header = | |
282 packet.codecSpecificHeader.codecHeader.VP8; | |
283 | |
284 if (codec_header.pictureId == kNoPictureId || | |
285 codec_header.temporalIdx == kNoTemporalIdx || | |
286 codec_header.tl0PicIdx == kNoTl0PicIdx) { | |
287 ManageFrameGeneric(std::move(frame)); | |
288 return; | |
289 } | |
290 | |
291 frame->picture_id = codec_header.pictureId % kPicIdLength; | |
292 | |
293 if (last_unwrap_ == -1) | |
294 last_unwrap_ = codec_header.pictureId; | |
295 | |
296 if (last_picture_id_ == -1) | |
297 last_picture_id_ = frame->picture_id; | |
298 | |
299 // Find if there has been a gap in fully received frames and save the picture | |
300 // id of those frames in |not_yet_received_frames_|. | |
301 if (AheadOf<uint8_t, kPicIdLength>(frame->picture_id, last_picture_id_)) { | |
302 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
303 while (last_picture_id_ != frame->picture_id) { | |
304 not_yet_received_frames_.insert(last_picture_id_); | |
305 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
306 } | |
307 } | |
308 | |
309 // Clean up info for base layers that are to old. | |
stefan-webrtc
2016/04/07 12:37:04
too old
philipel
2016/04/07 13:38:42
Done.
| |
310 uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - 10; | |
stefan-webrtc
2016/04/07 12:37:04
Why is 10 frames back too old? Wouldn't it be bett
philipel
2016/04/07 13:38:42
The value 10 is just an arbitrary number that is "
| |
311 auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx); | |
312 layer_info_.erase(layer_info_.begin(), clean_layer_info_to); | |
313 | |
314 // Clean up info about not yet received frames that are to old. | |
315 uint16_t old_picture_id = Subtract<kPicIdLength>(frame->picture_id, 20); | |
stefan-webrtc
2016/04/19 10:38:19
Name this constant, and the same with 10 above.
philipel
2016/04/19 11:52:07
Done.
| |
316 auto clean_frames_to = not_yet_received_frames_.lower_bound(old_picture_id); | |
317 not_yet_received_frames_.erase(not_yet_received_frames_.begin(), | |
318 clean_frames_to); | |
stefan-webrtc
2016/04/07 12:37:04
I think we should break out the clean up functiona
philipel
2016/04/07 13:38:42
Hmm... I think the interface of such a function wo
stefan-webrtc
2016/04/19 10:38:19
Maybe. I was thinking something simple, like Clean
| |
319 | |
320 if (packet.frameType == kVideoFrameKey) { | |
321 frame->num_references = 0; | |
322 layer_info_[codec_header.tl0PicIdx].fill(-1); | |
323 CompletedFrameVp8(std::move(frame)); | |
324 return; | |
325 } | |
326 | |
327 auto layer_info_it = layer_info_.find(codec_header.temporalIdx == 0 | |
328 ? codec_header.tl0PicIdx - 1 | |
stefan-webrtc
2016/04/07 12:37:04
Should this do Add<...>(codec_header.tl0PicIdx, -1
philipel
2016/04/07 13:38:42
Not needed in this case since tl0PicIdx wraps at 2
stefan-webrtc
2016/04/19 10:38:19
Acknowledged.
| |
329 : codec_header.tl0PicIdx); | |
330 | |
331 // If we don't have the base layer frame yet, stash this frame. | |
332 if (layer_info_it == layer_info_.end()) { | |
333 stashed_frames_.emplace(std::move(frame)); | |
334 return; | |
335 } | |
336 | |
337 // A non keyframe base layer frame has been received, copy the layer info | |
338 // from the previous base layer frame and set a reference to the previous | |
339 // base layer frame. | |
340 if (codec_header.temporalIdx == 0) { | |
341 layer_info_it = | |
342 layer_info_ | |
343 .insert(make_pair(codec_header.tl0PicIdx, layer_info_it->second)) | |
344 .first; | |
345 frame->num_references = 1; | |
346 frame->references[0] = layer_info_it->second[0]; | |
stefan-webrtc
2016/04/07 12:37:04
Is it guaranteed that there isn't a gap between "f
philipel
2016/04/07 13:38:42
On line 327 we check if this is a frame on tempora
stefan-webrtc
2016/04/19 10:38:19
Acknowledged.
| |
347 CompletedFrameVp8(std::move(frame)); | |
348 return; | |
349 } | |
350 | |
351 // Layer sync frame, this frame only references its base layer frame. | |
352 if (codec_header.layerSync) { | |
353 frame->num_references = 1; | |
354 frame->references[0] = layer_info_it->second[0]; | |
355 | |
356 CompletedFrameVp8(std::move(frame)); | |
357 return; | |
358 } | |
359 | |
360 // Find all references for this frame. | |
361 frame->num_references = 0; | |
362 for (uint8_t layer = 0; layer <= codec_header.temporalIdx; ++layer) { | |
363 RTC_DCHECK_NE(-1, layer_info_it->second[layer]); | |
364 ++frame->num_references; | |
365 frame->references[layer] = layer_info_it->second[layer]; | |
stefan-webrtc
2016/04/07 12:37:04
Same question here as on line 346, but I see below
philipel
2016/04/07 13:38:42
Updating the references here doesn't really matter
stefan-webrtc
2016/04/19 10:38:19
So should we only update the references when we ac
philipel
2016/04/19 11:52:07
Changed so that the check occurs before the assign
| |
366 | |
367 // If we have not yet received a frame between this frame and the referenced | |
368 // frame then we have to wait for that frame to be completed first. | |
369 auto not_received_frame_it = | |
370 not_yet_received_frames_.upper_bound(frame->references[layer]); | |
371 if (not_received_frame_it != not_yet_received_frames_.end() && | |
372 AheadOf<uint8_t, kPicIdLength>(frame->picture_id, | |
373 *not_received_frame_it)) { | |
374 stashed_frames_.emplace(std::move(frame)); | |
375 return; | |
376 } | |
377 } | |
378 | |
379 CompletedFrameVp8(std::move(frame)); | |
380 } | |
381 | |
382 void PacketBuffer::CompletedFrameVp8(std::unique_ptr<RtpFrameObject> frame) { | |
383 size_t index = frame->first_packet() % size_; | |
384 const VCMPacket& packet = data_buffer_[index]; | |
385 const RTPVideoHeaderVP8& codec_header = | |
386 packet.codecSpecificHeader.codecHeader.VP8; | |
387 | |
388 uint8_t tl0_pic_idx = codec_header.tl0PicIdx; | |
389 uint8_t temporal_index = codec_header.temporalIdx; | |
390 auto layer_info_it = layer_info_.find(tl0_pic_idx); | |
391 | |
392 // Update this layer info and newer. | |
393 while (layer_info_it != layer_info_.end()) { | |
394 if (layer_info_it->second[temporal_index] != -1 && | |
395 AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_index], | |
396 frame->picture_id)) { | |
397 // The frame was not newer, then no subsequent layer info have to be | |
398 // update. | |
399 break; | |
400 } | |
401 | |
402 layer_info_it->second[codec_header.temporalIdx] = frame->picture_id; | |
403 ++tl0_pic_idx; | |
404 layer_info_it = layer_info_.find(tl0_pic_idx); | |
405 } | |
406 not_yet_received_frames_.erase(frame->picture_id); | |
407 | |
408 for (size_t r = 0; r < frame->num_references; ++r) | |
409 frame->references[r] = UnwrapPictureId(frame->references[r]); | |
410 frame->picture_id = UnwrapPictureId(frame->picture_id); | |
411 | |
412 frame_callback_->OnCompleteFrame(std::move(frame)); | |
413 RetryStashedFrames(); | |
414 } | |
415 | |
416 uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { | |
417 if (last_unwrap_ == -1) | |
418 last_unwrap_ = picture_id; | |
419 | |
420 uint16_t unwrap_truncated = last_unwrap_ % kPicIdLength; | |
421 uint16_t diff = MinDiff<uint8_t, kPicIdLength>(unwrap_truncated, picture_id); | |
422 | |
423 if (AheadOf<uint8_t, kPicIdLength>(picture_id, unwrap_truncated)) | |
424 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | |
425 else | |
426 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | |
427 | |
428 return last_unwrap_; | |
429 } | |
430 | |
195 void PacketBuffer::Flush() { | 431 void PacketBuffer::Flush() { |
196 rtc::CritScope lock(&crit_); | 432 rtc::CritScope lock(&crit_); |
197 for (size_t i = 0; i < size_; ++i) { | 433 for (size_t i = 0; i < size_; ++i) |
198 sequence_buffer_[i].used = false; | 434 sequence_buffer_[i].used = false; |
199 sequence_buffer_[i].continuous = false; | 435 |
200 } | 436 last_seq_num_for_kf_.clear(); |
437 while (!stashed_frames_.empty()) | |
438 stashed_frames_.pop(); | |
439 not_yet_received_frames_.clear(); | |
440 | |
441 first_packet_received_ = false; | |
201 } | 442 } |
202 | 443 |
203 } // namespace video_coding | 444 } // namespace video_coding |
204 } // namespace webrtc | 445 } // namespace webrtc |
OLD | NEW |