Iterate over all VP9 GoF `pid_diff`s to determine frame references. Currently `num_references` is decremented to skip a reference to a frame prior to an upswitch point, but this also modified the loop condition in such a way that we didn't end up looking at all the `pid_diff`s. Bug: none Change-Id: I89b9581ce86c09955723589851d3ce373c66a5b5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/475921 Commit-Queue: Philip Eliasson <philipel@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47816}
diff --git a/modules/video_coding/rtp_vp9_ref_finder.cc b/modules/video_coding/rtp_vp9_ref_finder.cc index 4f5969a..ab2345f 100644 --- a/modules/video_coding/rtp_vp9_ref_finder.cc +++ b/modules/video_coding/rtp_vp9_ref_finder.cc
@@ -205,18 +205,20 @@ } // Populate references according to the scalability structure. - frame->num_references = info->gof->num_ref_pics[gof_idx]; - for (size_t i = 0; i < frame->num_references; ++i) { - frame->references[i] = Subtract<kFrameIdLength>( + size_t num_references = 0; + for (size_t i = 0; i < info->gof->num_ref_pics[gof_idx]; ++i) { + int64_t reference = Subtract<kFrameIdLength>( frame->Id(), info->gof->pid_diff[gof_idx][i]); // If this is a reference to a frame earlier than the last up switch // point, then ignore this reference. if (UpSwitchInIntervalVp9(frame->Id(), codec_header.temporal_idx, - frame->references[i])) { - --frame->num_references; + reference)) { + continue; } + frame->references[num_references++] = reference; } + frame->num_references = num_references; } else { frame->num_references = 0; }
diff --git a/modules/video_coding/rtp_vp9_ref_finder_unittest.cc b/modules/video_coding/rtp_vp9_ref_finder_unittest.cc index 0ca1a3b..17ca806 100644 --- a/modules/video_coding/rtp_vp9_ref_finder_unittest.cc +++ b/modules/video_coding/rtp_vp9_ref_finder_unittest.cc
@@ -716,4 +716,35 @@ EXPECT_THAT(frames_, SizeIs(0)); } +TEST_F(RtpVp9RefFinderTest, GofUpSwitchMultipleRefs) { + GofInfoVP9 ss; + ss.num_frames_in_gof = 3; + + ss.temporal_idx[0] = 0; + ss.num_ref_pics[0] = 1; + ss.pid_diff[0][0] = 3; + + ss.temporal_idx[1] = 1; + ss.num_ref_pics[1] = 1; + ss.pid_diff[1][0] = 1; + + ss.temporal_idx[2] = 2; + ss.num_ref_pics[2] = 2; + ss.pid_diff[2][0] = 2; + ss.pid_diff[2][1] = 1; + + Insert(Frame().Pid(0).SidAndTid(0, 0).Tl0(0).AsKeyFrame().Gof(&ss)); + EXPECT_THAT(frames_, SizeIs(1)); + EXPECT_THAT(frames_, HasFrameWithIdAndRefs(0, {})); + Insert(Frame().Pid(1).SidAndTid(0, 1).Tl0(0).AsUpswitch()); + EXPECT_THAT(frames_, SizeIs(2)); + EXPECT_THAT(frames_, HasFrameWithIdAndRefs(5, {0})); + + // Since PID0 was prior to the upswitch frame (PID1), the reference from PID2 + // to PID0 should be removed. + Insert(Frame().Pid(2).SidAndTid(0, 2).Tl0(0)); + EXPECT_THAT(frames_, SizeIs(3)); + EXPECT_THAT(frames_, HasFrameWithIdAndRefs(10, {5})); +} + } // namespace webrtc