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