From 57ec685446399babd3c88ab30e20a62bcd9b8037 Mon Sep 17 00:00:00 2001 From: philipel Date: Tue, 3 Jul 2018 18:09:32 +0200 Subject: [PATCH] Unwrap TL0 pic index to avoid having to work with a wrapped number. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Commit-Queue: Philip Eliasson Cr-Commit-Position: refs/heads/master@{#23872} --- .../rtp_frame_reference_finder.cc | 66 +++++++++---------- .../video_coding/rtp_frame_reference_finder.h | 18 ++--- .../rtp_frame_reference_finder_unittest.cc | 10 +++ 3 files changed, 51 insertions(+), 43 deletions(-) diff --git a/modules/video_coding/rtp_frame_reference_finder.cc b/modules/video_coding/rtp_frame_reference_finder.cc index 396935cdbb..109d50638b 100644 --- a/modules/video_coding/rtp_frame_reference_finder.cc +++ b/modules/video_coding/rtp_frame_reference_finder.cc @@ -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(layer_info_it->second[temporal_index], + if (layer_info_it->second[temporal_idx] != -1 && + AheadOf(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); diff --git a/modules/video_coding/rtp_frame_reference_finder.h b/modules/video_coding/rtp_frame_reference_finder.h index f0344f163d..ceceeca8a3 100644 --- a/modules/video_coding/rtp_frame_reference_finder.h +++ b/modules/video_coding/rtp_frame_reference_finder.h @@ -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, - DescendingSeqNumComp> - layer_info_ RTC_GUARDED_BY(crit_); + // layer given an unwrapped Tl0 picture index. + std::map> 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 scalability_structures_ RTC_GUARDED_BY(crit_); - // Holds the the Gof information for a given TL0 picture index. - std::map> gof_info_ - RTC_GUARDED_BY(crit_); + // Holds the the Gof information for a given unwrapped TL0 picture index. + std::map 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 unwrapper_ RTC_GUARDED_BY(crit_); + + SeqNumUnwrapper tl0_unwrapper_ RTC_GUARDED_BY(crit_); }; } // namespace video_coding diff --git a/modules/video_coding/rtp_frame_reference_finder_unittest.cc b/modules/video_coding/rtp_frame_reference_finder_unittest.cc index 0d63a1dd57..83454eb418 100644 --- a/modules/video_coding/rtp_frame_reference_finder_unittest.cc +++ b/modules/video_coding/rtp_frame_reference_finder_unittest.cc @@ -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;