1 /*
2 * Copyright (c) 2012 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/video_coding_impl.h"
12
13 #include <algorithm>
14 #include <memory>
15
16 #include "api/field_trials_view.h"
17 #include "api/sequence_checker.h"
18 #include "api/transport/field_trial_based_config.h"
19 #include "api/video/encoded_image.h"
20 #include "modules/video_coding/include/video_codec_interface.h"
21 #include "modules/video_coding/timing/timing.h"
22 #include "rtc_base/logging.h"
23 #include "rtc_base/memory/always_valid_pointer.h"
24 #include "system_wrappers/include/clock.h"
25
26 namespace webrtc {
27 namespace vcm {
28
Period() const29 int64_t VCMProcessTimer::Period() const {
30 return _periodMs;
31 }
32
TimeUntilProcess() const33 int64_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);
37 }
38
Processed()39 void VCMProcessTimer::Processed() {
40 _latestMs = _clock->TimeInMilliseconds();
41 }
42
DEPRECATED_VCMDecoderDataBase()43 DEPRECATED_VCMDecoderDataBase::DEPRECATED_VCMDecoderDataBase() {
44 decoder_sequence_checker_.Detach();
45 }
46
DeregisterExternalDecoder(uint8_t payload_type)47 VideoDecoder* 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.
RegisterExternalDecoder(uint8_t payload_type,VideoDecoder * external_decoder)69 void 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
IsExternalDecoderRegistered(uint8_t payload_type) const78 bool 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
RegisterReceiveCodec(uint8_t payload_type,const VideoDecoder::Settings & settings)85 void 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
DeregisterReceiveCodec(uint8_t payload_type)95 bool 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
GetDecoder(const VCMEncodedFrame & frame,VCMDecodedFrameCallback * decoded_frame_callback)107 VCMGenericDecoder* 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
CreateAndInitDecoder(const VCMEncodedFrame & frame)139 void 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
172 } // namespace vcm
173
174 namespace {
175
176 class VideoCodingModuleImpl : public VideoCodingModule {
177 public:
VideoCodingModuleImpl(Clock * clock,const FieldTrialsView * field_trials)178 explicit VideoCodingModuleImpl(Clock* clock,
179 const FieldTrialsView* field_trials)
180 : VideoCodingModule(),
181 field_trials_(field_trials),
182 timing_(new VCMTiming(clock, *field_trials_)),
183 receiver_(clock, timing_.get(), *field_trials_) {}
184
185 ~VideoCodingModuleImpl() override = default;
186
Process()187 void Process() override { receiver_.Process(); }
188
RegisterReceiveCodec(uint8_t payload_type,const VideoDecoder::Settings & decoder_settings)189 void RegisterReceiveCodec(
190 uint8_t payload_type,
191 const VideoDecoder::Settings& decoder_settings) override {
192 receiver_.RegisterReceiveCodec(payload_type, decoder_settings);
193 }
194
RegisterExternalDecoder(VideoDecoder * externalDecoder,uint8_t payloadType)195 void RegisterExternalDecoder(VideoDecoder* externalDecoder,
196 uint8_t payloadType) override {
197 receiver_.RegisterExternalDecoder(externalDecoder, payloadType);
198 }
199
RegisterReceiveCallback(VCMReceiveCallback * receiveCallback)200 int32_t RegisterReceiveCallback(
201 VCMReceiveCallback* receiveCallback) override {
202 RTC_DCHECK(construction_thread_.IsCurrent());
203 return receiver_.RegisterReceiveCallback(receiveCallback);
204 }
205
RegisterFrameTypeCallback(VCMFrameTypeCallback * frameTypeCallback)206 int32_t RegisterFrameTypeCallback(
207 VCMFrameTypeCallback* frameTypeCallback) override {
208 return receiver_.RegisterFrameTypeCallback(frameTypeCallback);
209 }
210
RegisterPacketRequestCallback(VCMPacketRequestCallback * callback)211 int32_t RegisterPacketRequestCallback(
212 VCMPacketRequestCallback* callback) override {
213 RTC_DCHECK(construction_thread_.IsCurrent());
214 return receiver_.RegisterPacketRequestCallback(callback);
215 }
216
Decode(uint16_t maxWaitTimeMs)217 int32_t Decode(uint16_t maxWaitTimeMs) override {
218 return receiver_.Decode(maxWaitTimeMs);
219 }
220
IncomingPacket(const uint8_t * incomingPayload,size_t payloadLength,const RTPHeader & rtp_header,const RTPVideoHeader & video_header)221 int32_t IncomingPacket(const uint8_t* incomingPayload,
222 size_t payloadLength,
223 const RTPHeader& rtp_header,
224 const RTPVideoHeader& video_header) override {
225 return receiver_.IncomingPacket(incomingPayload, payloadLength, rtp_header,
226 video_header);
227 }
228
SetNackSettings(size_t max_nack_list_size,int max_packet_age_to_nack,int max_incomplete_time_ms)229 void SetNackSettings(size_t max_nack_list_size,
230 int max_packet_age_to_nack,
231 int max_incomplete_time_ms) override {
232 return receiver_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
233 max_incomplete_time_ms);
234 }
235
236 private:
237 AlwaysValidPointer<const FieldTrialsView, FieldTrialBasedConfig>
238 field_trials_;
239 SequenceChecker construction_thread_;
240 const std::unique_ptr<VCMTiming> timing_;
241 vcm::VideoReceiver receiver_;
242 };
243 } // namespace
244
245 // DEPRECATED. Create method for current interface, will be removed when the
246 // new jitter buffer is in place.
Create(Clock * clock,const FieldTrialsView * field_trials)247 VideoCodingModule* VideoCodingModule::Create(
248 Clock* clock,
249 const FieldTrialsView* field_trials) {
250 RTC_DCHECK(clock);
251 return new VideoCodingModuleImpl(clock, field_trials);
252 }
253
254 } // namespace webrtc
255