blob: 2eaecd5011e10c8707b627b12facba3dc3e569c2 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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/video_coding_impl.h"
philipel5908c712015-12-21 08:23:20 -080012
13#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <memory>
philipel5908c712015-12-21 08:23:20 -080015
Jonas Orelande62c2f22022-03-29 11:04:48 +020016#include "api/field_trials_view.h"
Artem Titovd15a5752021-02-10 14:31:24 +010017#include "api/sequence_checker.h"
Jonas Orelande02f9ee2022-03-25 12:43:14 +010018#include "api/transport/field_trial_based_config.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/video/encoded_image.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/video_coding/include/video_codec_interface.h"
Rasmus Brandtc4d253c2022-05-25 12:03:35 +020021#include "modules/video_coding/timing/timing.h"
Tommi20b32712022-09-29 14:13:15 +020022#include "rtc_base/logging.h"
Jonas Orelande02f9ee2022-03-25 12:43:14 +010023#include "rtc_base/memory/always_valid_pointer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000025
agalusza@google.coma7e360e2013-08-01 03:15:08 +000026namespace webrtc {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000027namespace vcm {
niklase@google.com470e71d2011-07-07 08:21:25 +000028
philipel5908c712015-12-21 08:23:20 -080029int64_t VCMProcessTimer::Period() const {
30 return _periodMs;
niklase@google.com470e71d2011-07-07 08:21:25 +000031}
32
philipel5908c712015-12-21 08:23:20 -080033int64_t VCMProcessTimer::TimeUntilProcess() const {
34 const int64_t time_since_process = _clock->TimeInMilliseconds() - _latestMs;
35 const int64_t time_until_process = _periodMs - time_since_process;
36 return std::max<int64_t>(time_until_process, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000037}
38
philipel5908c712015-12-21 08:23:20 -080039void VCMProcessTimer::Processed() {
40 _latestMs = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +000041}
Tommi20b32712022-09-29 14:13:15 +020042
43DEPRECATED_VCMDecoderDataBase::DEPRECATED_VCMDecoderDataBase() {
44 decoder_sequence_checker_.Detach();
45}
46
47VideoDecoder* DEPRECATED_VCMDecoderDataBase::DeregisterExternalDecoder(
48 uint8_t payload_type) {
49 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
50 auto it = decoders_.find(payload_type);
51 if (it == decoders_.end()) {
52 return nullptr;
53 }
54
55 // We can't use payload_type to check if the decoder is currently in use,
56 // because payload type may be out of date (e.g. before we decode the first
57 // frame after RegisterReceiveCodec).
58 if (current_decoder_ && current_decoder_->IsSameDecoder(it->second)) {
59 // Release it if it was registered and in use.
60 current_decoder_ = absl::nullopt;
61 }
62 VideoDecoder* ret = it->second;
63 decoders_.erase(it);
64 return ret;
65}
66
67// Add the external decoder object to the list of external decoders.
68// Won't be registered as a receive codec until RegisterReceiveCodec is called.
69void DEPRECATED_VCMDecoderDataBase::RegisterExternalDecoder(
70 uint8_t payload_type,
71 VideoDecoder* external_decoder) {
72 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
73 // If payload value already exists, erase old and insert new.
74 DeregisterExternalDecoder(payload_type);
75 decoders_[payload_type] = external_decoder;
76}
77
78bool DEPRECATED_VCMDecoderDataBase::IsExternalDecoderRegistered(
79 uint8_t payload_type) const {
80 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
81 return payload_type == current_payload_type_ ||
82 decoders_.find(payload_type) != decoders_.end();
83}
84
85void DEPRECATED_VCMDecoderDataBase::RegisterReceiveCodec(
86 uint8_t payload_type,
87 const VideoDecoder::Settings& settings) {
88 // If payload value already exists, erase old and insert new.
89 if (payload_type == current_payload_type_) {
90 current_payload_type_ = absl::nullopt;
91 }
92 decoder_settings_[payload_type] = settings;
93}
94
95bool DEPRECATED_VCMDecoderDataBase::DeregisterReceiveCodec(
96 uint8_t payload_type) {
97 if (decoder_settings_.erase(payload_type) == 0) {
98 return false;
99 }
100 if (payload_type == current_payload_type_) {
101 // This codec is currently in use.
102 current_payload_type_ = absl::nullopt;
103 }
104 return true;
105}
106
107VCMGenericDecoder* DEPRECATED_VCMDecoderDataBase::GetDecoder(
108 const VCMEncodedFrame& frame,
109 VCMDecodedFrameCallback* decoded_frame_callback) {
110 RTC_DCHECK_RUN_ON(&decoder_sequence_checker_);
111 RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
112 uint8_t payload_type = frame.PayloadType();
113 if (payload_type == current_payload_type_ || payload_type == 0) {
114 return current_decoder_.has_value() ? &*current_decoder_ : nullptr;
115 }
116 // If decoder exists - delete.
117 if (current_decoder_.has_value()) {
118 current_decoder_ = absl::nullopt;
119 current_payload_type_ = absl::nullopt;
120 }
121
122 CreateAndInitDecoder(frame);
123 if (current_decoder_ == absl::nullopt) {
124 return nullptr;
125 }
126
127 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
128 callback->OnIncomingPayloadType(payload_type);
129 if (current_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
130 0) {
131 current_decoder_ = absl::nullopt;
132 return nullptr;
133 }
134
135 current_payload_type_ = payload_type;
136 return &*current_decoder_;
137}
138
139void DEPRECATED_VCMDecoderDataBase::CreateAndInitDecoder(
140 const VCMEncodedFrame& frame) {
141 uint8_t payload_type = frame.PayloadType();
142 RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
143 << int{payload_type} << "'.";
144 auto decoder_item = decoder_settings_.find(payload_type);
145 if (decoder_item == decoder_settings_.end()) {
146 RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
147 << int{payload_type};
148 return;
149 }
150 auto external_dec_item = decoders_.find(payload_type);
151 if (external_dec_item == decoders_.end()) {
152 RTC_LOG(LS_ERROR) << "No decoder of this type exists.";
153 return;
154 }
155 current_decoder_.emplace(external_dec_item->second);
156
157 // Copy over input resolutions to prevent codec reinitialization due to
158 // the first frame being of a different resolution than the database values.
159 // This is best effort, since there's no guarantee that width/height have been
160 // parsed yet (and may be zero).
161 RenderResolution frame_resolution(frame.EncodedImage()._encodedWidth,
162 frame.EncodedImage()._encodedHeight);
163 if (frame_resolution.Valid()) {
164 decoder_item->second.set_max_render_resolution(frame_resolution);
165 }
166 if (!current_decoder_->Configure(decoder_item->second)) {
167 current_decoder_ = absl::nullopt;
168 RTC_LOG(LS_ERROR) << "Failed to initialize decoder.";
169 }
170}
171
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000172} // namespace vcm
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000174namespace {
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +0000175
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000176class VideoCodingModuleImpl : public VideoCodingModule {
177 public:
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100178 explicit VideoCodingModuleImpl(Clock* clock,
Jonas Orelande62c2f22022-03-29 11:04:48 +0200179 const FieldTrialsView* field_trials)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000180 : VideoCodingModule(),
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100181 field_trials_(field_trials),
182 timing_(new VCMTiming(clock, *field_trials_)),
183 receiver_(clock, timing_.get(), *field_trials_) {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000184
Danil Chapovalovce808862022-06-22 15:48:36 +0200185 ~VideoCodingModuleImpl() override = default;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000186
Yves Gerey665174f2018-06-19 15:03:05 +0200187 void Process() override { receiver_.Process(); }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000188
Danil Chapovalovba0a3062021-08-13 18:15:55 +0200189 void RegisterReceiveCodec(
Danil Chapovalov355b8d22021-08-13 16:50:37 +0200190 uint8_t payload_type,
191 const VideoDecoder::Settings& decoder_settings) override {
Danil Chapovalovba0a3062021-08-13 18:15:55 +0200192 receiver_.RegisterReceiveCodec(payload_type, decoder_settings);
Danil Chapovalov355b8d22021-08-13 16:50:37 +0200193 }
194
Anders Carlsson7eb8e9f2018-05-18 10:33:04 +0200195 void RegisterExternalDecoder(VideoDecoder* externalDecoder,
196 uint8_t payloadType) override {
197 receiver_.RegisterExternalDecoder(externalDecoder, payloadType);
198 }
199
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000200 int32_t RegisterReceiveCallback(
201 VCMReceiveCallback* receiveCallback) override {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200202 RTC_DCHECK(construction_thread_.IsCurrent());
pbos0fa9b222015-11-13 05:59:57 -0800203 return receiver_.RegisterReceiveCallback(receiveCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000204 }
205
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000206 int32_t RegisterFrameTypeCallback(
207 VCMFrameTypeCallback* frameTypeCallback) override {
pbos0fa9b222015-11-13 05:59:57 -0800208 return receiver_.RegisterFrameTypeCallback(frameTypeCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000209 }
210
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000211 int32_t RegisterPacketRequestCallback(
212 VCMPacketRequestCallback* callback) override {
Sebastian Janssonc01367d2019-04-08 15:20:44 +0200213 RTC_DCHECK(construction_thread_.IsCurrent());
pbos0fa9b222015-11-13 05:59:57 -0800214 return receiver_.RegisterPacketRequestCallback(callback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000215 }
216
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000217 int32_t Decode(uint16_t maxWaitTimeMs) override {
pbos0fa9b222015-11-13 05:59:57 -0800218 return receiver_.Decode(maxWaitTimeMs);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000219 }
220
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000221 int32_t IncomingPacket(const uint8_t* incomingPayload,
222 size_t payloadLength,
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200223 const RTPHeader& rtp_header,
224 const RTPVideoHeader& video_header) override {
225 return receiver_.IncomingPacket(incomingPayload, payloadLength, rtp_header,
226 video_header);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000227 }
228
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000229 void SetNackSettings(size_t max_nack_list_size,
230 int max_packet_age_to_nack,
231 int max_incomplete_time_ms) override {
pbos0fa9b222015-11-13 05:59:57 -0800232 return receiver_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
233 max_incomplete_time_ms);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000234 }
235
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000236 private:
Jonas Orelande62c2f22022-03-29 11:04:48 +0200237 AlwaysValidPointer<const FieldTrialsView, FieldTrialBasedConfig>
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100238 field_trials_;
Artem Titovc8421c42021-02-02 10:57:19 +0100239 SequenceChecker construction_thread_;
Jiawei Ouc2ebe212018-11-08 10:02:56 -0800240 const std::unique_ptr<VCMTiming> timing_;
pbos0fa9b222015-11-13 05:59:57 -0800241 vcm::VideoReceiver receiver_;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000242};
243} // namespace
244
tommia5c18d72017-03-20 10:43:23 -0700245// DEPRECATED. Create method for current interface, will be removed when the
philipel83f831a2016-03-12 03:30:23 -0800246// new jitter buffer is in place.
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100247VideoCodingModule* VideoCodingModule::Create(
248 Clock* clock,
Jonas Orelande62c2f22022-03-29 11:04:48 +0200249 const FieldTrialsView* field_trials) {
tommid0a71ba2017-03-14 04:16:20 -0700250 RTC_DCHECK(clock);
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100251 return new VideoCodingModuleImpl(clock, field_trials);
niklase@google.com470e71d2011-07-07 08:21:25 +0000252}
253
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000254} // namespace webrtc