Unwrap TL0 pic index to avoid having to work with a wrapped number.
This is to avoid clearing the |gof_info_| map when there are jumps in the tl0 pic index. Bug: chromium:855211 Change-Id: I762557070d65b3c535cb9a49498975bcd9c2c485 Reviewed-on: https://webrtc-review.googlesource.com/86943 Reviewed-by: Björn Terelius <terelius@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23872}
This commit is contained in:
@ -272,8 +272,10 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
|
||||
} while (last_picture_id_ != frame->id.picture_id);
|
||||
}
|
||||
|
||||
int64_t unwrapped_tl0 = tl0_unwrapper_.Unwrap(codec_header.tl0PicIdx);
|
||||
|
||||
// Clean up info for base layers that are too old.
|
||||
uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - kMaxLayerInfo;
|
||||
int64_t old_tl0_pic_idx = unwrapped_tl0 - kMaxLayerInfo;
|
||||
auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx);
|
||||
layer_info_.erase(layer_info_.begin(), clean_layer_info_to);
|
||||
|
||||
@ -286,14 +288,13 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
|
||||
|
||||
if (frame->frame_type() == kVideoFrameKey) {
|
||||
frame->num_references = 0;
|
||||
layer_info_[codec_header.tl0PicIdx].fill(-1);
|
||||
UpdateLayerInfoVp8(frame, codec_header);
|
||||
layer_info_[unwrapped_tl0].fill(-1);
|
||||
UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
|
||||
return kHandOff;
|
||||
}
|
||||
|
||||
auto layer_info_it = layer_info_.find(codec_header.temporalIdx == 0
|
||||
? codec_header.tl0PicIdx - 1
|
||||
: codec_header.tl0PicIdx);
|
||||
auto layer_info_it = layer_info_.find(
|
||||
codec_header.temporalIdx == 0 ? unwrapped_tl0 - 1 : unwrapped_tl0);
|
||||
|
||||
// If we don't have the base layer frame yet, stash this frame.
|
||||
if (layer_info_it == layer_info_.end())
|
||||
@ -304,11 +305,10 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
|
||||
// base layer frame.
|
||||
if (codec_header.temporalIdx == 0) {
|
||||
layer_info_it =
|
||||
layer_info_.emplace(codec_header.tl0PicIdx, layer_info_it->second)
|
||||
.first;
|
||||
layer_info_.emplace(unwrapped_tl0, layer_info_it->second).first;
|
||||
frame->num_references = 1;
|
||||
frame->references[0] = layer_info_it->second[0];
|
||||
UpdateLayerInfoVp8(frame, codec_header);
|
||||
UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
|
||||
return kHandOff;
|
||||
}
|
||||
|
||||
@ -317,7 +317,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
|
||||
frame->num_references = 1;
|
||||
frame->references[0] = layer_info_it->second[0];
|
||||
|
||||
UpdateLayerInfoVp8(frame, codec_header);
|
||||
UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
|
||||
return kHandOff;
|
||||
}
|
||||
|
||||
@ -361,30 +361,28 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
|
||||
frame->references[layer] = layer_info_it->second[layer];
|
||||
}
|
||||
|
||||
UpdateLayerInfoVp8(frame, codec_header);
|
||||
UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
|
||||
return kHandOff;
|
||||
}
|
||||
|
||||
void RtpFrameReferenceFinder::UpdateLayerInfoVp8(
|
||||
RtpFrameObject* frame,
|
||||
const RTPVideoHeaderVP8& codec_header) {
|
||||
uint8_t tl0_pic_idx = codec_header.tl0PicIdx;
|
||||
uint8_t temporal_index = codec_header.temporalIdx;
|
||||
auto layer_info_it = layer_info_.find(tl0_pic_idx);
|
||||
void RtpFrameReferenceFinder::UpdateLayerInfoVp8(RtpFrameObject* frame,
|
||||
int64_t unwrapped_tl0,
|
||||
uint8_t temporal_idx) {
|
||||
auto layer_info_it = layer_info_.find(unwrapped_tl0);
|
||||
|
||||
// Update this layer info and newer.
|
||||
while (layer_info_it != layer_info_.end()) {
|
||||
if (layer_info_it->second[temporal_index] != -1 &&
|
||||
AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_index],
|
||||
if (layer_info_it->second[temporal_idx] != -1 &&
|
||||
AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_idx],
|
||||
frame->id.picture_id)) {
|
||||
// The frame was not newer, then no subsequent layer info have to be
|
||||
// update.
|
||||
break;
|
||||
}
|
||||
|
||||
layer_info_it->second[codec_header.temporalIdx] = frame->id.picture_id;
|
||||
++tl0_pic_idx;
|
||||
layer_info_it = layer_info_.find(tl0_pic_idx);
|
||||
layer_info_it->second[temporal_idx] = frame->id.picture_id;
|
||||
++unwrapped_tl0;
|
||||
layer_info_it = layer_info_.find(unwrapped_tl0);
|
||||
}
|
||||
not_yet_received_frames_.erase(frame->id.picture_id);
|
||||
|
||||
@ -403,7 +401,8 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
|
||||
const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9;
|
||||
|
||||
if (codec_header.picture_id == kNoPictureId ||
|
||||
codec_header.temporal_idx == kNoTemporalIdx) {
|
||||
codec_header.temporal_idx == kNoTemporalIdx ||
|
||||
codec_header.tl0_pic_idx == kNoTl0PicIdx) {
|
||||
return ManageFrameGeneric(std::move(frame), codec_header.picture_id);
|
||||
}
|
||||
|
||||
@ -429,6 +428,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
|
||||
}
|
||||
|
||||
GofInfo* info;
|
||||
int64_t unwrapped_tl0 = tl0_unwrapper_.Unwrap(codec_header.tl0_pic_idx);
|
||||
if (codec_header.ss_data_available) {
|
||||
if (codec_header.temporal_idx != 0) {
|
||||
RTC_LOG(LS_WARNING) << "Received scalability structure on a non base "
|
||||
@ -442,12 +442,12 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
|
||||
|
||||
scalability_structures_[current_ss_idx_] = codec_header.gof;
|
||||
scalability_structures_[current_ss_idx_].pid_start = frame->id.picture_id;
|
||||
gof_info_.emplace(codec_header.tl0_pic_idx,
|
||||
gof_info_.emplace(unwrapped_tl0,
|
||||
GofInfo(&scalability_structures_[current_ss_idx_],
|
||||
frame->id.picture_id));
|
||||
}
|
||||
|
||||
const auto gof_info_it = gof_info_.find(codec_header.tl0_pic_idx);
|
||||
const auto gof_info_it = gof_info_.find(unwrapped_tl0);
|
||||
if (gof_info_it == gof_info_.end())
|
||||
return kStash;
|
||||
|
||||
@ -465,27 +465,25 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
|
||||
return kDrop;
|
||||
}
|
||||
|
||||
auto gof_info_it = gof_info_.find((codec_header.temporal_idx == 0)
|
||||
? codec_header.tl0_pic_idx - 1
|
||||
: codec_header.tl0_pic_idx);
|
||||
auto gof_info_it = gof_info_.find(
|
||||
(codec_header.temporal_idx == 0) ? unwrapped_tl0 - 1 : unwrapped_tl0);
|
||||
|
||||
// Gof info for this frame is not available yet, stash this frame.
|
||||
if (gof_info_it == gof_info_.end())
|
||||
return kStash;
|
||||
|
||||
if (codec_header.temporal_idx == 0) {
|
||||
gof_info_it =
|
||||
gof_info_
|
||||
.emplace(codec_header.tl0_pic_idx,
|
||||
GofInfo(gof_info_it->second.gof, frame->id.picture_id))
|
||||
.first;
|
||||
gof_info_it = gof_info_
|
||||
.emplace(unwrapped_tl0, GofInfo(gof_info_it->second.gof,
|
||||
frame->id.picture_id))
|
||||
.first;
|
||||
}
|
||||
|
||||
info = &gof_info_it->second;
|
||||
}
|
||||
|
||||
// Clean up info for base layers that are too old.
|
||||
uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved;
|
||||
int64_t old_tl0_pic_idx = unwrapped_tl0 - kMaxGofSaved;
|
||||
auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx);
|
||||
gof_info_.erase(gof_info_.begin(), clean_gof_info_to);
|
||||
|
||||
|
||||
@ -100,7 +100,8 @@ class RtpFrameReferenceFinder {
|
||||
// Updates necessary layer info state used to determine frame references for
|
||||
// Vp8.
|
||||
void UpdateLayerInfoVp8(RtpFrameObject* frame,
|
||||
const RTPVideoHeaderVP8& codec_header)
|
||||
int64_t unwrapped_tl0,
|
||||
uint8_t temporal_idx)
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
// Find references for Vp9 frames
|
||||
@ -162,11 +163,9 @@ class RtpFrameReferenceFinder {
|
||||
RTC_GUARDED_BY(crit_);
|
||||
|
||||
// Holds the information about the last completed frame for a given temporal
|
||||
// layer given a Tl0 picture index.
|
||||
std::map<uint8_t,
|
||||
std::array<int16_t, kMaxTemporalLayers>,
|
||||
DescendingSeqNumComp<uint8_t>>
|
||||
layer_info_ RTC_GUARDED_BY(crit_);
|
||||
// layer given an unwrapped Tl0 picture index.
|
||||
std::map<int64_t, std::array<int16_t, kMaxTemporalLayers>> layer_info_
|
||||
RTC_GUARDED_BY(crit_);
|
||||
|
||||
// Where the current scalability structure is in the
|
||||
// |scalability_structures_| array.
|
||||
@ -176,9 +175,8 @@ class RtpFrameReferenceFinder {
|
||||
std::array<GofInfoVP9, kMaxGofSaved> scalability_structures_
|
||||
RTC_GUARDED_BY(crit_);
|
||||
|
||||
// Holds the the Gof information for a given TL0 picture index.
|
||||
std::map<uint8_t, GofInfo, DescendingSeqNumComp<uint8_t>> gof_info_
|
||||
RTC_GUARDED_BY(crit_);
|
||||
// Holds the the Gof information for a given unwrapped TL0 picture index.
|
||||
std::map<int64_t, GofInfo> gof_info_ RTC_GUARDED_BY(crit_);
|
||||
|
||||
// Keep track of which picture id and which temporal layer that had the
|
||||
// up switch flag set.
|
||||
@ -204,6 +202,8 @@ class RtpFrameReferenceFinder {
|
||||
// Unwrapper used to unwrap VP8/VP9 streams which have their picture id
|
||||
// specified.
|
||||
SeqNumUnwrapper<uint16_t, kPicIdLength> unwrapper_ RTC_GUARDED_BY(crit_);
|
||||
|
||||
SeqNumUnwrapper<uint8_t> tl0_unwrapper_ RTC_GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
} // namespace video_coding
|
||||
|
||||
@ -1331,6 +1331,16 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9GofPidJump) {
|
||||
InsertVp9Gof(sn + 1, sn + 1, false, pid + 1000, 0, 0, 1);
|
||||
}
|
||||
|
||||
TEST_F(TestRtpFrameReferenceFinder, Vp9GofTl0Jump) {
|
||||
uint16_t pid = Rand();
|
||||
uint16_t sn = Rand();
|
||||
GofInfoVP9 ss;
|
||||
ss.SetGofInfoVP9(kTemporalStructureMode3);
|
||||
|
||||
InsertVp9Gof(sn, sn, true, pid + 0, 0, 0, 125, true, &ss);
|
||||
InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 0, 0, false, &ss);
|
||||
}
|
||||
|
||||
TEST_F(TestRtpFrameReferenceFinder, Vp9GofTidTooHigh) {
|
||||
// Same as RtpFrameReferenceFinder::kMaxTemporalLayers.
|
||||
const int kMaxTemporalLayers = 5;
|
||||
|
||||
Reference in New Issue
Block a user