blob: 1a99fc2ba76fbe9fa5fc9ef60b3b9f0dd1767f19 [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 }
philipel4e702162020-11-27 17:56:37 +010091 case kVideoCodecGeneric: {
92 if (auto* generic_header = absl::get_if<RTPVideoHeaderLegacyGeneric>(
93 &video_header.video_type_header)) {
94 return GetRefFinderAs<RtpFrameIdOnlyRefFinder>().ManageFrame(
95 std::move(frame), generic_header->picture_id);
96 }
97
98 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
99 std::move(frame));
100 }
101 default: {
philipel39f09b42020-12-01 11:47:12 +0100102 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
103 std::move(frame));
philipel4e702162020-11-27 17:56:37 +0100104 }
105 }
106}
107
108RtpFrameReferenceFinder::ReturnVector
109RtpFrameReferenceFinderImpl::PaddingReceived(uint16_t seq_num) {
110 if (auto* ref_finder = absl::get_if<RtpSeqNumOnlyRefFinder>(&ref_finder_)) {
111 return ref_finder->PaddingReceived(seq_num);
112 }
113 return {};
114}
115
116void RtpFrameReferenceFinderImpl::ClearTo(uint16_t seq_num) {
117 struct ClearToVisitor {
118 void operator()(absl::monostate& ref_finder) {}
119 void operator()(RtpGenericFrameRefFinder& ref_finder) {}
120 void operator()(RtpFrameIdOnlyRefFinder& ref_finder) {}
121 void operator()(RtpSeqNumOnlyRefFinder& ref_finder) {
122 ref_finder.ClearTo(seq_num);
123 }
124 void operator()(RtpVp8RefFinder& ref_finder) {
125 ref_finder.ClearTo(seq_num);
126 }
127 void operator()(RtpVp9RefFinder& ref_finder) {
128 ref_finder.ClearTo(seq_num);
129 }
130 uint16_t seq_num;
131 };
132
133 absl::visit(ClearToVisitor{seq_num}, ref_finder_);
134}
135
136template <typename T>
137T& RtpFrameReferenceFinderImpl::GetRefFinderAs() {
138 if (auto* ref_finder = absl::get_if<T>(&ref_finder_)) {
139 return *ref_finder;
140 }
141 return ref_finder_.emplace<T>();
142}
143
144} // namespace internal
philipel02447bc2016-05-13 06:01:03 -0700145
146RtpFrameReferenceFinder::RtpFrameReferenceFinder(
147 OnCompleteFrameCallback* frame_callback)
philipel7acc4a42019-09-26 11:25:52 +0200148 : RtpFrameReferenceFinder(frame_callback, 0) {}
149
150RtpFrameReferenceFinder::RtpFrameReferenceFinder(
151 OnCompleteFrameCallback* frame_callback,
152 int64_t picture_id_offset)
philipel4e702162020-11-27 17:56:37 +0100153 : picture_id_offset_(picture_id_offset),
philipel7acc4a42019-09-26 11:25:52 +0200154 frame_callback_(frame_callback),
philipel4e702162020-11-27 17:56:37 +0100155 impl_(std::make_unique<internal::RtpFrameReferenceFinderImpl>()) {}
philipel02447bc2016-05-13 06:01:03 -0700156
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200157RtpFrameReferenceFinder::~RtpFrameReferenceFinder() = default;
158
philipel02447bc2016-05-13 06:01:03 -0700159void RtpFrameReferenceFinder::ManageFrame(
160 std::unique_ptr<RtpFrameObject> frame) {
philipel463d3012016-09-09 03:32:44 -0700161 // If we have cleared past this frame, drop it.
162 if (cleared_to_seq_num_ != -1 &&
163 AheadOf<uint16_t>(cleared_to_seq_num_, frame->first_seq_num())) {
164 return;
165 }
philipel4e702162020-11-27 17:56:37 +0100166 HandOffFrames(impl_->ManageFrame(std::move(frame)));
philipel02447bc2016-05-13 06:01:03 -0700167}
168
philipel9b2ce6b2016-07-05 05:04:46 -0700169void RtpFrameReferenceFinder::PaddingReceived(uint16_t seq_num) {
philipel4e702162020-11-27 17:56:37 +0100170 HandOffFrames(impl_->PaddingReceived(seq_num));
philipel9b2ce6b2016-07-05 05:04:46 -0700171}
172
philipel463d3012016-09-09 03:32:44 -0700173void RtpFrameReferenceFinder::ClearTo(uint16_t seq_num) {
philipel463d3012016-09-09 03:32:44 -0700174 cleared_to_seq_num_ = seq_num;
philipel4e702162020-11-27 17:56:37 +0100175 impl_->ClearTo(seq_num);
philipel463d3012016-09-09 03:32:44 -0700176}
177
philipel4e702162020-11-27 17:56:37 +0100178void RtpFrameReferenceFinder::HandOffFrames(ReturnVector frames) {
179 for (auto& frame : frames) {
philipel9aa9b8d2021-02-15 13:31:29 +0100180 frame->SetId(frame->Id() + picture_id_offset_);
philipel02447bc2016-05-13 06:01:03 -0700181 for (size_t i = 0; i < frame->num_references; ++i) {
philipel4e702162020-11-27 17:56:37 +0100182 frame->references[i] += picture_id_offset_;
philipel02447bc2016-05-13 06:01:03 -0700183 }
184
philipel4e702162020-11-27 17:56:37 +0100185 frame_callback_->OnCompleteFrame(std::move(frame));
philipel02447bc2016-05-13 06:01:03 -0700186 }
philipel02447bc2016-05-13 06:01:03 -0700187}
188
philipel02447bc2016-05-13 06:01:03 -0700189} // namespace video_coding
190} // namespace webrtc