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 12 matching lines...) Expand all Loading... | |
23 PacketBuffer::PacketBuffer(size_t start_buffer_size, | 23 PacketBuffer::PacketBuffer(size_t start_buffer_size, |
24 size_t max_buffer_size, | 24 size_t max_buffer_size, |
25 OnCompleteFrameCallback* frame_callback) | 25 OnCompleteFrameCallback* frame_callback) |
26 : size_(start_buffer_size), | 26 : size_(start_buffer_size), |
27 max_size_(max_buffer_size), | 27 max_size_(max_buffer_size), |
28 first_seq_num_(0), | 28 first_seq_num_(0), |
29 last_seq_num_(0), | 29 last_seq_num_(0), |
30 first_packet_received_(false), | 30 first_packet_received_(false), |
31 data_buffer_(start_buffer_size), | 31 data_buffer_(start_buffer_size), |
32 sequence_buffer_(start_buffer_size), | 32 sequence_buffer_(start_buffer_size), |
33 frame_callback_(frame_callback), | 33 reference_finder_(frame_callback) { |
34 last_picture_id_(-1), | |
35 last_unwrap_(-1), | |
36 current_ss_idx_(0) { | |
37 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); | 34 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); |
38 // Buffer size must always be a power of 2. | 35 // Buffer size must always be a power of 2. |
39 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); | 36 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); |
40 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); | 37 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); |
41 } | 38 } |
42 | 39 |
43 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { | 40 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { |
44 rtc::CritScope lock(&crit_); | 41 rtc::CritScope lock(&crit_); |
45 uint16_t seq_num = packet.seqNum; | 42 uint16_t seq_num = packet.seqNum; |
46 size_t index = seq_num % size_; | 43 size_t index = seq_num % size_; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 | 142 |
146 while (!sequence_buffer_[start_index].frame_begin) { | 143 while (!sequence_buffer_[start_index].frame_begin) { |
147 sequence_buffer_[start_index].frame_created = true; | 144 sequence_buffer_[start_index].frame_created = true; |
148 start_index = start_index > 0 ? start_index - 1 : size_ - 1; | 145 start_index = start_index > 0 ? start_index - 1 : size_ - 1; |
149 start_seq_num--; | 146 start_seq_num--; |
150 } | 147 } |
151 sequence_buffer_[start_index].frame_created = true; | 148 sequence_buffer_[start_index].frame_created = true; |
152 | 149 |
153 std::unique_ptr<RtpFrameObject> frame( | 150 std::unique_ptr<RtpFrameObject> frame( |
154 new RtpFrameObject(this, start_seq_num, seq_num)); | 151 new RtpFrameObject(this, start_seq_num, seq_num)); |
155 ManageFrame(std::move(frame)); | 152 reference_finder_.ManageFrame(std::move(frame)); |
156 } | 153 } |
157 | 154 |
158 index = (index + 1) % size_; | 155 index = (index + 1) % size_; |
159 ++seq_num; | 156 ++seq_num; |
160 } | 157 } |
161 } | 158 } |
162 | 159 |
163 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { | 160 void PacketBuffer::ReturnFrame(RtpFrameObject* frame) { |
164 rtc::CritScope lock(&crit_); | 161 rtc::CritScope lock(&crit_); |
165 size_t index = frame->first_seq_num() % size_; | 162 size_t index = frame->first_seq_num() % size_; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 const uint8_t* source = data_buffer_[index].dataPtr; | 194 const uint8_t* source = data_buffer_[index].dataPtr; |
198 size_t length = data_buffer_[index].sizeBytes; | 195 size_t length = data_buffer_[index].sizeBytes; |
199 memcpy(destination, source, length); | 196 memcpy(destination, source, length); |
200 destination += length; | 197 destination += length; |
201 index = (index + 1) % size_; | 198 index = (index + 1) % size_; |
202 ++seq_num; | 199 ++seq_num; |
203 } | 200 } |
204 return true; | 201 return true; |
205 } | 202 } |
206 | 203 |
207 void PacketBuffer::ManageFrame(std::unique_ptr<RtpFrameObject> frame) { | 204 VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) { |
208 size_t start_index = frame->first_seq_num() % size_; | 205 rtc::CritScope lock(&crit_); |
209 VideoCodecType codec_type = data_buffer_[start_index].codec; | 206 size_t index = seq_num % size_; |
210 | 207 if (!sequence_buffer_[index].used || |
211 switch (codec_type) { | 208 seq_num != sequence_buffer_[index].seq_num) { |
212 case kVideoCodecULPFEC: | 209 return nullptr; |
stefan-webrtc
2016/05/12 11:52:07
Should we DCHECK here, or is this a valid case?
philipel
2016/05/12 13:34:49
This is a valid case, we return nullptr if the pac
stefan-webrtc
2016/05/13 11:10:22
Makes sense
| |
213 case kVideoCodecRED: | |
214 case kVideoCodecUnknown: | |
215 RTC_NOTREACHED(); | |
216 break; | |
217 case kVideoCodecVP8: | |
218 ManageFrameVp8(std::move(frame)); | |
219 break; | |
220 case kVideoCodecVP9: | |
221 ManageFrameVp9(std::move(frame)); | |
222 break; | |
223 case kVideoCodecH264: | |
224 case kVideoCodecI420: | |
225 case kVideoCodecGeneric: | |
226 ManageFrameGeneric(std::move(frame)); | |
227 break; | |
228 } | 210 } |
211 return &data_buffer_[index]; | |
229 } | 212 } |
230 | 213 |
231 void PacketBuffer::RetryStashedFrames() { | 214 void PacketBuffer::Clear() { |
232 size_t num_stashed_frames = stashed_frames_.size(); | |
233 | |
234 // Clean up stashed frames if there are too many. | |
235 while (stashed_frames_.size() > kMaxStashedFrames) | |
236 stashed_frames_.pop(); | |
237 | |
238 // Since frames are stashed if there is not enough data to determine their | |
239 // frame references we should at most check |stashed_frames_.size()| in | |
240 // order to not pop and push frames in and endless loop. | |
241 for (size_t i = 0; i < num_stashed_frames && !stashed_frames_.empty(); ++i) { | |
242 std::unique_ptr<RtpFrameObject> frame = std::move(stashed_frames_.front()); | |
243 stashed_frames_.pop(); | |
244 ManageFrame(std::move(frame)); | |
245 } | |
246 } | |
247 | |
248 void PacketBuffer::ManageFrameGeneric( | |
249 std::unique_ptr<RtpFrameObject> frame) { | |
250 size_t index = frame->first_seq_num() % size_; | |
251 const VCMPacket& packet = data_buffer_[index]; | |
252 | |
253 if (packet.frameType == kVideoFrameKey) | |
254 last_seq_num_gop_[frame->last_seq_num()] = frame->last_seq_num(); | |
255 | |
256 // We have received a frame but not yet a keyframe, stash this frame. | |
257 if (last_seq_num_gop_.empty()) { | |
258 stashed_frames_.emplace(std::move(frame)); | |
259 return; | |
260 } | |
261 | |
262 // Clean up info for old keyframes but make sure to keep info | |
263 // for the last keyframe. | |
264 auto clean_to = last_seq_num_gop_.lower_bound(frame->last_seq_num() - 100); | |
265 if (clean_to != last_seq_num_gop_.end()) | |
266 last_seq_num_gop_.erase(last_seq_num_gop_.begin(), clean_to); | |
267 | |
268 // Find the last sequence number of the last frame for the keyframe | |
269 // that this frame indirectly references. | |
270 auto seq_num_it = last_seq_num_gop_.upper_bound(frame->last_seq_num()); | |
271 seq_num_it--; | |
272 | |
273 // Make sure the packet sequence numbers are continuous, otherwise stash | |
274 // this frame. | |
275 if (packet.frameType == kVideoFrameDelta) { | |
276 if (seq_num_it->second != | |
277 static_cast<uint16_t>(frame->first_seq_num() - 1)) { | |
278 stashed_frames_.emplace(std::move(frame)); | |
279 return; | |
280 } | |
281 } | |
282 | |
283 RTC_DCHECK(AheadOrAt(frame->last_seq_num(), seq_num_it->first)); | |
284 | |
285 // Since keyframes can cause reordering of the frames delivered from | |
286 // FindFrames() we can't simply assign the picture id according to some | |
287 // incrementing counter. | |
288 frame->picture_id = frame->last_seq_num(); | |
289 frame->num_references = packet.frameType == kVideoFrameDelta; | |
290 frame->references[0] = seq_num_it->second; | |
291 seq_num_it->second = frame->picture_id; | |
292 | |
293 last_picture_id_ = frame->picture_id; | |
294 frame_callback_->OnCompleteFrame(std::move(frame)); | |
295 RetryStashedFrames(); | |
296 } | |
297 | |
298 void PacketBuffer::ManageFrameVp8(std::unique_ptr<RtpFrameObject> frame) { | |
299 size_t index = frame->first_seq_num() % size_; | |
300 const VCMPacket& packet = data_buffer_[index]; | |
301 const RTPVideoHeaderVP8& codec_header = | |
302 packet.codecSpecificHeader.codecHeader.VP8; | |
303 | |
304 if (codec_header.pictureId == kNoPictureId || | |
305 codec_header.temporalIdx == kNoTemporalIdx || | |
306 codec_header.tl0PicIdx == kNoTl0PicIdx) { | |
307 ManageFrameGeneric(std::move(frame)); | |
308 return; | |
309 } | |
310 | |
311 frame->picture_id = codec_header.pictureId % kPicIdLength; | |
312 | |
313 if (last_unwrap_ == -1) | |
314 last_unwrap_ = codec_header.pictureId; | |
315 | |
316 if (last_picture_id_ == -1) | |
317 last_picture_id_ = frame->picture_id; | |
318 | |
319 // Find if there has been a gap in fully received frames and save the picture | |
320 // id of those frames in |not_yet_received_frames_|. | |
321 if (AheadOf<uint16_t, kPicIdLength>(frame->picture_id, last_picture_id_)) { | |
322 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
323 while (last_picture_id_ != frame->picture_id) { | |
324 not_yet_received_frames_.insert(last_picture_id_); | |
325 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
326 } | |
327 } | |
328 | |
329 // Clean up info for base layers that are too old. | |
330 uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - kMaxLayerInfo; | |
331 auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx); | |
332 layer_info_.erase(layer_info_.begin(), clean_layer_info_to); | |
333 | |
334 // Clean up info about not yet received frames that are too old. | |
335 uint16_t old_picture_id = Subtract<kPicIdLength>(frame->picture_id, | |
336 kMaxNotYetReceivedFrames); | |
337 auto clean_frames_to = not_yet_received_frames_.lower_bound(old_picture_id); | |
338 not_yet_received_frames_.erase(not_yet_received_frames_.begin(), | |
339 clean_frames_to); | |
340 | |
341 if (packet.frameType == kVideoFrameKey) { | |
342 frame->num_references = 0; | |
343 layer_info_[codec_header.tl0PicIdx].fill(-1); | |
344 CompletedFrameVp8(std::move(frame)); | |
345 return; | |
346 } | |
347 | |
348 auto layer_info_it = layer_info_.find(codec_header.temporalIdx == 0 | |
349 ? codec_header.tl0PicIdx - 1 | |
350 : codec_header.tl0PicIdx); | |
351 | |
352 // If we don't have the base layer frame yet, stash this frame. | |
353 if (layer_info_it == layer_info_.end()) { | |
354 stashed_frames_.emplace(std::move(frame)); | |
355 return; | |
356 } | |
357 | |
358 // A non keyframe base layer frame has been received, copy the layer info | |
359 // from the previous base layer frame and set a reference to the previous | |
360 // base layer frame. | |
361 if (codec_header.temporalIdx == 0) { | |
362 layer_info_it = | |
363 layer_info_ | |
364 .insert(make_pair(codec_header.tl0PicIdx, layer_info_it->second)) | |
365 .first; | |
366 frame->num_references = 1; | |
367 frame->references[0] = layer_info_it->second[0]; | |
368 CompletedFrameVp8(std::move(frame)); | |
369 return; | |
370 } | |
371 | |
372 // Layer sync frame, this frame only references its base layer frame. | |
373 if (codec_header.layerSync) { | |
374 frame->num_references = 1; | |
375 frame->references[0] = layer_info_it->second[0]; | |
376 | |
377 CompletedFrameVp8(std::move(frame)); | |
378 return; | |
379 } | |
380 | |
381 // Find all references for this frame. | |
382 frame->num_references = 0; | |
383 for (uint8_t layer = 0; layer <= codec_header.temporalIdx; ++layer) { | |
384 RTC_DCHECK_NE(-1, layer_info_it->second[layer]); | |
385 | |
386 // If we have not yet received a frame between this frame and the referenced | |
387 // frame then we have to wait for that frame to be completed first. | |
388 auto not_received_frame_it = | |
389 not_yet_received_frames_.upper_bound(layer_info_it->second[layer]); | |
390 if (not_received_frame_it != not_yet_received_frames_.end() && | |
391 AheadOf<uint16_t, kPicIdLength>(frame->picture_id, | |
392 *not_received_frame_it)) { | |
393 stashed_frames_.emplace(std::move(frame)); | |
394 return; | |
395 } | |
396 | |
397 ++frame->num_references; | |
398 frame->references[layer] = layer_info_it->second[layer]; | |
399 } | |
400 | |
401 CompletedFrameVp8(std::move(frame)); | |
402 } | |
403 | |
404 void PacketBuffer::CompletedFrameVp8(std::unique_ptr<RtpFrameObject> frame) { | |
405 size_t index = frame->first_seq_num() % size_; | |
406 const VCMPacket& packet = data_buffer_[index]; | |
407 const RTPVideoHeaderVP8& codec_header = | |
408 packet.codecSpecificHeader.codecHeader.VP8; | |
409 | |
410 uint8_t tl0_pic_idx = codec_header.tl0PicIdx; | |
411 uint8_t temporal_index = codec_header.temporalIdx; | |
412 auto layer_info_it = layer_info_.find(tl0_pic_idx); | |
413 | |
414 // Update this layer info and newer. | |
415 while (layer_info_it != layer_info_.end()) { | |
416 if (layer_info_it->second[temporal_index] != -1 && | |
417 AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_index], | |
418 frame->picture_id)) { | |
419 // The frame was not newer, then no subsequent layer info have to be | |
420 // update. | |
421 break; | |
422 } | |
423 | |
424 layer_info_it->second[codec_header.temporalIdx] = frame->picture_id; | |
425 ++tl0_pic_idx; | |
426 layer_info_it = layer_info_.find(tl0_pic_idx); | |
427 } | |
428 not_yet_received_frames_.erase(frame->picture_id); | |
429 | |
430 for (size_t i = 0; i < frame->num_references; ++i) | |
431 frame->references[i] = UnwrapPictureId(frame->references[i]); | |
432 frame->picture_id = UnwrapPictureId(frame->picture_id); | |
433 | |
434 frame_callback_->OnCompleteFrame(std::move(frame)); | |
435 RetryStashedFrames(); | |
436 } | |
437 | |
438 void PacketBuffer::ManageFrameVp9(std::unique_ptr<RtpFrameObject> frame) { | |
439 size_t index = frame->first_seq_num() % size_; | |
440 const VCMPacket& packet = data_buffer_[index]; | |
441 const RTPVideoHeaderVP9& codec_header = | |
442 packet.codecSpecificHeader.codecHeader.VP9; | |
443 | |
444 if (codec_header.picture_id == kNoPictureId) { | |
445 ManageFrameGeneric(std::move(frame)); | |
446 return; | |
447 } | |
448 | |
449 frame->spatial_layer = codec_header.spatial_idx; | |
450 frame->inter_layer_predicted = codec_header.inter_layer_predicted; | |
451 frame->picture_id = codec_header.picture_id % kPicIdLength; | |
452 | |
453 if (last_unwrap_ == -1) | |
454 last_unwrap_ = codec_header.picture_id; | |
455 | |
456 if (last_picture_id_ == -1) | |
457 last_picture_id_ = frame->picture_id; | |
458 | |
459 if (codec_header.flexible_mode) { | |
460 frame->num_references = codec_header.num_ref_pics; | |
461 for (size_t i = 0; i < frame->num_references; ++i) { | |
462 frame->references[i] = | |
463 Subtract<1 << 16>(frame->picture_id, codec_header.pid_diff[i]); | |
464 } | |
465 | |
466 CompletedFrameVp9(std::move(frame)); | |
467 return; | |
468 } | |
469 | |
470 if (codec_header.ss_data_available) { | |
471 // Scalability structures can only be sent with tl0 frames. | |
472 if (codec_header.temporal_idx != 0) { | |
473 LOG(LS_WARNING) << "Received scalability structure on a non base layer" | |
474 " frame. Scalability structure ignored."; | |
475 } else { | |
476 current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1); | |
477 scalability_structures_[current_ss_idx_] = codec_header.gof; | |
478 scalability_structures_[current_ss_idx_].pid_start = frame->picture_id; | |
479 | |
480 auto pid_and_gof = std::make_pair( | |
481 frame->picture_id, &scalability_structures_[current_ss_idx_]); | |
482 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | |
483 } | |
484 } | |
485 | |
486 // Clean up info for base layers that are too old. | |
487 uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved; | |
488 auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx); | |
489 gof_info_.erase(gof_info_.begin(), clean_gof_info_to); | |
490 | |
491 if (packet.frameType == kVideoFrameKey) { | |
492 // When using GOF all keyframes must include the scalability structure. | |
493 if (!codec_header.ss_data_available) | |
494 LOG(LS_WARNING) << "Received keyframe without scalability structure"; | |
495 | |
496 frame->num_references = 0; | |
497 GofInfoVP9* gof = gof_info_.find(codec_header.tl0_pic_idx)->second.second; | |
498 FrameReceivedVp9(frame->picture_id, *gof); | |
499 CompletedFrameVp9(std::move(frame)); | |
500 return; | |
501 } | |
502 | |
503 auto gof_info_it = gof_info_.find( | |
504 (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) | |
505 ? codec_header.tl0_pic_idx - 1 | |
506 : codec_header.tl0_pic_idx); | |
507 | |
508 // Gof info for this frame is not available yet, stash this frame. | |
509 if (gof_info_it == gof_info_.end()) { | |
510 stashed_frames_.emplace(std::move(frame)); | |
511 return; | |
512 } | |
513 | |
514 GofInfoVP9* gof = gof_info_it->second.second; | |
515 uint16_t picture_id_tl0 = gof_info_it->second.first; | |
516 | |
517 FrameReceivedVp9(frame->picture_id, *gof); | |
518 | |
519 // Make sure we don't miss any frame that could potentially have the | |
520 // up switch flag set. | |
521 if (MissingRequiredFrameVp9(frame->picture_id, *gof)) { | |
522 stashed_frames_.emplace(std::move(frame)); | |
523 return; | |
524 } | |
525 | |
526 if (codec_header.temporal_up_switch) { | |
527 auto pid_tidx = | |
528 std::make_pair(frame->picture_id, codec_header.temporal_idx); | |
529 up_switch_.insert(pid_tidx); | |
530 } | |
531 | |
532 // If this is a base layer frame that contains a scalability structure | |
533 // then gof info has already been inserted earlier, so we only want to | |
534 // insert if we haven't done so already. | |
535 if (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) { | |
536 auto pid_and_gof = std::make_pair(frame->picture_id, gof); | |
537 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | |
538 } | |
539 | |
540 // Clean out old info about up switch frames. | |
541 uint16_t old_picture_id = Subtract<kPicIdLength>(last_picture_id_, 50); | |
542 auto up_switch_erase_to = up_switch_.lower_bound(old_picture_id); | |
543 up_switch_.erase(up_switch_.begin(), up_switch_erase_to); | |
544 | |
545 RTC_DCHECK( | |
546 (AheadOrAt<uint16_t, kPicIdLength>(frame->picture_id, picture_id_tl0))); | |
547 | |
548 size_t diff = | |
549 ForwardDiff<uint16_t, kPicIdLength>(gof->pid_start, frame->picture_id); | |
550 size_t gof_idx = diff % gof->num_frames_in_gof; | |
551 | |
552 // Populate references according to the scalability structure. | |
553 frame->num_references = gof->num_ref_pics[gof_idx]; | |
554 for (size_t i = 0; i < frame->num_references; ++i) { | |
555 frame->references[i] = | |
556 Subtract<kPicIdLength>(frame->picture_id, gof->pid_diff[gof_idx][i]); | |
557 | |
558 // If this is a reference to a frame earlier than the last up switch point, | |
559 // then ignore this reference. | |
560 if (UpSwitchInIntervalVp9(frame->picture_id, codec_header.temporal_idx, | |
561 frame->references[i])) { | |
562 --frame->num_references; | |
563 } | |
564 } | |
565 | |
566 CompletedFrameVp9(std::move(frame)); | |
567 } | |
568 | |
569 bool PacketBuffer::MissingRequiredFrameVp9(uint16_t picture_id, | |
570 const GofInfoVP9& gof) { | |
571 size_t diff = ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, picture_id); | |
572 size_t gof_idx = diff % gof.num_frames_in_gof; | |
573 size_t temporal_idx = gof.temporal_idx[gof_idx]; | |
574 | |
575 // For every reference this frame has, check if there is a frame missing in | |
576 // the interval (|ref_pid|, |picture_id|) in any of the lower temporal | |
577 // layers. If so, we are missing a required frame. | |
578 uint8_t num_references = gof.num_ref_pics[gof_idx]; | |
579 for (size_t i = 0; i < num_references; ++i) { | |
580 uint16_t ref_pid = | |
581 Subtract<kPicIdLength>(picture_id, gof.pid_diff[gof_idx][i]); | |
582 for (size_t l = 0; l < temporal_idx; ++l) { | |
583 auto missing_frame_it = missing_frames_for_layer_[l].lower_bound(ref_pid); | |
584 if (missing_frame_it != missing_frames_for_layer_[l].end() && | |
585 AheadOf<uint16_t, kPicIdLength>(picture_id, *missing_frame_it)) { | |
586 return true; | |
587 } | |
588 } | |
589 } | |
590 return false; | |
591 } | |
592 | |
593 void PacketBuffer::FrameReceivedVp9(uint16_t picture_id, | |
594 const GofInfoVP9& gof) { | |
595 RTC_DCHECK_NE(-1, last_picture_id_); | |
596 | |
597 // If there is a gap, find which temporal layer the missing frames | |
598 // belong to and add the frame as missing for that temporal layer. | |
599 // Otherwise, remove this frame from the set of missing frames. | |
600 if (AheadOf<uint16_t, kPicIdLength>(picture_id, last_picture_id_)) { | |
601 size_t diff = | |
602 ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, last_picture_id_); | |
603 size_t gof_idx = diff % gof.num_frames_in_gof; | |
604 | |
605 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
606 while (last_picture_id_ != picture_id) { | |
607 ++gof_idx; | |
608 RTC_DCHECK_NE(0ul, gof_idx % gof.num_frames_in_gof); | |
609 size_t temporal_idx = gof.temporal_idx[gof_idx]; | |
610 missing_frames_for_layer_[temporal_idx].insert(last_picture_id_); | |
611 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | |
612 } | |
613 } else { | |
614 size_t diff = | |
615 ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, picture_id); | |
616 size_t gof_idx = diff % gof.num_frames_in_gof; | |
617 size_t temporal_idx = gof.temporal_idx[gof_idx]; | |
618 missing_frames_for_layer_[temporal_idx].erase(picture_id); | |
619 } | |
620 } | |
621 | |
622 bool PacketBuffer::UpSwitchInIntervalVp9(uint16_t picture_id, | |
623 uint8_t temporal_idx, | |
624 uint16_t pid_ref) { | |
625 for (auto up_switch_it = up_switch_.upper_bound(pid_ref); | |
626 up_switch_it != up_switch_.end() && | |
627 AheadOf<uint16_t, kPicIdLength>(picture_id, up_switch_it->first); | |
628 ++up_switch_it) { | |
629 if (up_switch_it->second < temporal_idx) | |
630 return true; | |
631 } | |
632 | |
633 return false; | |
634 } | |
635 | |
636 void PacketBuffer::CompletedFrameVp9(std::unique_ptr<RtpFrameObject> frame) { | |
637 for (size_t i = 0; i < frame->num_references; ++i) | |
638 frame->references[i] = UnwrapPictureId(frame->references[i]); | |
639 frame->picture_id = UnwrapPictureId(frame->picture_id); | |
640 | |
641 frame_callback_->OnCompleteFrame(std::move(frame)); | |
642 RetryStashedFrames(); | |
643 } | |
644 | |
645 uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { | |
646 RTC_DCHECK_NE(-1, last_unwrap_); | |
647 | |
648 uint16_t unwrap_truncated = last_unwrap_ % kPicIdLength; | |
649 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); | |
650 | |
651 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) | |
652 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | |
653 else | |
654 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | |
655 | |
656 return last_unwrap_; | |
657 } | |
658 | |
659 void PacketBuffer::Flush() { | |
660 rtc::CritScope lock(&crit_); | 215 rtc::CritScope lock(&crit_); |
661 for (size_t i = 0; i < size_; ++i) | 216 for (size_t i = 0; i < size_; ++i) |
662 sequence_buffer_[i].used = false; | 217 sequence_buffer_[i].used = false; |
663 | 218 |
664 last_seq_num_gop_.clear(); | |
665 while (!stashed_frames_.empty()) | |
666 stashed_frames_.pop(); | |
667 not_yet_received_frames_.clear(); | |
668 | |
669 first_packet_received_ = false; | 219 first_packet_received_ = false; |
670 } | 220 } |
671 | 221 |
672 } // namespace video_coding | 222 } // namespace video_coding |
673 } // namespace webrtc | 223 } // namespace webrtc |
OLD | NEW |