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