• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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