blob: a060f8477735acf6764c3c24a85a81f4f88d1d6c [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 {
philipel4e702162020-11-27 17:56:37 +010024namespace internal {
25class RtpFrameReferenceFinderImpl {
26 public:
27 RtpFrameReferenceFinderImpl() = default;
28
29 RtpFrameReferenceFinder::ReturnVector ManageFrame(
philipelca188092021-03-23 12:00:49 +010030 std::unique_ptr<RtpFrameObject> frame);
philipel4e702162020-11-27 17:56:37 +010031 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
47RtpFrameReferenceFinder::ReturnVector RtpFrameReferenceFinderImpl::ManageFrame(
philipelca188092021-03-23 12:00:49 +010048 std::unique_ptr<RtpFrameObject> frame) {
philipel4e702162020-11-27 17:56:37 +010049 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 }
philipel4e702162020-11-27 17:56:37 +010090 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: {
philipel39f09b42020-12-01 11:47:12 +0100101 return GetRefFinderAs<RtpSeqNumOnlyRefFinder>().ManageFrame(
102 std::move(frame));
philipel4e702162020-11-27 17:56:37 +0100103 }
104 }
105}
106
107RtpFrameReferenceFinder::ReturnVector
108RtpFrameReferenceFinderImpl::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
115void 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
135template <typename T>
136T& 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
philipel02447bc2016-05-13 06:01:03 -0700144
145RtpFrameReferenceFinder::RtpFrameReferenceFinder(
146 OnCompleteFrameCallback* frame_callback)
philipel7acc4a42019-09-26 11:25:52 +0200147 : RtpFrameReferenceFinder(frame_callback, 0) {}
148
149RtpFrameReferenceFinder::RtpFrameReferenceFinder(
150 OnCompleteFrameCallback* frame_callback,
151 int64_t picture_id_offset)
philipel4e702162020-11-27 17:56:37 +0100152 : picture_id_offset_(picture_id_offset),
philipel7acc4a42019-09-26 11:25:52 +0200153 frame_callback_(frame_callback),
philipel4e702162020-11-27 17:56:37 +0100154 impl_(std::make_unique<internal::RtpFrameReferenceFinderImpl>()) {}
philipel02447bc2016-05-13 06:01:03 -0700155
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200156RtpFrameReferenceFinder::~RtpFrameReferenceFinder() = default;
157
philipel02447bc2016-05-13 06:01:03 -0700158void RtpFrameReferenceFinder::ManageFrame(
philipelca188092021-03-23 12:00:49 +0100159 std::unique_ptr<RtpFrameObject> frame) {
philipel463d3012016-09-09 03:32:44 -0700160 // If we have cleared past this frame, drop it.
161 if (cleared_to_seq_num_ != -1 &&
162 AheadOf<uint16_t>(cleared_to_seq_num_, frame->first_seq_num())) {
163 return;
164 }
philipel4e702162020-11-27 17:56:37 +0100165 HandOffFrames(impl_->ManageFrame(std::move(frame)));
philipel02447bc2016-05-13 06:01:03 -0700166}
167
philipel9b2ce6b2016-07-05 05:04:46 -0700168void RtpFrameReferenceFinder::PaddingReceived(uint16_t seq_num) {
philipel4e702162020-11-27 17:56:37 +0100169 HandOffFrames(impl_->PaddingReceived(seq_num));
philipel9b2ce6b2016-07-05 05:04:46 -0700170}
171
philipel463d3012016-09-09 03:32:44 -0700172void RtpFrameReferenceFinder::ClearTo(uint16_t seq_num) {
philipel463d3012016-09-09 03:32:44 -0700173 cleared_to_seq_num_ = seq_num;
philipel4e702162020-11-27 17:56:37 +0100174 impl_->ClearTo(seq_num);
philipel463d3012016-09-09 03:32:44 -0700175}
176
philipel4e702162020-11-27 17:56:37 +0100177void RtpFrameReferenceFinder::HandOffFrames(ReturnVector frames) {
178 for (auto& frame : frames) {
philipel9aa9b8d2021-02-15 13:31:29 +0100179 frame->SetId(frame->Id() + picture_id_offset_);
philipel02447bc2016-05-13 06:01:03 -0700180 for (size_t i = 0; i < frame->num_references; ++i) {
philipel4e702162020-11-27 17:56:37 +0100181 frame->references[i] += picture_id_offset_;
philipel02447bc2016-05-13 06:01:03 -0700182 }
183
philipel4e702162020-11-27 17:56:37 +0100184 frame_callback_->OnCompleteFrame(std::move(frame));
philipel02447bc2016-05-13 06:01:03 -0700185 }
philipel02447bc2016-05-13 06:01:03 -0700186}
187
philipel02447bc2016-05-13 06:01:03 -0700188} // namespace webrtc