Always unwrap VP9 TL0PicIdx forward if the frame is newer.
Bug: webrtc:12979 Change-Id: Idcc14f8f61b04f9eb194b55ffa40fb95319a881c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/226463 Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34513}
This commit is contained in:
parent
9f2a20f434
commit
dbab1be1d1
@ -77,8 +77,21 @@ RtpVp9RefFinder::FrameDecision RtpVp9RefFinder::ManageFrameInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
GofInfo* info;
|
GofInfo* info;
|
||||||
int64_t unwrapped_tl0 =
|
|
||||||
tl0_unwrapper_.Unwrap(codec_header.tl0_pic_idx & 0xFF);
|
// The VP9 `tl0_pic_idx` is 8 bits and therefor wraps often. In the case of
|
||||||
|
// packet loss the next received frame could have a `tl0_pic_idx` that looks
|
||||||
|
// older than the previously received frame. Always wrap forward if |frame| is
|
||||||
|
// newer in RTP packet sequence number order.
|
||||||
|
int64_t unwrapped_tl0;
|
||||||
|
auto tl0_it = gof_info_.rbegin();
|
||||||
|
if (tl0_it != gof_info_.rend() &&
|
||||||
|
AheadOf(frame->last_seq_num(), tl0_it->second.last_seq_num)) {
|
||||||
|
unwrapped_tl0 =
|
||||||
|
tl0_unwrapper_.UnwrapForward(codec_header.tl0_pic_idx & 0xFF);
|
||||||
|
} else {
|
||||||
|
unwrapped_tl0 = tl0_unwrapper_.Unwrap(codec_header.tl0_pic_idx & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
if (codec_header.ss_data_available) {
|
if (codec_header.ss_data_available) {
|
||||||
if (codec_header.temporal_idx != 0) {
|
if (codec_header.temporal_idx != 0) {
|
||||||
RTC_LOG(LS_WARNING) << "Received scalability structure on a non base "
|
RTC_LOG(LS_WARNING) << "Received scalability structure on a non base "
|
||||||
@ -104,9 +117,9 @@ RtpVp9RefFinder::FrameDecision RtpVp9RefFinder::ManageFrameInternal(
|
|||||||
current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1);
|
current_ss_idx_ = Add<kMaxGofSaved>(current_ss_idx_, 1);
|
||||||
scalability_structures_[current_ss_idx_] = gof;
|
scalability_structures_[current_ss_idx_] = gof;
|
||||||
scalability_structures_[current_ss_idx_].pid_start = frame->Id();
|
scalability_structures_[current_ss_idx_].pid_start = frame->Id();
|
||||||
gof_info_.emplace(
|
gof_info_.emplace(unwrapped_tl0,
|
||||||
unwrapped_tl0,
|
GofInfo(&scalability_structures_[current_ss_idx_],
|
||||||
GofInfo(&scalability_structures_[current_ss_idx_], frame->Id()));
|
frame->Id(), frame->last_seq_num()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto gof_info_it = gof_info_.find(unwrapped_tl0);
|
const auto gof_info_it = gof_info_.find(unwrapped_tl0);
|
||||||
@ -147,7 +160,8 @@ RtpVp9RefFinder::FrameDecision RtpVp9RefFinder::ManageFrameInternal(
|
|||||||
if (codec_header.temporal_idx == 0) {
|
if (codec_header.temporal_idx == 0) {
|
||||||
gof_info_it = gof_info_
|
gof_info_it = gof_info_
|
||||||
.emplace(unwrapped_tl0,
|
.emplace(unwrapped_tl0,
|
||||||
GofInfo(gof_info_it->second.gof, frame->Id()))
|
GofInfo(gof_info_it->second.gof, frame->Id(),
|
||||||
|
frame->last_seq_num()))
|
||||||
.first;
|
.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,10 +42,13 @@ class RtpVp9RefFinder {
|
|||||||
enum FrameDecision { kStash, kHandOff, kDrop };
|
enum FrameDecision { kStash, kHandOff, kDrop };
|
||||||
|
|
||||||
struct GofInfo {
|
struct GofInfo {
|
||||||
GofInfo(GofInfoVP9* gof, uint16_t last_picture_id)
|
GofInfo(GofInfoVP9* gof, uint16_t last_picture_id, uint16_t last_seq_num)
|
||||||
: gof(gof), last_picture_id(last_picture_id) {}
|
: gof(gof),
|
||||||
|
last_picture_id(last_picture_id),
|
||||||
|
last_seq_num(last_seq_num) {}
|
||||||
GofInfoVP9* gof;
|
GofInfoVP9* gof;
|
||||||
uint16_t last_picture_id;
|
uint16_t last_picture_id;
|
||||||
|
uint16_t last_seq_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
FrameDecision ManageFrameInternal(RtpFrameObject* frame);
|
FrameDecision ManageFrameInternal(RtpFrameObject* frame);
|
||||||
|
|||||||
@ -23,6 +23,7 @@ using ::testing::Matches;
|
|||||||
using ::testing::MatchResultListener;
|
using ::testing::MatchResultListener;
|
||||||
using ::testing::Pointee;
|
using ::testing::Pointee;
|
||||||
using ::testing::Property;
|
using ::testing::Property;
|
||||||
|
using ::testing::SizeIs;
|
||||||
using ::testing::UnorderedElementsAreArray;
|
using ::testing::UnorderedElementsAreArray;
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -661,6 +662,24 @@ TEST_F(RtpVp9RefFinderTest, GofTl0Jump) {
|
|||||||
Insert(Frame().Pid(1).SidAndTid(0, 0).Tl0(0).Gof(&ss));
|
Insert(Frame().Pid(1).SidAndTid(0, 0).Tl0(0).Gof(&ss));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpVp9RefFinderTest, DontDiscardNewerFramesWithWrappedTl0) {
|
||||||
|
GofInfoVP9 ss;
|
||||||
|
ss.SetGofInfoVP9(kTemporalStructureMode1);
|
||||||
|
|
||||||
|
Insert(
|
||||||
|
Frame().Pid(0).SidAndTid(0, 0).Tl0(0).SeqNum(0, 0).AsKeyFrame().Gof(&ss));
|
||||||
|
// ... 254 frames are lost ...
|
||||||
|
Insert(Frame()
|
||||||
|
.Pid(255)
|
||||||
|
.SidAndTid(0, 0)
|
||||||
|
.Tl0(255)
|
||||||
|
.SeqNum(255, 255)
|
||||||
|
.AsKeyFrame()
|
||||||
|
.Gof(&ss));
|
||||||
|
|
||||||
|
EXPECT_THAT(frames_, SizeIs(2));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(RtpVp9RefFinderTest, GofTidTooHigh) {
|
TEST_F(RtpVp9RefFinderTest, GofTidTooHigh) {
|
||||||
const int kMaxTemporalLayers = 5;
|
const int kMaxTemporalLayers = 5;
|
||||||
GofInfoVP9 ss;
|
GofInfoVP9 ss;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user