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