blob: 13e1fe38aa36988a2ba18c78d4888d9cfe77587e [file] [log] [blame]
philipel02447bc2016-05-13 06:01:03 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/rtp_frame_reference_finder.h"
philipel02447bc2016-05-13 06:01:03 -070012
philipel4e702162020-11-27 17:56:37 +010013#include <utility>
philipel02447bc2016-05-13 06:01:03 -070014
philipel4e702162020-11-27 17:56:37 +010015#include "absl/types/variant.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/video_coding/frame_object.h"
philipel4e702162020-11-27 17:56:37 +010017#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"
philipel02447bc2016-05-13 06:01:03 -070022
23namespace webrtc {
24namespace video_coding {
philipel4e702162020-11-27 17:56:37 +010025namespace internal {
26class RtpFrameReferenceFinderImpl {
27 public:
28 RtpFrameReferenceFinderImpl() = default;
29
30 RtpFrameReferenceFinder::ReturnVector ManageFrame(
31 std::unique_ptr<RtpFrameObject> frame);
32 RtpFrameReferenceFinder::ReturnVector PaddingReceived(uint16_t seq_num);
33 void ClearTo(uint16_t seq_num);
34
35 private:
36 using RefFinder = absl::variant<absl::monostate,
37 RtpGenericFrameRefFinder,
38 RtpFrameIdOnlyRefFinder,
39 RtpSeqNumOnlyRefFinder,
40 RtpVp8RefFinder,
41 RtpVp9RefFinder>;
42
43 template <typename T>
44 T& GetRefFinderAs();
45 RefFinder ref_finder_;
46};
47
48RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinderImpl::ManageFrame(
49 std::unique_ptr<RtpFrameObject> frame) {
50 const RTPVideoHeader& video_header = frame->GetRtpVideoHeader();
51
52 if (video_header.generic.has_value()) {
53 return GetRefFinderAs<RtpGenericFrameRefFinder>().ManageFrame(
54 std::move(frame), *video_header.generic);
55 }
56
57 switch (frame->codec_type()) {
58 case kVideoCodecVP8: {
59 const RTPVideoHeaderVP8& vp8_header =
60 absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
61
62 if (vp8_header.temporalIdx == kNoTemporalIdx ||
63 vp8_header.tl0PicIdx == kNoTl0PicIdx) {
64 if (vp8_header.pictureId == kNoPictureId) {
65 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
66 std::move(frame));
67 }
68
69 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame(
70 std::move(frame), vp8_header.pictureId);
71 }
72
73 return GetRefFinderAs<RtpVp8RefFinder>().ManageFrame(std::move(frame));
74 }
75 case kVideoCodecVP9: {
76 const RTPVideoHeaderVP9& vp9_header =
77 absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
78
79 if (vp9_header.temporal_idx == kNoTemporalIdx) {
80 if (vp9_header.picture_id == kNoPictureId) {
81 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
82 std::move(frame));
83 }
84
85 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame(
86 std::move(frame), vp9_header.picture_id);
87 }
88
89 return GetRefFinderAs<RtpVp9RefFinder>().ManageFrame(std::move(frame));
90 }
91 case kVideoCodecH264: {
92 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
93 std::move(frame));
94 }
95 case kVideoCodecGeneric: {
96 if (auto* generic_header = absl::get_if<RTPVideoHeaderLegacyGeneric>(
97 &video_header.video_type_header)) {
98 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame(
99 std::move(frame), generic_header->picture_id);
100 }
101
102 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
103 std::move(frame));
104 }
105 default: {
106 RTC_CHECK_NOTREACHED();
107 }
108 }
109}
110
111RtpFrameReferenceFinder::ReturnVector
112RtpFrameReferenceFinderImpl::PaddingReceived(uint16_t seq_num) {
113 if (auto* ref_finder = absl::get_if<RtpSeqNumOnlyRefFinder>(&ref_finder_)) {
114 return ref_finder->PaddingReceived(seq_num);
115 }
116 return {};
117}
118
119void RtpFrameReferenceFinderImpl::ClearTo(uint16_t seq_num) {
120 struct ClearToVisitor {
121 void operator()(absl::monostate& ref_finder) {}
122 void operator()(RtpGenericFrameRefFinder& ref_finder) {}
123 void operator()(RtpFrameIdOnlyRefFinder& ref_finder) {}
124 void operator()(RtpSeqNumOnlyRefFinder& ref_finder) {
125 ref_finder.ClearTo(seq_num);
126 }
127 void operator()(RtpVp8RefFinder& ref_finder) {
128 ref_finder.ClearTo(seq_num);
129 }
130 void operator()(RtpVp9RefFinder& ref_finder) {
131 ref_finder.ClearTo(seq_num);
132 }
133 uint16_t seq_num;
134 };
135
136 absl::visit(ClearToVisitor{seq_num}, ref_finder_);
137}
138
139template <typename T>
140T& RtpFrameReferenceFinderImpl::GetRefFinderAs() {
141 if (auto* ref_finder = absl::get_if<T>(&ref_finder_)) {
142 return *ref_finder;
143 }
144 return ref_finder_.emplace<T>();
145}
146
147} // namespace internal
philipel02447bc2016-05-13 06:01:03 -0700148
149RtpFrameReferenceFinder::RtpFrameReferenceFinder(
150 OnCompleteFrameCallback* frame_callback)
philipel7acc4a42019-09-26 11:25:52 +0200151 : RtpFrameReferenceFinder(frame_callback, 0) {}
152
153RtpFrameReferenceFinder::RtpFrameReferenceFinder(
154 OnCompleteFrameCallback* frame_callback,
155 int64_t picture_id_offset)
philipel4e702162020-11-27 17:56:37 +0100156 : picture_id_offset_(picture_id_offset),
philipel7acc4a42019-09-26 11:25:52 +0200157 frame_callback_(frame_callback),
philipel4e702162020-11-27 17:56:37 +0100158 impl_(std::make_unique<internal::RtpFrameReferenceFinderImpl>()) {}
philipel02447bc2016-05-13 06:01:03 -0700159
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200160RtpFrameReferenceFinder::~RtpFrameReferenceFinder() = default;
161
philipel02447bc2016-05-13 06:01:03 -0700162void RtpFrameReferenceFinder::ManageFrame(
163 std::unique_ptr<RtpFrameObject> frame) {
philipel463d3012016-09-09 03:32:44 -0700164 // If we have cleared past this frame, drop it.
165 if (cleared_to_seq_num_ != -1 &&
166 AheadOf<uint16_t>(cleared_to_seq_num_, frame->first_seq_num())) {
167 return;
168 }
philipel4e702162020-11-27 17:56:37 +0100169 HandOffFrames(impl_->ManageFrame(std::move(frame)));
philipel02447bc2016-05-13 06:01:03 -0700170}
171
philipel9b2ce6b2016-07-05 05:04:46 -0700172void RtpFrameReferenceFinder::PaddingReceived(uint16_t seq_num) {
philipel4e702162020-11-27 17:56:37 +0100173 HandOffFrames(impl_->PaddingReceived(seq_num));
philipel9b2ce6b2016-07-05 05:04:46 -0700174}
175
philipel463d3012016-09-09 03:32:44 -0700176void RtpFrameReferenceFinder::ClearTo(uint16_t seq_num) {
philipel463d3012016-09-09 03:32:44 -0700177 cleared_to_seq_num_ = seq_num;
philipel4e702162020-11-27 17:56:37 +0100178 impl_->ClearTo(seq_num);
philipel463d3012016-09-09 03:32:44 -0700179}
180
philipel4e702162020-11-27 17:56:37 +0100181void RtpFrameReferenceFinder::HandOffFrames(ReturnVector frames) {
182 for (auto& frame : frames) {
183 frame->id.picture_id += picture_id_offset_;
philipel02447bc2016-05-13 06:01:03 -0700184 for (size_t i = 0; i < frame->num_references; ++i) {
philipel4e702162020-11-27 17:56:37 +0100185 frame->references[i] += picture_id_offset_;
philipel02447bc2016-05-13 06:01:03 -0700186 }
187
philipel4e702162020-11-27 17:56:37 +0100188 frame_callback_->OnCompleteFrame(std::move(frame));
philipel02447bc2016-05-13 06:01:03 -0700189 }
philipel02447bc2016-05-13 06:01:03 -0700190}
191
philipel02447bc2016-05-13 06:01:03 -0700192} // namespace video_coding
193} // namespace webrtc