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

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

Issue 1847193003: Convert Vp8 Rtp headers to frame references. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Picture id start at the picture id of the first frame. Created 4 years, 8 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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698