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/codec_database.h"
12 
13 #include "modules/video_coding/codecs/h264/include/h264.h"
14 #include "modules/video_coding/codecs/i420/include/i420.h"
15 #include "modules/video_coding/codecs/vp8/include/vp8.h"
16 #include "modules/video_coding/codecs/vp9/include/vp9.h"
17 #include "modules/video_coding/internal_defines.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/logging.h"
20 
21 namespace {
22 const size_t kDefaultPayloadSize = 1440;
23 }
24 
25 namespace webrtc {
26 
27 // Create an internal Decoder given a codec type
CreateDecoder(VideoCodecType type)28 static std::unique_ptr<VCMGenericDecoder> CreateDecoder(VideoCodecType type) {
29   switch (type) {
30     case kVideoCodecVP8:
31       return std::unique_ptr<VCMGenericDecoder>(
32           new VCMGenericDecoder(VP8Decoder::Create()));
33     case kVideoCodecVP9:
34       return std::unique_ptr<VCMGenericDecoder>(
35           new VCMGenericDecoder(VP9Decoder::Create()));
36     case kVideoCodecI420:
37       return std::unique_ptr<VCMGenericDecoder>(
38           new VCMGenericDecoder(new I420Decoder()));
39     case kVideoCodecH264:
40       if (H264Decoder::IsSupported()) {
41         return std::unique_ptr<VCMGenericDecoder>(
42             new VCMGenericDecoder(H264Decoder::Create()));
43       }
44       break;
45     default:
46       break;
47   }
48   RTC_LOG(LS_WARNING) << "No internal decoder of this type exists.";
49   return std::unique_ptr<VCMGenericDecoder>();
50 }
51 
VCMDecoderMapItem(VideoCodec * settings,int number_of_cores,bool require_key_frame)52 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings,
53                                      int number_of_cores,
54                                      bool require_key_frame)
55     : settings(settings),
56       number_of_cores(number_of_cores),
57       require_key_frame(require_key_frame) {
58   RTC_DCHECK_GE(number_of_cores, 0);
59 }
60 
VCMExtDecoderMapItem(VideoDecoder * external_decoder_instance,uint8_t payload_type)61 VCMExtDecoderMapItem::VCMExtDecoderMapItem(
62     VideoDecoder* external_decoder_instance,
63     uint8_t payload_type)
64     : payload_type(payload_type),
65       external_decoder_instance(external_decoder_instance) {}
66 
VCMCodecDataBase(VCMEncodedFrameCallback * encoded_frame_callback)67 VCMCodecDataBase::VCMCodecDataBase(
68     VCMEncodedFrameCallback* encoded_frame_callback)
69     : number_of_cores_(0),
70       max_payload_size_(kDefaultPayloadSize),
71       periodic_key_frames_(false),
72       pending_encoder_reset_(true),
73       send_codec_(),
74       receive_codec_(),
75       encoder_payload_type_(0),
76       external_encoder_(nullptr),
77       internal_source_(false),
78       encoded_frame_callback_(encoded_frame_callback),
79       dec_map_(),
80       dec_external_map_() {}
81 
~VCMCodecDataBase()82 VCMCodecDataBase::~VCMCodecDataBase() {
83   DeleteEncoder();
84   ptr_decoder_.reset();
85   for (auto& kv : dec_map_)
86     delete kv.second;
87   for (auto& kv : dec_external_map_)
88     delete kv.second;
89 }
90 
91 // Assuming only one registered encoder - since only one used, no need for more.
SetSendCodec(const VideoCodec * send_codec,int number_of_cores,size_t max_payload_size)92 bool VCMCodecDataBase::SetSendCodec(const VideoCodec* send_codec,
93                                     int number_of_cores,
94                                     size_t max_payload_size) {
95   RTC_DCHECK(send_codec);
96   if (max_payload_size == 0) {
97     max_payload_size = kDefaultPayloadSize;
98   }
99   RTC_DCHECK_GE(number_of_cores, 1);
100   RTC_DCHECK_GE(send_codec->plType, 1);
101   // Make sure the start bit rate is sane...
102   RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
103   RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown);
104   bool reset_required = pending_encoder_reset_;
105   if (number_of_cores_ != number_of_cores) {
106     number_of_cores_ = number_of_cores;
107     reset_required = true;
108   }
109   if (max_payload_size_ != max_payload_size) {
110     max_payload_size_ = max_payload_size;
111     reset_required = true;
112   }
113 
114   VideoCodec new_send_codec;
115   memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
116 
117   if (new_send_codec.maxBitrate == 0) {
118     // max is one bit per pixel
119     new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
120                                  static_cast<int>(send_codec->width) *
121                                  static_cast<int>(send_codec->maxFramerate)) /
122                                 1000;
123     if (send_codec->startBitrate > new_send_codec.maxBitrate) {
124       // But if the user tries to set a higher start bit rate we will
125       // increase the max accordingly.
126       new_send_codec.maxBitrate = send_codec->startBitrate;
127     }
128   }
129 
130   if (new_send_codec.startBitrate > new_send_codec.maxBitrate)
131     new_send_codec.startBitrate = new_send_codec.maxBitrate;
132 
133   if (!reset_required) {
134     reset_required = RequiresEncoderReset(new_send_codec);
135   }
136 
137   memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
138 
139   if (!reset_required) {
140     return true;
141   }
142 
143   // If encoder exists, will destroy it and create new one.
144   DeleteEncoder();
145   RTC_DCHECK_EQ(encoder_payload_type_, send_codec_.plType)
146       << "Encoder not registered for payload type " << send_codec_.plType;
147   ptr_encoder_.reset(new VCMGenericEncoder(
148       external_encoder_, encoded_frame_callback_, internal_source_));
149   encoded_frame_callback_->SetInternalSource(internal_source_);
150   if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
151                                max_payload_size_) < 0) {
152     RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
153     DeleteEncoder();
154     return false;
155   }
156 
157   // Intentionally don't check return value since the encoder registration
158   // shouldn't fail because the codec doesn't support changing the periodic key
159   // frame setting.
160   ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_);
161 
162   pending_encoder_reset_ = false;
163 
164   return true;
165 }
166 
SendCodec(VideoCodec * current_send_codec) const167 bool VCMCodecDataBase::SendCodec(VideoCodec* current_send_codec) const {
168   if (!ptr_encoder_) {
169     return false;
170   }
171   memcpy(current_send_codec, &send_codec_, sizeof(VideoCodec));
172   return true;
173 }
174 
SendCodec() const175 VideoCodecType VCMCodecDataBase::SendCodec() const {
176   if (!ptr_encoder_) {
177     return kVideoCodecUnknown;
178   }
179   return send_codec_.codecType;
180 }
181 
DeregisterExternalEncoder(uint8_t payload_type,bool * was_send_codec)182 bool VCMCodecDataBase::DeregisterExternalEncoder(uint8_t payload_type,
183                                                  bool* was_send_codec) {
184   RTC_DCHECK(was_send_codec);
185   *was_send_codec = false;
186   if (encoder_payload_type_ != payload_type) {
187     return false;
188   }
189   if (send_codec_.plType == payload_type) {
190     // De-register as send codec if needed.
191     DeleteEncoder();
192     memset(&send_codec_, 0, sizeof(VideoCodec));
193     *was_send_codec = true;
194   }
195   encoder_payload_type_ = 0;
196   external_encoder_ = nullptr;
197   internal_source_ = false;
198   return true;
199 }
200 
RegisterExternalEncoder(VideoEncoder * external_encoder,uint8_t payload_type,bool internal_source)201 void VCMCodecDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
202                                                uint8_t payload_type,
203                                                bool internal_source) {
204   // Since only one encoder can be used at a given time, only one external
205   // encoder can be registered/used.
206   external_encoder_ = external_encoder;
207   encoder_payload_type_ = payload_type;
208   internal_source_ = internal_source;
209   pending_encoder_reset_ = true;
210 }
211 
RequiresEncoderReset(const VideoCodec & new_send_codec)212 bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) {
213   if (!ptr_encoder_)
214     return true;
215 
216   // Does not check startBitrate or maxFramerate
217   if (new_send_codec.codecType != send_codec_.codecType ||
218       strcmp(new_send_codec.plName, send_codec_.plName) != 0 ||
219       new_send_codec.plType != send_codec_.plType ||
220       new_send_codec.width != send_codec_.width ||
221       new_send_codec.height != send_codec_.height ||
222       new_send_codec.maxBitrate != send_codec_.maxBitrate ||
223       new_send_codec.minBitrate != send_codec_.minBitrate ||
224       new_send_codec.qpMax != send_codec_.qpMax ||
225       new_send_codec.numberOfSimulcastStreams !=
226           send_codec_.numberOfSimulcastStreams ||
227       new_send_codec.mode != send_codec_.mode) {
228     return true;
229   }
230 
231   switch (new_send_codec.codecType) {
232     case kVideoCodecVP8:
233       if (memcmp(&new_send_codec.VP8(), send_codec_.VP8(),
234                  sizeof(new_send_codec.VP8())) != 0) {
235         return true;
236       }
237       break;
238     case kVideoCodecVP9:
239       if (memcmp(&new_send_codec.VP9(), send_codec_.VP9(),
240                  sizeof(new_send_codec.VP9())) != 0) {
241         return true;
242       }
243       break;
244     case kVideoCodecH264:
245       if (memcmp(&new_send_codec.H264(), send_codec_.H264(),
246                  sizeof(new_send_codec.H264())) != 0) {
247         return true;
248       }
249       break;
250     case kVideoCodecGeneric:
251       break;
252     // Known codecs without payload-specifics
253     case kVideoCodecI420:
254     case kVideoCodecRED:
255     case kVideoCodecULPFEC:
256     case kVideoCodecFlexfec:
257       break;
258     // Unknown codec type, reset just to be sure.
259     case kVideoCodecUnknown:
260       return true;
261   }
262 
263   if (new_send_codec.numberOfSimulcastStreams > 0) {
264     for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
265          ++i) {
266       if (memcmp(&new_send_codec.simulcastStream[i],
267                  &send_codec_.simulcastStream[i],
268                  sizeof(new_send_codec.simulcastStream[i])) != 0) {
269         return true;
270       }
271     }
272   }
273   return false;
274 }
275 
GetEncoder()276 VCMGenericEncoder* VCMCodecDataBase::GetEncoder() {
277   return ptr_encoder_.get();
278 }
279 
SetPeriodicKeyFrames(bool enable)280 bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) {
281   periodic_key_frames_ = enable;
282   if (ptr_encoder_) {
283     return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0);
284   }
285   return true;
286 }
287 
DeregisterExternalDecoder(uint8_t payload_type)288 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) {
289   ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type);
290   if (it == dec_external_map_.end()) {
291     // Not found
292     return false;
293   }
294   // We can't use payload_type to check if the decoder is currently in use,
295   // because payload type may be out of date (e.g. before we decode the first
296   // frame after RegisterReceiveCodec)
297   if (ptr_decoder_ &&
298       ptr_decoder_->IsSameDecoder((*it).second->external_decoder_instance)) {
299     // Release it if it was registered and in use.
300     ptr_decoder_.reset();
301   }
302   DeregisterReceiveCodec(payload_type);
303   delete it->second;
304   dec_external_map_.erase(it);
305   return true;
306 }
307 
308 // Add the external encoder object to the list of external decoders.
309 // Won't be registered as a receive codec until RegisterReceiveCodec is called.
RegisterExternalDecoder(VideoDecoder * external_decoder,uint8_t payload_type)310 void VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* external_decoder,
311                                                uint8_t payload_type) {
312   // Check if payload value already exists, if so  - erase old and insert new.
313   VCMExtDecoderMapItem* ext_decoder =
314       new VCMExtDecoderMapItem(external_decoder, payload_type);
315   DeregisterExternalDecoder(payload_type);
316   dec_external_map_[payload_type] = ext_decoder;
317 }
318 
DecoderRegistered() const319 bool VCMCodecDataBase::DecoderRegistered() const {
320   return !dec_map_.empty();
321 }
322 
RegisterReceiveCodec(const VideoCodec * receive_codec,int number_of_cores,bool require_key_frame)323 bool VCMCodecDataBase::RegisterReceiveCodec(const VideoCodec* receive_codec,
324                                             int number_of_cores,
325                                             bool require_key_frame) {
326   if (number_of_cores < 0) {
327     return false;
328   }
329   // Check if payload value already exists, if so  - erase old and insert new.
330   DeregisterReceiveCodec(receive_codec->plType);
331   if (receive_codec->codecType == kVideoCodecUnknown) {
332     return false;
333   }
334   VideoCodec* new_receive_codec = new VideoCodec(*receive_codec);
335   dec_map_[receive_codec->plType] = new VCMDecoderMapItem(
336       new_receive_codec, number_of_cores, require_key_frame);
337   return true;
338 }
339 
DeregisterReceiveCodec(uint8_t payload_type)340 bool VCMCodecDataBase::DeregisterReceiveCodec(uint8_t payload_type) {
341   DecoderMap::iterator it = dec_map_.find(payload_type);
342   if (it == dec_map_.end()) {
343     return false;
344   }
345   delete it->second;
346   dec_map_.erase(it);
347   if (receive_codec_.plType == payload_type) {
348     // This codec is currently in use.
349     memset(&receive_codec_, 0, sizeof(VideoCodec));
350   }
351   return true;
352 }
353 
GetDecoder(const VCMEncodedFrame & frame,VCMDecodedFrameCallback * decoded_frame_callback)354 VCMGenericDecoder* VCMCodecDataBase::GetDecoder(
355     const VCMEncodedFrame& frame,
356     VCMDecodedFrameCallback* decoded_frame_callback) {
357   RTC_DCHECK(decoded_frame_callback->UserReceiveCallback());
358   uint8_t payload_type = frame.PayloadType();
359   if (payload_type == receive_codec_.plType || payload_type == 0) {
360     return ptr_decoder_.get();
361   }
362   // Check for exisitng decoder, if exists - delete.
363   if (ptr_decoder_) {
364     ptr_decoder_.reset();
365     memset(&receive_codec_, 0, sizeof(VideoCodec));
366   }
367   ptr_decoder_ = CreateAndInitDecoder(frame, &receive_codec_);
368   if (!ptr_decoder_) {
369     return nullptr;
370   }
371   VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback();
372   callback->OnIncomingPayloadType(receive_codec_.plType);
373   if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) <
374       0) {
375     ptr_decoder_.reset();
376     memset(&receive_codec_, 0, sizeof(VideoCodec));
377     return nullptr;
378   }
379   return ptr_decoder_.get();
380 }
381 
GetCurrentDecoder()382 VCMGenericDecoder* VCMCodecDataBase::GetCurrentDecoder() {
383   return ptr_decoder_.get();
384 }
385 
PrefersLateDecoding() const386 bool VCMCodecDataBase::PrefersLateDecoding() const {
387   return ptr_decoder_ ? ptr_decoder_->PrefersLateDecoding() : true;
388 }
389 
MatchesCurrentResolution(int width,int height) const390 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const {
391   return send_codec_.width == width && send_codec_.height == height;
392 }
393 
CreateAndInitDecoder(const VCMEncodedFrame & frame,VideoCodec * new_codec) const394 std::unique_ptr<VCMGenericDecoder> VCMCodecDataBase::CreateAndInitDecoder(
395     const VCMEncodedFrame& frame,
396     VideoCodec* new_codec) const {
397   uint8_t payload_type = frame.PayloadType();
398   RTC_LOG(LS_INFO) << "Initializing decoder with payload type '"
399                    << static_cast<int>(payload_type) << "'.";
400   RTC_DCHECK(new_codec);
401   const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type);
402   if (!decoder_item) {
403     RTC_LOG(LS_ERROR) << "Can't find a decoder associated with payload type: "
404                       << static_cast<int>(payload_type);
405     return nullptr;
406   }
407   std::unique_ptr<VCMGenericDecoder> ptr_decoder;
408   const VCMExtDecoderMapItem* external_dec_item =
409       FindExternalDecoderItem(payload_type);
410   if (external_dec_item) {
411     // External codec.
412     ptr_decoder.reset(new VCMGenericDecoder(
413         external_dec_item->external_decoder_instance, true));
414   } else {
415     // Create decoder.
416     ptr_decoder = CreateDecoder(decoder_item->settings->codecType);
417   }
418   if (!ptr_decoder)
419     return nullptr;
420 
421   // Copy over input resolutions to prevent codec reinitialization due to
422   // the first frame being of a different resolution than the database values.
423   // This is best effort, since there's no guarantee that width/height have been
424   // parsed yet (and may be zero).
425   if (frame.EncodedImage()._encodedWidth > 0 &&
426       frame.EncodedImage()._encodedHeight > 0) {
427     decoder_item->settings->width = frame.EncodedImage()._encodedWidth;
428     decoder_item->settings->height = frame.EncodedImage()._encodedHeight;
429   }
430   if (ptr_decoder->InitDecode(decoder_item->settings.get(),
431                               decoder_item->number_of_cores) < 0) {
432     return nullptr;
433   }
434   memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec));
435   return ptr_decoder;
436 }
437 
DeleteEncoder()438 void VCMCodecDataBase::DeleteEncoder() {
439   if (!ptr_encoder_)
440     return;
441   ptr_encoder_->Release();
442   ptr_encoder_.reset();
443 }
444 
FindDecoderItem(uint8_t payload_type) const445 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem(
446     uint8_t payload_type) const {
447   DecoderMap::const_iterator it = dec_map_.find(payload_type);
448   if (it != dec_map_.end()) {
449     return (*it).second;
450   }
451   return nullptr;
452 }
453 
FindExternalDecoderItem(uint8_t payload_type) const454 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem(
455     uint8_t payload_type) const {
456   ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type);
457   if (it != dec_external_map_.end()) {
458     return (*it).second;
459   }
460   return nullptr;
461 }
462 }  // namespace webrtc
463