rtp_frame_reference_finder.cc (6615B)
1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/video_coding/rtp_frame_reference_finder.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <memory> 16 #include <utility> 17 #include <variant> 18 19 #include "api/video/video_codec_type.h" 20 #include "modules/rtp_rtcp/source/frame_object.h" 21 #include "modules/rtp_rtcp/source/rtp_video_header.h" 22 #include "modules/video_coding/codecs/interface/common_constants.h" 23 #include "modules/video_coding/codecs/vp8/include/vp8_globals.h" 24 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" 25 #include "modules/video_coding/rtp_frame_id_only_ref_finder.h" 26 #include "modules/video_coding/rtp_generic_ref_finder.h" 27 #include "modules/video_coding/rtp_seq_num_only_ref_finder.h" 28 #include "modules/video_coding/rtp_vp8_ref_finder.h" 29 #include "modules/video_coding/rtp_vp9_ref_finder.h" 30 #include "rtc_base/numerics/sequence_number_util.h" 31 32 namespace webrtc { 33 namespace internal { 34 class RtpFrameReferenceFinderImpl { 35 public: 36 RtpFrameReferenceFinderImpl() = default; 37 38 RtpFrameReferenceFinder::ReturnVector ManageFrame( 39 std::unique_ptr<RtpFrameObject> frame); 40 RtpFrameReferenceFinder::ReturnVector PaddingReceived(uint16_t seq_num); 41 void ClearTo(uint16_t seq_num); 42 43 private: 44 using RefFinder = std::variant<std::monostate, 45 RtpGenericFrameRefFinder, 46 RtpFrameIdOnlyRefFinder, 47 RtpSeqNumOnlyRefFinder, 48 RtpVp8RefFinder, 49 RtpVp9RefFinder>; 50 51 template <typename T> 52 T& GetRefFinderAs(); 53 RefFinder ref_finder_; 54 }; 55 56 RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinderImpl::ManageFrame( 57 std::unique_ptr<RtpFrameObject> frame) { 58 const RTPVideoHeader& video_header = frame->GetRtpVideoHeader(); 59 60 if (video_header.generic.has_value()) { 61 return GetRefFinderAs<RtpGenericFrameRefFinder>().ManageFrame( 62 std::move(frame), *video_header.generic); 63 } 64 65 switch (frame->codec_type()) { 66 case kVideoCodecVP8: { 67 const RTPVideoHeaderVP8& vp8_header = 68 std::get<RTPVideoHeaderVP8>(video_header.video_type_header); 69 70 if (vp8_header.temporalIdx == kNoTemporalIdx || 71 vp8_header.tl0PicIdx == kNoTl0PicIdx) { 72 if (vp8_header.pictureId == kNoPictureId) { 73 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( 74 std::move(frame)); 75 } 76 77 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( 78 std::move(frame), vp8_header.pictureId); 79 } 80 81 return GetRefFinderAs<RtpVp8RefFinder>().ManageFrame(std::move(frame)); 82 } 83 case kVideoCodecVP9: { 84 const RTPVideoHeaderVP9& vp9_header = 85 std::get<RTPVideoHeaderVP9>(video_header.video_type_header); 86 87 if (vp9_header.temporal_idx == kNoTemporalIdx) { 88 if (vp9_header.picture_id == kNoPictureId) { 89 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( 90 std::move(frame)); 91 } 92 93 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( 94 std::move(frame), vp9_header.picture_id); 95 } 96 97 return GetRefFinderAs<RtpVp9RefFinder>().ManageFrame(std::move(frame)); 98 } 99 case kVideoCodecGeneric: { 100 if (auto* generic_header = std::get_if<RTPVideoHeaderLegacyGeneric>( 101 &video_header.video_type_header)) { 102 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame( 103 std::move(frame), generic_header->picture_id); 104 } 105 106 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( 107 std::move(frame)); 108 } 109 default: { 110 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame( 111 std::move(frame)); 112 } 113 } 114 } 115 116 RtpFrameReferenceFinder::ReturnVector 117 RtpFrameReferenceFinderImpl::PaddingReceived(uint16_t seq_num) { 118 if (auto* ref_finder = std::get_if<RtpSeqNumOnlyRefFinder>(&ref_finder_)) { 119 return ref_finder->PaddingReceived(seq_num); 120 } 121 return {}; 122 } 123 124 void RtpFrameReferenceFinderImpl::ClearTo(uint16_t seq_num) { 125 struct ClearToVisitor { 126 void operator()(std::monostate& /* ref_finder */) {} 127 void operator()(RtpGenericFrameRefFinder& /* ref_finder */) {} 128 void operator()(RtpFrameIdOnlyRefFinder& /* ref_finder */) {} 129 void operator()(RtpSeqNumOnlyRefFinder& ref_finder) { 130 ref_finder.ClearTo(seq_num); 131 } 132 void operator()(RtpVp8RefFinder& ref_finder) { 133 ref_finder.ClearTo(seq_num); 134 } 135 void operator()(RtpVp9RefFinder& ref_finder) { 136 ref_finder.ClearTo(seq_num); 137 } 138 uint16_t seq_num; 139 }; 140 141 std::visit(ClearToVisitor{seq_num}, ref_finder_); 142 } 143 144 template <typename T> 145 T& RtpFrameReferenceFinderImpl::GetRefFinderAs() { 146 if (auto* ref_finder = std::get_if<T>(&ref_finder_)) { 147 return *ref_finder; 148 } 149 return ref_finder_.emplace<T>(); 150 } 151 152 } // namespace internal 153 154 RtpFrameReferenceFinder::RtpFrameReferenceFinder() 155 : RtpFrameReferenceFinder(0) {} 156 157 RtpFrameReferenceFinder::RtpFrameReferenceFinder(int64_t picture_id_offset) 158 : picture_id_offset_(picture_id_offset), 159 impl_(std::make_unique<internal::RtpFrameReferenceFinderImpl>()) {} 160 161 RtpFrameReferenceFinder::~RtpFrameReferenceFinder() = default; 162 163 RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinder::ManageFrame( 164 std::unique_ptr<RtpFrameObject> frame) { 165 // If we have cleared past this frame, drop it. 166 if (cleared_to_seq_num_ != -1 && 167 AheadOf<uint16_t>(cleared_to_seq_num_, frame->first_seq_num())) { 168 return {}; 169 } 170 171 auto frames = impl_->ManageFrame(std::move(frame)); 172 AddPictureIdOffset(frames); 173 return frames; 174 } 175 176 RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinder::PaddingReceived( 177 uint16_t seq_num) { 178 auto frames = impl_->PaddingReceived(seq_num); 179 AddPictureIdOffset(frames); 180 return frames; 181 } 182 183 void RtpFrameReferenceFinder::ClearTo(uint16_t seq_num) { 184 cleared_to_seq_num_ = seq_num; 185 impl_->ClearTo(seq_num); 186 } 187 188 void RtpFrameReferenceFinder::AddPictureIdOffset(ReturnVector& frames) { 189 for (auto& frame : frames) { 190 frame->SetId(frame->Id() + picture_id_offset_); 191 for (size_t i = 0; i < frame->num_references; ++i) { 192 frame->references[i] += picture_id_offset_; 193 } 194 } 195 } 196 197 } // namespace webrtc