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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 if (codec_header.ss_data_available) { | 361 if (codec_header.ss_data_available) { |
362 // Scalability structures can only be sent with tl0 frames. | 362 // Scalability structures can only be sent with tl0 frames. |
363 if (codec_header.temporal_idx != 0) { | 363 if (codec_header.temporal_idx != 0) { |
364 LOG(LS_WARNING) << "Received scalability structure on a non base layer" | 364 LOG(LS_WARNING) << "Received scalability structure on a non base layer" |
365 " frame. Scalability structure ignored."; | 365 " frame. Scalability structure ignored."; |
366 } else { | 366 } else { |
367 current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1); | 367 current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1); |
368 scalability_structures_[current_ss_idx_] = codec_header.gof; | 368 scalability_structures_[current_ss_idx_] = codec_header.gof; |
369 scalability_structures_[current_ss_idx_].pid_start = frame->picture_id; | 369 scalability_structures_[current_ss_idx_].pid_start = frame->picture_id; |
370 | 370 |
371 auto pid_and_gof = std::make_pair( | 371 GofInfo info(&scalability_structures_[current_ss_idx_], |
372 frame->picture_id, &scalability_structures_[current_ss_idx_]); | 372 frame->picture_id); |
373 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | 373 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, info)); |
374 } | 374 } |
375 } | 375 } |
376 | 376 |
377 // Clean up info for base layers that are too old. | 377 // Clean up info for base layers that are too old. |
378 uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved; | 378 uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved; |
379 auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx); | 379 auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx); |
380 gof_info_.erase(gof_info_.begin(), clean_gof_info_to); | 380 gof_info_.erase(gof_info_.begin(), clean_gof_info_to); |
381 | 381 |
382 if (frame->frame_type() == kVideoFrameKey) { | 382 if (frame->frame_type() == kVideoFrameKey) { |
383 // When using GOF all keyframes must include the scalability structure. | 383 // When using GOF all keyframes must include the scalability structure. |
384 if (!codec_header.ss_data_available) | 384 if (!codec_header.ss_data_available) |
385 LOG(LS_WARNING) << "Received keyframe without scalability structure"; | 385 LOG(LS_WARNING) << "Received keyframe without scalability structure"; |
386 | 386 |
387 frame->num_references = 0; | 387 frame->num_references = 0; |
388 GofInfoVP9* gof = gof_info_.find(codec_header.tl0_pic_idx)->second.second; | 388 GofInfo info = gof_info_.find(codec_header.tl0_pic_idx)->second; |
389 FrameReceivedVp9(frame->picture_id, *gof); | 389 FrameReceivedVp9(frame->picture_id, &info); |
390 CompletedFrameVp9(std::move(frame)); | 390 CompletedFrameVp9(std::move(frame)); |
391 return; | 391 return; |
392 } | 392 } |
393 | 393 |
394 auto gof_info_it = gof_info_.find( | 394 auto gof_info_it = gof_info_.find( |
395 (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) | 395 (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) |
396 ? codec_header.tl0_pic_idx - 1 | 396 ? codec_header.tl0_pic_idx - 1 |
397 : codec_header.tl0_pic_idx); | 397 : codec_header.tl0_pic_idx); |
398 | 398 |
399 // Gof info for this frame is not available yet, stash this frame. | 399 // Gof info for this frame is not available yet, stash this frame. |
400 if (gof_info_it == gof_info_.end()) { | 400 if (gof_info_it == gof_info_.end()) { |
401 stashed_frames_.emplace(std::move(frame)); | 401 stashed_frames_.emplace(std::move(frame)); |
402 return; | 402 return; |
403 } | 403 } |
404 | 404 |
405 GofInfoVP9* gof = gof_info_it->second.second; | 405 GofInfo* info = &gof_info_it->second; |
406 uint16_t picture_id_tl0 = gof_info_it->second.first; | 406 FrameReceivedVp9(frame->picture_id, info); |
407 | |
408 FrameReceivedVp9(frame->picture_id, *gof); | |
409 | 407 |
410 // Make sure we don't miss any frame that could potentially have the | 408 // Make sure we don't miss any frame that could potentially have the |
411 // up switch flag set. | 409 // up switch flag set. |
412 if (MissingRequiredFrameVp9(frame->picture_id, *gof)) { | 410 if (MissingRequiredFrameVp9(frame->picture_id, *info)) { |
413 stashed_frames_.emplace(std::move(frame)); | 411 stashed_frames_.emplace(std::move(frame)); |
414 return; | 412 return; |
415 } | 413 } |
416 | 414 |
417 if (codec_header.temporal_up_switch) { | 415 if (codec_header.temporal_up_switch) { |
418 auto pid_tidx = | 416 auto pid_tidx = |
419 std::make_pair(frame->picture_id, codec_header.temporal_idx); | 417 std::make_pair(frame->picture_id, codec_header.temporal_idx); |
420 up_switch_.insert(pid_tidx); | 418 up_switch_.insert(pid_tidx); |
421 } | 419 } |
422 | 420 |
423 // If this is a base layer frame that contains a scalability structure | 421 // If this is a base layer frame that contains a scalability structure |
424 // then gof info has already been inserted earlier, so we only want to | 422 // then gof info has already been inserted earlier, so we only want to |
425 // insert if we haven't done so already. | 423 // insert if we haven't done so already. |
426 if (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) { | 424 if (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) { |
427 auto pid_and_gof = std::make_pair(frame->picture_id, gof); | 425 GofInfo new_info(info->gof, frame->picture_id); |
428 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, pid_and_gof)); | 426 gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, new_info)); |
429 } | 427 } |
430 | 428 |
431 // Clean out old info about up switch frames. | 429 // Clean out old info about up switch frames. |
432 uint16_t old_picture_id = Subtract<kPicIdLength>(last_picture_id_, 50); | 430 uint16_t old_picture_id = Subtract<kPicIdLength>(frame->picture_id, 50); |
433 auto up_switch_erase_to = up_switch_.lower_bound(old_picture_id); | 431 auto up_switch_erase_to = up_switch_.lower_bound(old_picture_id); |
434 up_switch_.erase(up_switch_.begin(), up_switch_erase_to); | 432 up_switch_.erase(up_switch_.begin(), up_switch_erase_to); |
435 | 433 |
436 RTC_DCHECK( | 434 size_t diff = ForwardDiff<uint16_t, kPicIdLength>(info->gof->pid_start, |
437 (AheadOrAt<uint16_t, kPicIdLength>(frame->picture_id, picture_id_tl0))); | 435 frame->picture_id); |
438 | 436 size_t gof_idx = diff % info->gof->num_frames_in_gof; |
439 size_t diff = | |
440 ForwardDiff<uint16_t, kPicIdLength>(gof->pid_start, frame->picture_id); | |
441 size_t gof_idx = diff % gof->num_frames_in_gof; | |
442 | 437 |
443 // Populate references according to the scalability structure. | 438 // Populate references according to the scalability structure. |
444 frame->num_references = gof->num_ref_pics[gof_idx]; | 439 frame->num_references = info->gof->num_ref_pics[gof_idx]; |
445 for (size_t i = 0; i < frame->num_references; ++i) { | 440 for (size_t i = 0; i < frame->num_references; ++i) { |
446 frame->references[i] = | 441 frame->references[i] = Subtract<kPicIdLength>( |
447 Subtract<kPicIdLength>(frame->picture_id, gof->pid_diff[gof_idx][i]); | 442 frame->picture_id, info->gof->pid_diff[gof_idx][i]); |
448 | 443 |
449 // If this is a reference to a frame earlier than the last up switch point, | 444 // If this is a reference to a frame earlier than the last up switch point, |
450 // then ignore this reference. | 445 // then ignore this reference. |
451 if (UpSwitchInIntervalVp9(frame->picture_id, codec_header.temporal_idx, | 446 if (UpSwitchInIntervalVp9(frame->picture_id, codec_header.temporal_idx, |
452 frame->references[i])) { | 447 frame->references[i])) { |
453 --frame->num_references; | 448 --frame->num_references; |
454 } | 449 } |
455 } | 450 } |
456 | 451 |
457 CompletedFrameVp9(std::move(frame)); | 452 CompletedFrameVp9(std::move(frame)); |
458 } | 453 } |
459 | 454 |
460 bool RtpFrameReferenceFinder::MissingRequiredFrameVp9(uint16_t picture_id, | 455 bool RtpFrameReferenceFinder::MissingRequiredFrameVp9(uint16_t picture_id, |
461 const GofInfoVP9& gof) { | 456 const GofInfo& info) { |
462 size_t diff = ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, picture_id); | 457 size_t diff = |
463 size_t gof_idx = diff % gof.num_frames_in_gof; | 458 ForwardDiff<uint16_t, kPicIdLength>(info.gof->pid_start, picture_id); |
464 size_t temporal_idx = gof.temporal_idx[gof_idx]; | 459 size_t gof_idx = diff % info.gof->num_frames_in_gof; |
| 460 size_t temporal_idx = info.gof->temporal_idx[gof_idx]; |
465 | 461 |
466 // For every reference this frame has, check if there is a frame missing in | 462 // For every reference this frame has, check if there is a frame missing in |
467 // the interval (|ref_pid|, |picture_id|) in any of the lower temporal | 463 // the interval (|ref_pid|, |picture_id|) in any of the lower temporal |
468 // layers. If so, we are missing a required frame. | 464 // layers. If so, we are missing a required frame. |
469 uint8_t num_references = gof.num_ref_pics[gof_idx]; | 465 uint8_t num_references = info.gof->num_ref_pics[gof_idx]; |
470 for (size_t i = 0; i < num_references; ++i) { | 466 for (size_t i = 0; i < num_references; ++i) { |
471 uint16_t ref_pid = | 467 uint16_t ref_pid = |
472 Subtract<kPicIdLength>(picture_id, gof.pid_diff[gof_idx][i]); | 468 Subtract<kPicIdLength>(picture_id, info.gof->pid_diff[gof_idx][i]); |
473 for (size_t l = 0; l < temporal_idx; ++l) { | 469 for (size_t l = 0; l < temporal_idx; ++l) { |
474 auto missing_frame_it = missing_frames_for_layer_[l].lower_bound(ref_pid); | 470 auto missing_frame_it = missing_frames_for_layer_[l].lower_bound(ref_pid); |
475 if (missing_frame_it != missing_frames_for_layer_[l].end() && | 471 if (missing_frame_it != missing_frames_for_layer_[l].end() && |
476 AheadOf<uint16_t, kPicIdLength>(picture_id, *missing_frame_it)) { | 472 AheadOf<uint16_t, kPicIdLength>(picture_id, *missing_frame_it)) { |
477 return true; | 473 return true; |
478 } | 474 } |
479 } | 475 } |
480 } | 476 } |
481 return false; | 477 return false; |
482 } | 478 } |
483 | 479 |
484 void RtpFrameReferenceFinder::FrameReceivedVp9(uint16_t picture_id, | 480 void RtpFrameReferenceFinder::FrameReceivedVp9(uint16_t picture_id, |
485 const GofInfoVP9& gof) { | 481 GofInfo* info) { |
486 RTC_DCHECK_NE(-1, last_picture_id_); | 482 int last_picture_id = info->last_picture_id; |
487 | 483 |
488 // If there is a gap, find which temporal layer the missing frames | 484 // If there is a gap, find which temporal layer the missing frames |
489 // belong to and add the frame as missing for that temporal layer. | 485 // belong to and add the frame as missing for that temporal layer. |
490 // Otherwise, remove this frame from the set of missing frames. | 486 // Otherwise, remove this frame from the set of missing frames. |
491 if (AheadOf<uint16_t, kPicIdLength>(picture_id, last_picture_id_)) { | 487 if (AheadOf<uint16_t, kPicIdLength>(picture_id, last_picture_id)) { |
492 size_t diff = | 488 size_t diff = ForwardDiff<uint16_t, kPicIdLength>(info->gof->pid_start, |
493 ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, last_picture_id_); | 489 last_picture_id); |
494 size_t gof_idx = diff % gof.num_frames_in_gof; | 490 size_t gof_idx = diff % info->gof->num_frames_in_gof; |
495 | 491 |
496 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | 492 last_picture_id = Add<kPicIdLength>(last_picture_id, 1); |
497 while (last_picture_id_ != picture_id) { | 493 while (last_picture_id != picture_id) { |
498 ++gof_idx; | 494 ++gof_idx; |
499 RTC_DCHECK_NE(0ul, gof_idx % gof.num_frames_in_gof); | 495 RTC_DCHECK_NE(0ul, gof_idx % info->gof->num_frames_in_gof); |
500 size_t temporal_idx = gof.temporal_idx[gof_idx]; | 496 size_t temporal_idx = info->gof->temporal_idx[gof_idx]; |
501 missing_frames_for_layer_[temporal_idx].insert(last_picture_id_); | 497 missing_frames_for_layer_[temporal_idx].insert(last_picture_id); |
502 last_picture_id_ = Add<kPicIdLength>(last_picture_id_, 1); | 498 last_picture_id = Add<kPicIdLength>(last_picture_id, 1); |
503 } | 499 } |
| 500 info->last_picture_id = last_picture_id; |
504 } else { | 501 } else { |
505 size_t diff = | 502 size_t diff = |
506 ForwardDiff<uint16_t, kPicIdLength>(gof.pid_start, picture_id); | 503 ForwardDiff<uint16_t, kPicIdLength>(info->gof->pid_start, picture_id); |
507 size_t gof_idx = diff % gof.num_frames_in_gof; | 504 size_t gof_idx = diff % info->gof->num_frames_in_gof; |
508 size_t temporal_idx = gof.temporal_idx[gof_idx]; | 505 size_t temporal_idx = info->gof->temporal_idx[gof_idx]; |
509 missing_frames_for_layer_[temporal_idx].erase(picture_id); | 506 missing_frames_for_layer_[temporal_idx].erase(picture_id); |
510 } | 507 } |
511 } | 508 } |
512 | 509 |
513 bool RtpFrameReferenceFinder::UpSwitchInIntervalVp9(uint16_t picture_id, | 510 bool RtpFrameReferenceFinder::UpSwitchInIntervalVp9(uint16_t picture_id, |
514 uint8_t temporal_idx, | 511 uint8_t temporal_idx, |
515 uint16_t pid_ref) { | 512 uint16_t pid_ref) { |
516 for (auto up_switch_it = up_switch_.upper_bound(pid_ref); | 513 for (auto up_switch_it = up_switch_.upper_bound(pid_ref); |
517 up_switch_it != up_switch_.end() && | 514 up_switch_it != up_switch_.end() && |
518 AheadOf<uint16_t, kPicIdLength>(picture_id, up_switch_it->first); | 515 AheadOf<uint16_t, kPicIdLength>(picture_id, up_switch_it->first); |
(...skipping 24 matching lines...) Expand all Loading... |
543 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) | 540 if (AheadOf<uint16_t, kPicIdLength>(picture_id, unwrap_truncated)) |
544 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); | 541 last_unwrap_ = Add<1 << 16>(last_unwrap_, diff); |
545 else | 542 else |
546 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); | 543 last_unwrap_ = Subtract<1 << 16>(last_unwrap_, diff); |
547 | 544 |
548 return last_unwrap_; | 545 return last_unwrap_; |
549 } | 546 } |
550 | 547 |
551 } // namespace video_coding | 548 } // namespace video_coding |
552 } // namespace webrtc | 549 } // namespace webrtc |
OLD | NEW |