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 13 matching lines...) Expand all Loading... | |
24 OnCompleteFrameCallback* frame_callback) | 24 OnCompleteFrameCallback* frame_callback) |
25 : size_(start_buffer_size), | 25 : size_(start_buffer_size), |
26 max_size_(max_buffer_size), | 26 max_size_(max_buffer_size), |
27 first_seq_num_(0), | 27 first_seq_num_(0), |
28 last_seq_num_(0), | 28 last_seq_num_(0), |
29 first_packet_received_(false), | 29 first_packet_received_(false), |
30 data_buffer_(start_buffer_size), | 30 data_buffer_(start_buffer_size), |
31 sequence_buffer_(start_buffer_size), | 31 sequence_buffer_(start_buffer_size), |
32 frame_callback_(frame_callback), | 32 frame_callback_(frame_callback), |
33 last_picture_id_(-1), | 33 last_picture_id_(-1), |
34 last_unwrap_(-1) { | 34 last_unwrap_(-1), |
35 current_ss_idx_(0) { | |
35 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); | 36 RTC_DCHECK_LE(start_buffer_size, max_buffer_size); |
36 // Buffer size must always be a power of 2. | 37 // Buffer size must always be a power of 2. |
37 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); | 38 RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); |
38 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); | 39 RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); |
39 } | 40 } |
40 | 41 |
41 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { | 42 bool PacketBuffer::InsertPacket(const VCMPacket& packet) { |
42 rtc::CritScope lock(&crit_); | 43 rtc::CritScope lock(&crit_); |
43 uint16_t seq_num = packet.seqNum; | 44 uint16_t seq_num = packet.seqNum; |
44 size_t index = seq_num % size_; | 45 size_t index = seq_num % size_; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 case kVideoCodecULPFEC : | 211 case kVideoCodecULPFEC : |
211 case kVideoCodecRED : | 212 case kVideoCodecRED : |
212 case kVideoCodecUnknown : { | 213 case kVideoCodecUnknown : { |
213 RTC_NOTREACHED(); | 214 RTC_NOTREACHED(); |
214 } | 215 } |
215 case kVideoCodecVP8 : { | 216 case kVideoCodecVP8 : { |
216 ManageFrameVp8(std::move(frame)); | 217 ManageFrameVp8(std::move(frame)); |
217 break; | 218 break; |
218 } | 219 } |
219 case kVideoCodecVP9 : { | 220 case kVideoCodecVP9 : { |
220 // TODO(philipel): ManageFrameVp9(std::move(frame)); | 221 ManageFrameVp9(std::move(frame)); |
221 break; | 222 break; |
222 } | 223 } |
223 case kVideoCodecH264 : | 224 case kVideoCodecH264 : |
224 case kVideoCodecI420 : | 225 case kVideoCodecI420 : |
225 case kVideoCodecGeneric : | 226 case kVideoCodecGeneric : |
226 default : { | 227 default : { |
227 ManageFrameGeneric(std::move(frame)); | 228 ManageFrameGeneric(std::move(frame)); |
228 } | 229 } |
229 } | 230 } |
230 } | 231 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 frame->picture_id = codec_header.pictureId % kPicIdLength; | 313 frame->picture_id = codec_header.pictureId % kPicIdLength; |
313 | 314 |
314 if (last_unwrap_ == -1) | 315 if (last_unwrap_ == -1) |
315 last_unwrap_ = codec_header.pictureId; | 316 last_unwrap_ = codec_header.pictureId; |
316 | 317 |
317 if (last_picture_id_ == -1) | 318 if (last_picture_id_ == -1) |
318 last_picture_id_ = frame->picture_id; | 319 last_picture_id_ = frame->picture_id; |
319 | 320 |
320 // Find if there has been a gap in fully received frames and save the picture | 321 // Find if there has been a gap in fully received frames and save the picture |
321 // id of those frames in |not_yet_received_frames_|. | 322 // id of those frames in |not_yet_received_frames_|. |
322 if (AheadOf<uint8_t, kPicIdLength>(frame->picture_id, last_picture_id_)) { | 323 if (AheadOf<uint16_t, kPicIdLength>(frame->picture_id, last_picture_id_)) { |
stefan-webrtc
2016/04/26 08:15:12
Do we have a unittest which would have caught this
philipel
2016/04/28 09:40:42
This was not a bug, I simply wanted to test what w
| |
323 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | 324 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); |
324 while (last_picture_id_ != frame->picture_id) { | 325 while (last_picture_id_ != frame->picture_id) { |
325 not_yet_received_frames_.insert(last_picture_id_); | 326 not_yet_received_frames_.insert(last_picture_id_); |
326 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | 327 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); |
327 } | 328 } |
328 } | 329 } |
329 | 330 |
330 // Clean up info for base layers that are too old. | 331 // Clean up info for base layers that are too old. |
331 uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - kMaxLayerInfo; | 332 uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - kMaxLayerInfo; |
332 auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx); | 333 auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 // Find all references for this frame. | 383 // Find all references for this frame. |
383 frame->num_references = 0; | 384 frame->num_references = 0; |
384 for (uint8_t layer = 0; layer <= codec_header.temporalIdx; ++layer) { | 385 for (uint8_t layer = 0; layer <= codec_header.temporalIdx; ++layer) { |
385 RTC_DCHECK_NE(-1, layer_info_it->second[layer]); | 386 RTC_DCHECK_NE(-1, layer_info_it->second[layer]); |
386 | 387 |
387 // If we have not yet received a frame between this frame and the referenced | 388 // If we have not yet received a frame between this frame and the referenced |
388 // frame then we have to wait for that frame to be completed first. | 389 // frame then we have to wait for that frame to be completed first. |
389 auto not_received_frame_it = | 390 auto not_received_frame_it = |
390 not_yet_received_frames_.upper_bound(layer_info_it->second[layer]); | 391 not_yet_received_frames_.upper_bound(layer_info_it->second[layer]); |
391 if (not_received_frame_it != not_yet_received_frames_.end() && | 392 if (not_received_frame_it != not_yet_received_frames_.end() && |
392 AheadOf<uint8_t, kPicIdLength>(frame->picture_id, | 393 AheadOf<uint16_t, kPicIdLength>(frame->picture_id, |
393 *not_received_frame_it)) { | 394 *not_received_frame_it)) { |
394 stashed_frames_.emplace(std::move(frame)); | 395 stashed_frames_.emplace(std::move(frame)); |
395 return; | 396 return; |
396 } | 397 } |
397 | 398 |
398 ++frame->num_references; | 399 ++frame->num_references; |
399 frame->references[layer] = layer_info_it->second[layer]; | 400 frame->references[layer] = layer_info_it->second[layer]; |
400 } | 401 } |
401 | 402 |
402 CompletedFrameVp8(std::move(frame)); | 403 CompletedFrameVp8(std::move(frame)); |
(...skipping 26 matching lines...) Expand all Loading... | |
429 not_yet_received_frames_.erase(frame->picture_id); | 430 not_yet_received_frames_.erase(frame->picture_id); |
430 | 431 |
431 for (size_t r = 0; r < frame->num_references; ++r) | 432 for (size_t r = 0; r < frame->num_references; ++r) |
432 frame->references[r] = UnwrapPictureId(frame->references[r]); | 433 frame->references[r] = UnwrapPictureId(frame->references[r]); |
433 frame->picture_id = UnwrapPictureId(frame->picture_id); | 434 frame->picture_id = UnwrapPictureId(frame->picture_id); |
434 | 435 |
435 frame_callback_->OnCompleteFrame(std::move(frame)); | 436 frame_callback_->OnCompleteFrame(std::move(frame)); |
436 RetryStashedFrames(); | 437 RetryStashedFrames(); |
437 } | 438 } |
438 | 439 |
440 void PacketBuffer::ManageFrameVp9(std::unique_ptr<RtpFrameObject> frame) { | |
441 size_t index = frame->first_seq_num() % size_; | |
442 const VCMPacket& packet = data_buffer_[index]; | |
443 const RTPVideoHeaderVP9& codec_header = | |
444 packet.codecSpecificHeader.codecHeader.VP9; | |
445 | |
446 if (codec_header.picture_id == kNoPictureId) { | |
447 ManageFrameGeneric(std::move(frame)); | |
448 return; | |
449 } | |
450 | |
451 frame->spatial_layer = codec_header.spatial_idx; | |
452 frame->inter_layer_predicted = codec_header.inter_layer_predicted; | |
453 frame->picture_id = codec_header.picture_id % kPicIdLength; | |
stefan-webrtc
2016/04/26 08:15:12
kPictureIdLength
philipel
2016/04/28 09:40:42
I prefer not, there will be many lines that are al
| |
454 | |
455 if (last_unwrap_ == -1) | |
456 last_unwrap_ = codec_header.picture_id; | |
457 | |
458 if (last_picture_id_ == -1) | |
459 last_picture_id_ = frame->picture_id; | |
460 | |
461 // GLORIUS flexible mode! | |
stefan-webrtc
2016/04/26 08:15:12
I don't think we need this comment... :)
philipel
2016/04/28 09:40:42
Removed :P
| |
462 if (codec_header.flexible_mode) { | |
463 frame->num_references = codec_header.num_ref_pics; | |
464 for (size_t r = 0; r < frame->num_references; ++r) { | |
stefan-webrtc
2016/04/26 08:15:12
use index i rather than r.
philipel
2016/04/28 09:40:42
Done.
| |
465 frame->references[r] = Subtract<1 << 16>(frame->picture_id, | |
466 codec_header.pid_diff[r]); | |
467 } | |
468 | |
469 CompletedFrameVp9(std::move(frame)); | |
470 return; | |
471 } | |
472 | |
473 if (codec_header.ss_data_available) { | |
474 // Scalability structures can only be sent with tl0 frames. | |
475 RTC_DCHECK_EQ(0, codec_header.spatial_idx); | |
stefan-webrtc
2016/04/26 08:15:12
I don't think we'd want to crash if someone gives
philipel
2016/04/28 09:40:42
SS are now ignored if they are not sent on a base
| |
476 | |
477 current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1); | |
478 scalability_structures_[current_ss_idx_] = codec_header.gof; | |
479 scalability_structures_[current_ss_idx_].pid_start = frame->picture_id; | |
480 | |
481 auto pid_and_gof = std::make_pair(frame->picture_id, | |
482 &scalability_structures_[current_ss_idx_]); | |
483 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | |
484 } | |
485 | |
486 // Clean up info for base layers that are to old. | |
stefan-webrtc
2016/04/26 08:15:12
too old
philipel
2016/04/28 09:40:41
Done.
| |
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 RTC_DCHECK(codec_header.ss_data_available); | |
494 | |
495 frame->num_references = 0; | |
496 CompletedFrameVp9(std::move(frame)); | |
497 return; | |
498 } | |
499 | |
500 auto gof_info_it = gof_info_.find((codec_header.temporal_idx == 0 && | |
501 !codec_header.ss_data_available) | |
502 ? codec_header.tl0_pic_idx - 1 | |
503 : codec_header.tl0_pic_idx); | |
504 | |
505 // Gof info for this frame is not available yet, stash this frame. | |
506 if (gof_info_it == gof_info_.end()) { | |
507 stashed_frames_.emplace(std::move(frame)); | |
stefan-webrtc
2016/04/26 08:15:12
What happens if we have already deleted the ss tha
philipel
2016/04/28 09:40:42
RetryStashedFrames have built in clean up logic wh
| |
508 return; | |
509 } | |
510 | |
511 uint16_t picture_id_tl0 = gof_info_it->second.first; | |
512 GofInfoVP9* gof = gof_info_it->second.second; | |
513 | |
514 // If this is a base layer frame that contains a scalability structure | |
515 // then gof info has already been inserted earlier, so we only want to | |
516 // insert if we haven't done so already. | |
517 if (codec_header.temporal_idx == 0 && | |
518 !codec_header.ss_data_available) { | |
519 auto pid_and_gof = std::make_pair(frame->picture_id, gof); | |
520 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | |
521 } | |
522 | |
523 // Sync frames only depend on their tl0_pic_idx.W | |
stefan-webrtc
2016/04/26 08:15:12
Erase W.
And is this comment true? I think a fram
philipel
2016/04/28 09:40:42
I was thinking of sync frames for Vp8 for some rea
| |
524 if (codec_header.temporal_up_switch) { | |
525 frame->num_references = 1; | |
526 frame->references[0] = picture_id_tl0; | |
527 CompletedFrameVp9(std::move(frame)); | |
528 return; | |
529 } | |
530 | |
531 RTC_DCHECK((AheadOrAt<uint16_t, kPicIdLength>(frame->picture_id, | |
stefan-webrtc
2016/04/26 08:15:12
Is this a safe DCHECK if someone produces a bit st
philipel
2016/04/28 09:40:41
What this check do is to make sure we don't select
| |
532 picture_id_tl0))); | |
533 | |
534 uint8_t diff = ForwardDiff<uint16_t, kPicIdLength>(gof->pid_start, | |
535 frame->picture_id); | |
stefan-webrtc
2016/04/26 08:15:12
May not be correctly indented
philipel
2016/04/28 09:40:41
Done.
| |
536 uint8_t gof_idx = diff % gof->num_frames_in_gof; | |
537 | |
538 // Populate references according to the scalability structure. | |
539 frame->num_references = gof->num_ref_pics[gof_idx]; | |
540 for (size_t r = 0; r < frame->num_references; ++r) { | |
stefan-webrtc
2016/04/26 08:15:12
index i
philipel
2016/04/28 09:40:42
Done.
| |
541 diff = ForwardDiff<uint16_t, kPicIdLength>(gof->pid_start, | |
542 frame->picture_id); | |
stefan-webrtc
2016/04/26 08:15:12
Indentation.
And actually, you have already compu
philipel
2016/04/28 09:40:42
Done.
| |
543 gof_idx = diff % gof->num_frames_in_gof; | |
stefan-webrtc
2016/04/26 08:15:12
This too, if I'm not mistaken
philipel
2016/04/28 09:40:42
Done.
| |
544 frame->references[r] = Subtract<1 << 16>(frame->picture_id, | |
545 gof->pid_diff[gof_idx][r]); | |
546 } | |
547 | |
548 CompletedFrameVp9(std::move(frame)); | |
549 } | |
550 | |
551 void PacketBuffer::CompletedFrameVp9(std::unique_ptr<RtpFrameObject> frame) { | |
552 for (size_t r = 0; r < frame->num_references; ++r) | |
553 frame->references[r] = UnwrapPictureId(frame->references[r]); | |
554 frame->picture_id = UnwrapPictureId(frame->picture_id); | |
555 | |
556 frame_callback_->OnCompleteFrame(std::move(frame)); | |
557 RetryStashedFrames(); | |
558 } | |
559 | |
560 | |
439 uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { | 561 uint16_t PacketBuffer::UnwrapPictureId(uint16_t picture_id) { |
440 if (last_unwrap_ == -1) | 562 RTC_DCHECK_NE(-1, last_unwrap_); |
441 last_unwrap_ = picture_id; | |
442 | 563 |
443 uint16_t unwrap_truncated = last_unwrap_ % kPicIdLength; | 564 uint16_t unwrap_truncated = last_unwrap_ % kPicIdLength; |
444 uint16_t diff = MinDiff<uint8_t, kPicIdLength>(unwrap_truncated, picture_id); | 565 uint16_t diff = MinDiff<uint16_t, kPicIdLength>(unwrap_truncated, picture_id); |
445 | 566 |
446 if (AheadOf<uint8_t, kPicIdLength>(picture_id, unwrap_truncated)) | 567 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) |
447 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | 568 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); |
448 else | 569 else |
449 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | 570 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); |
450 | 571 |
451 return last_unwrap_; | 572 return last_unwrap_; |
452 } | 573 } |
453 | 574 |
454 void PacketBuffer::Flush() { | 575 void PacketBuffer::Flush() { |
455 rtc::CritScope lock(&crit_); | 576 rtc::CritScope lock(&crit_); |
456 for (size_t i = 0; i < size_; ++i) | 577 for (size_t i = 0; i < size_; ++i) |
457 sequence_buffer_[i].used = false; | 578 sequence_buffer_[i].used = false; |
458 | 579 |
459 last_seq_num_gop_.clear(); | 580 last_seq_num_gop_.clear(); |
460 while (!stashed_frames_.empty()) | 581 while (!stashed_frames_.empty()) |
461 stashed_frames_.pop(); | 582 stashed_frames_.pop(); |
462 not_yet_received_frames_.clear(); | 583 not_yet_received_frames_.clear(); |
463 | 584 |
464 first_packet_received_ = false; | 585 first_packet_received_ = false; |
465 } | 586 } |
466 | 587 |
467 } // namespace video_coding | 588 } // namespace video_coding |
468 } // namespace webrtc | 589 } // namespace webrtc |
OLD | NEW |