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

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

Issue 2127073002: Bugfix for Vp9 GOF and missing frames. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Better unittest describing the bug fixed. Created 4 years, 5 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
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/rtp_frame_reference_finder.h ('k') | webrtc/modules/video_coding/video_packet_buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698