| OLD | NEW |
| (Empty) |
| 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 "webrtc/modules/video_coding/main/source/codec_database.h" | |
| 12 | |
| 13 #include <assert.h> | |
| 14 | |
| 15 #include "webrtc/base/checks.h" | |
| 16 #include "webrtc/base/logging.h" | |
| 17 #include "webrtc/engine_configurations.h" | |
| 18 #ifdef VIDEOCODEC_H264 | |
| 19 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" | |
| 20 #endif | |
| 21 #ifdef VIDEOCODEC_I420 | |
| 22 #include "webrtc/modules/video_coding/codecs/i420/include/i420.h" | |
| 23 #endif | |
| 24 #ifdef VIDEOCODEC_VP8 | |
| 25 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | |
| 26 #endif | |
| 27 #ifdef VIDEOCODEC_VP9 | |
| 28 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" | |
| 29 #endif | |
| 30 #include "webrtc/modules/video_coding/main/source/internal_defines.h" | |
| 31 | |
| 32 namespace { | |
| 33 const size_t kDefaultPayloadSize = 1440; | |
| 34 const uint8_t kDefaultPayloadType = 100; | |
| 35 } | |
| 36 | |
| 37 namespace webrtc { | |
| 38 | |
| 39 VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() { | |
| 40 VideoCodecVP8 vp8_settings; | |
| 41 memset(&vp8_settings, 0, sizeof(vp8_settings)); | |
| 42 | |
| 43 vp8_settings.resilience = kResilientStream; | |
| 44 vp8_settings.numberOfTemporalLayers = 1; | |
| 45 vp8_settings.denoisingOn = true; | |
| 46 vp8_settings.errorConcealmentOn = false; | |
| 47 vp8_settings.automaticResizeOn = false; | |
| 48 vp8_settings.frameDroppingOn = true; | |
| 49 vp8_settings.keyFrameInterval = 3000; | |
| 50 | |
| 51 return vp8_settings; | |
| 52 } | |
| 53 | |
| 54 VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() { | |
| 55 VideoCodecVP9 vp9_settings; | |
| 56 memset(&vp9_settings, 0, sizeof(vp9_settings)); | |
| 57 | |
| 58 vp9_settings.resilience = 1; | |
| 59 vp9_settings.numberOfTemporalLayers = 1; | |
| 60 vp9_settings.denoisingOn = false; | |
| 61 vp9_settings.frameDroppingOn = true; | |
| 62 vp9_settings.keyFrameInterval = 3000; | |
| 63 vp9_settings.adaptiveQpMode = true; | |
| 64 vp9_settings.automaticResizeOn = true; | |
| 65 vp9_settings.numberOfSpatialLayers = 1; | |
| 66 vp9_settings.flexibleMode = false; | |
| 67 return vp9_settings; | |
| 68 } | |
| 69 | |
| 70 VideoCodecH264 VideoEncoder::GetDefaultH264Settings() { | |
| 71 VideoCodecH264 h264_settings; | |
| 72 memset(&h264_settings, 0, sizeof(h264_settings)); | |
| 73 | |
| 74 h264_settings.profile = kProfileBase; | |
| 75 h264_settings.frameDroppingOn = true; | |
| 76 h264_settings.keyFrameInterval = 3000; | |
| 77 h264_settings.spsData = NULL; | |
| 78 h264_settings.spsLen = 0; | |
| 79 h264_settings.ppsData = NULL; | |
| 80 h264_settings.ppsLen = 0; | |
| 81 | |
| 82 return h264_settings; | |
| 83 } | |
| 84 | |
| 85 VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, | |
| 86 int number_of_cores, | |
| 87 bool require_key_frame) | |
| 88 : settings(settings), | |
| 89 number_of_cores(number_of_cores), | |
| 90 require_key_frame(require_key_frame) { | |
| 91 assert(number_of_cores >= 0); | |
| 92 } | |
| 93 | |
| 94 VCMExtDecoderMapItem::VCMExtDecoderMapItem( | |
| 95 VideoDecoder* external_decoder_instance, | |
| 96 uint8_t payload_type, | |
| 97 bool internal_render_timing) | |
| 98 : payload_type(payload_type), | |
| 99 external_decoder_instance(external_decoder_instance), | |
| 100 internal_render_timing(internal_render_timing) { | |
| 101 } | |
| 102 | |
| 103 VCMCodecDataBase::VCMCodecDataBase( | |
| 104 VideoEncoderRateObserver* encoder_rate_observer, | |
| 105 VCMEncodedFrameCallback* encoded_frame_callback) | |
| 106 : number_of_cores_(0), | |
| 107 max_payload_size_(kDefaultPayloadSize), | |
| 108 periodic_key_frames_(false), | |
| 109 pending_encoder_reset_(true), | |
| 110 send_codec_(), | |
| 111 receive_codec_(), | |
| 112 encoder_payload_type_(0), | |
| 113 external_encoder_(NULL), | |
| 114 internal_source_(false), | |
| 115 encoder_rate_observer_(encoder_rate_observer), | |
| 116 encoded_frame_callback_(encoded_frame_callback), | |
| 117 ptr_decoder_(NULL), | |
| 118 dec_map_(), | |
| 119 dec_external_map_() {} | |
| 120 | |
| 121 VCMCodecDataBase::~VCMCodecDataBase() { | |
| 122 ResetSender(); | |
| 123 ResetReceiver(); | |
| 124 } | |
| 125 | |
| 126 int VCMCodecDataBase::NumberOfCodecs() { | |
| 127 return VCM_NUM_VIDEO_CODECS_AVAILABLE; | |
| 128 } | |
| 129 | |
| 130 bool VCMCodecDataBase::Codec(int list_id, | |
| 131 VideoCodec* settings) { | |
| 132 if (!settings) { | |
| 133 return false; | |
| 134 } | |
| 135 if (list_id >= VCM_NUM_VIDEO_CODECS_AVAILABLE) { | |
| 136 return false; | |
| 137 } | |
| 138 memset(settings, 0, sizeof(VideoCodec)); | |
| 139 switch (list_id) { | |
| 140 #ifdef VIDEOCODEC_VP8 | |
| 141 case VCM_VP8_IDX: { | |
| 142 strncpy(settings->plName, "VP8", 4); | |
| 143 settings->codecType = kVideoCodecVP8; | |
| 144 // 96 to 127 dynamic payload types for video codecs. | |
| 145 settings->plType = kDefaultPayloadType; | |
| 146 settings->startBitrate = kDefaultStartBitrateKbps; | |
| 147 settings->minBitrate = VCM_MIN_BITRATE; | |
| 148 settings->maxBitrate = 0; | |
| 149 settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; | |
| 150 settings->width = VCM_DEFAULT_CODEC_WIDTH; | |
| 151 settings->height = VCM_DEFAULT_CODEC_HEIGHT; | |
| 152 settings->numberOfSimulcastStreams = 0; | |
| 153 settings->qpMax = 56; | |
| 154 settings->codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings(); | |
| 155 return true; | |
| 156 } | |
| 157 #endif | |
| 158 #ifdef VIDEOCODEC_VP9 | |
| 159 case VCM_VP9_IDX: { | |
| 160 strncpy(settings->plName, "VP9", 4); | |
| 161 settings->codecType = kVideoCodecVP9; | |
| 162 // 96 to 127 dynamic payload types for video codecs. | |
| 163 settings->plType = kDefaultPayloadType; | |
| 164 settings->startBitrate = 100; | |
| 165 settings->minBitrate = VCM_MIN_BITRATE; | |
| 166 settings->maxBitrate = 0; | |
| 167 settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; | |
| 168 settings->width = VCM_DEFAULT_CODEC_WIDTH; | |
| 169 settings->height = VCM_DEFAULT_CODEC_HEIGHT; | |
| 170 settings->numberOfSimulcastStreams = 0; | |
| 171 settings->qpMax = 56; | |
| 172 settings->codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings(); | |
| 173 return true; | |
| 174 } | |
| 175 #endif | |
| 176 #ifdef VIDEOCODEC_H264 | |
| 177 case VCM_H264_IDX: { | |
| 178 strncpy(settings->plName, "H264", 5); | |
| 179 settings->codecType = kVideoCodecH264; | |
| 180 // 96 to 127 dynamic payload types for video codecs. | |
| 181 settings->plType = kDefaultPayloadType; | |
| 182 settings->startBitrate = kDefaultStartBitrateKbps; | |
| 183 settings->minBitrate = VCM_MIN_BITRATE; | |
| 184 settings->maxBitrate = 0; | |
| 185 settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; | |
| 186 settings->width = VCM_DEFAULT_CODEC_WIDTH; | |
| 187 settings->height = VCM_DEFAULT_CODEC_HEIGHT; | |
| 188 settings->numberOfSimulcastStreams = 0; | |
| 189 settings->qpMax = 56; | |
| 190 settings->codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings(); | |
| 191 return true; | |
| 192 } | |
| 193 #endif | |
| 194 #ifdef VIDEOCODEC_I420 | |
| 195 case VCM_I420_IDX: { | |
| 196 strncpy(settings->plName, "I420", 5); | |
| 197 settings->codecType = kVideoCodecI420; | |
| 198 // 96 to 127 dynamic payload types for video codecs. | |
| 199 settings->plType = kDefaultPayloadType; | |
| 200 // Bitrate needed for this size and framerate. | |
| 201 settings->startBitrate = 3 * VCM_DEFAULT_CODEC_WIDTH * | |
| 202 VCM_DEFAULT_CODEC_HEIGHT * 8 * | |
| 203 VCM_DEFAULT_FRAME_RATE / 1000 / 2; | |
| 204 settings->maxBitrate = settings->startBitrate; | |
| 205 settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; | |
| 206 settings->width = VCM_DEFAULT_CODEC_WIDTH; | |
| 207 settings->height = VCM_DEFAULT_CODEC_HEIGHT; | |
| 208 settings->minBitrate = VCM_MIN_BITRATE; | |
| 209 settings->numberOfSimulcastStreams = 0; | |
| 210 return true; | |
| 211 } | |
| 212 #endif | |
| 213 default: { | |
| 214 return false; | |
| 215 } | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 bool VCMCodecDataBase::Codec(VideoCodecType codec_type, | |
| 220 VideoCodec* settings) { | |
| 221 for (int i = 0; i < VCMCodecDataBase::NumberOfCodecs(); i++) { | |
| 222 const bool ret = VCMCodecDataBase::Codec(i, settings); | |
| 223 if (!ret) { | |
| 224 return false; | |
| 225 } | |
| 226 if (codec_type == settings->codecType) { | |
| 227 return true; | |
| 228 } | |
| 229 } | |
| 230 return false; | |
| 231 } | |
| 232 | |
| 233 void VCMCodecDataBase::ResetSender() { | |
| 234 DeleteEncoder(); | |
| 235 periodic_key_frames_ = false; | |
| 236 } | |
| 237 | |
| 238 // Assuming only one registered encoder - since only one used, no need for more. | |
| 239 bool VCMCodecDataBase::SetSendCodec(const VideoCodec* send_codec, | |
| 240 int number_of_cores, | |
| 241 size_t max_payload_size) { | |
| 242 RTC_DCHECK(send_codec); | |
| 243 if (max_payload_size == 0) { | |
| 244 max_payload_size = kDefaultPayloadSize; | |
| 245 } | |
| 246 RTC_DCHECK_GE(number_of_cores, 1); | |
| 247 RTC_DCHECK_GE(send_codec->plType, 1); | |
| 248 // Make sure the start bit rate is sane... | |
| 249 RTC_DCHECK_LE(send_codec->startBitrate, 1000000u); | |
| 250 RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown); | |
| 251 bool reset_required = pending_encoder_reset_; | |
| 252 if (number_of_cores_ != number_of_cores) { | |
| 253 number_of_cores_ = number_of_cores; | |
| 254 reset_required = true; | |
| 255 } | |
| 256 if (max_payload_size_ != max_payload_size) { | |
| 257 max_payload_size_ = max_payload_size; | |
| 258 reset_required = true; | |
| 259 } | |
| 260 | |
| 261 VideoCodec new_send_codec; | |
| 262 memcpy(&new_send_codec, send_codec, sizeof(new_send_codec)); | |
| 263 | |
| 264 if (new_send_codec.maxBitrate == 0) { | |
| 265 // max is one bit per pixel | |
| 266 new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) * | |
| 267 static_cast<int>(send_codec->width) * | |
| 268 static_cast<int>(send_codec->maxFramerate)) / 1000; | |
| 269 if (send_codec->startBitrate > new_send_codec.maxBitrate) { | |
| 270 // But if the user tries to set a higher start bit rate we will | |
| 271 // increase the max accordingly. | |
| 272 new_send_codec.maxBitrate = send_codec->startBitrate; | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 if (new_send_codec.startBitrate > new_send_codec.maxBitrate) | |
| 277 new_send_codec.startBitrate = new_send_codec.maxBitrate; | |
| 278 | |
| 279 if (!reset_required) { | |
| 280 reset_required = RequiresEncoderReset(new_send_codec); | |
| 281 } | |
| 282 | |
| 283 memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_)); | |
| 284 | |
| 285 if (!reset_required) { | |
| 286 encoded_frame_callback_->SetPayloadType(send_codec_.plType); | |
| 287 return true; | |
| 288 } | |
| 289 | |
| 290 // If encoder exists, will destroy it and create new one. | |
| 291 DeleteEncoder(); | |
| 292 RTC_DCHECK_EQ(encoder_payload_type_, send_codec_.plType) | |
| 293 << "Encoder not registered for payload type " << send_codec_.plType; | |
| 294 ptr_encoder_.reset( | |
| 295 new VCMGenericEncoder(external_encoder_, encoder_rate_observer_, | |
| 296 encoded_frame_callback_, internal_source_)); | |
| 297 encoded_frame_callback_->SetPayloadType(send_codec_.plType); | |
| 298 encoded_frame_callback_->SetInternalSource(internal_source_); | |
| 299 if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_, | |
| 300 max_payload_size_) < 0) { | |
| 301 LOG(LS_ERROR) << "Failed to initialize video encoder."; | |
| 302 DeleteEncoder(); | |
| 303 return false; | |
| 304 } | |
| 305 | |
| 306 // Intentionally don't check return value since the encoder registration | |
| 307 // shouldn't fail because the codec doesn't support changing the periodic key | |
| 308 // frame setting. | |
| 309 ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_); | |
| 310 | |
| 311 pending_encoder_reset_ = false; | |
| 312 | |
| 313 return true; | |
| 314 } | |
| 315 | |
| 316 bool VCMCodecDataBase::SendCodec(VideoCodec* current_send_codec) const { | |
| 317 if (!ptr_encoder_) { | |
| 318 return false; | |
| 319 } | |
| 320 memcpy(current_send_codec, &send_codec_, sizeof(VideoCodec)); | |
| 321 return true; | |
| 322 } | |
| 323 | |
| 324 VideoCodecType VCMCodecDataBase::SendCodec() const { | |
| 325 if (!ptr_encoder_) { | |
| 326 return kVideoCodecUnknown; | |
| 327 } | |
| 328 return send_codec_.codecType; | |
| 329 } | |
| 330 | |
| 331 bool VCMCodecDataBase::DeregisterExternalEncoder( | |
| 332 uint8_t payload_type, bool* was_send_codec) { | |
| 333 assert(was_send_codec); | |
| 334 *was_send_codec = false; | |
| 335 if (encoder_payload_type_ != payload_type) { | |
| 336 return false; | |
| 337 } | |
| 338 if (send_codec_.plType == payload_type) { | |
| 339 // De-register as send codec if needed. | |
| 340 DeleteEncoder(); | |
| 341 memset(&send_codec_, 0, sizeof(VideoCodec)); | |
| 342 *was_send_codec = true; | |
| 343 } | |
| 344 encoder_payload_type_ = 0; | |
| 345 external_encoder_ = NULL; | |
| 346 internal_source_ = false; | |
| 347 return true; | |
| 348 } | |
| 349 | |
| 350 void VCMCodecDataBase::RegisterExternalEncoder( | |
| 351 VideoEncoder* external_encoder, | |
| 352 uint8_t payload_type, | |
| 353 bool internal_source) { | |
| 354 // Since only one encoder can be used at a given time, only one external | |
| 355 // encoder can be registered/used. | |
| 356 external_encoder_ = external_encoder; | |
| 357 encoder_payload_type_ = payload_type; | |
| 358 internal_source_ = internal_source; | |
| 359 pending_encoder_reset_ = true; | |
| 360 } | |
| 361 | |
| 362 bool VCMCodecDataBase::RequiresEncoderReset(const VideoCodec& new_send_codec) { | |
| 363 if (ptr_encoder_ == NULL) { | |
| 364 return true; | |
| 365 } | |
| 366 | |
| 367 // Does not check startBitrate or maxFramerate | |
| 368 if (new_send_codec.codecType != send_codec_.codecType || | |
| 369 strcmp(new_send_codec.plName, send_codec_.plName) != 0 || | |
| 370 new_send_codec.plType != send_codec_.plType || | |
| 371 new_send_codec.width != send_codec_.width || | |
| 372 new_send_codec.height != send_codec_.height || | |
| 373 new_send_codec.maxBitrate != send_codec_.maxBitrate || | |
| 374 new_send_codec.minBitrate != send_codec_.minBitrate || | |
| 375 new_send_codec.qpMax != send_codec_.qpMax || | |
| 376 new_send_codec.numberOfSimulcastStreams != | |
| 377 send_codec_.numberOfSimulcastStreams || | |
| 378 new_send_codec.mode != send_codec_.mode || | |
| 379 new_send_codec.extra_options != send_codec_.extra_options) { | |
| 380 return true; | |
| 381 } | |
| 382 | |
| 383 switch (new_send_codec.codecType) { | |
| 384 case kVideoCodecVP8: | |
| 385 if (memcmp(&new_send_codec.codecSpecific.VP8, | |
| 386 &send_codec_.codecSpecific.VP8, | |
| 387 sizeof(new_send_codec.codecSpecific.VP8)) != 0) { | |
| 388 return true; | |
| 389 } | |
| 390 break; | |
| 391 case kVideoCodecVP9: | |
| 392 if (memcmp(&new_send_codec.codecSpecific.VP9, | |
| 393 &send_codec_.codecSpecific.VP9, | |
| 394 sizeof(new_send_codec.codecSpecific.VP9)) != 0) { | |
| 395 return true; | |
| 396 } | |
| 397 break; | |
| 398 case kVideoCodecH264: | |
| 399 if (memcmp(&new_send_codec.codecSpecific.H264, | |
| 400 &send_codec_.codecSpecific.H264, | |
| 401 sizeof(new_send_codec.codecSpecific.H264)) != 0) { | |
| 402 return true; | |
| 403 } | |
| 404 break; | |
| 405 case kVideoCodecGeneric: | |
| 406 break; | |
| 407 // Known codecs without payload-specifics | |
| 408 case kVideoCodecI420: | |
| 409 case kVideoCodecRED: | |
| 410 case kVideoCodecULPFEC: | |
| 411 break; | |
| 412 // Unknown codec type, reset just to be sure. | |
| 413 case kVideoCodecUnknown: | |
| 414 return true; | |
| 415 } | |
| 416 | |
| 417 if (new_send_codec.numberOfSimulcastStreams > 0) { | |
| 418 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams; | |
| 419 ++i) { | |
| 420 if (memcmp(&new_send_codec.simulcastStream[i], | |
| 421 &send_codec_.simulcastStream[i], | |
| 422 sizeof(new_send_codec.simulcastStream[i])) != | |
| 423 0) { | |
| 424 return true; | |
| 425 } | |
| 426 } | |
| 427 } | |
| 428 return false; | |
| 429 } | |
| 430 | |
| 431 VCMGenericEncoder* VCMCodecDataBase::GetEncoder() { | |
| 432 return ptr_encoder_.get(); | |
| 433 } | |
| 434 | |
| 435 bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) { | |
| 436 periodic_key_frames_ = enable; | |
| 437 if (ptr_encoder_) { | |
| 438 return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0); | |
| 439 } | |
| 440 return true; | |
| 441 } | |
| 442 | |
| 443 void VCMCodecDataBase::ResetReceiver() { | |
| 444 ReleaseDecoder(ptr_decoder_); | |
| 445 ptr_decoder_ = NULL; | |
| 446 memset(&receive_codec_, 0, sizeof(VideoCodec)); | |
| 447 while (!dec_map_.empty()) { | |
| 448 DecoderMap::iterator it = dec_map_.begin(); | |
| 449 delete (*it).second; | |
| 450 dec_map_.erase(it); | |
| 451 } | |
| 452 while (!dec_external_map_.empty()) { | |
| 453 ExternalDecoderMap::iterator external_it = dec_external_map_.begin(); | |
| 454 delete (*external_it).second; | |
| 455 dec_external_map_.erase(external_it); | |
| 456 } | |
| 457 } | |
| 458 | |
| 459 bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { | |
| 460 ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); | |
| 461 if (it == dec_external_map_.end()) { | |
| 462 // Not found | |
| 463 return false; | |
| 464 } | |
| 465 // We can't use payload_type to check if the decoder is currently in use, | |
| 466 // because payload type may be out of date (e.g. before we decode the first | |
| 467 // frame after RegisterReceiveCodec) | |
| 468 if (ptr_decoder_ != NULL && | |
| 469 &ptr_decoder_->_decoder == (*it).second->external_decoder_instance) { | |
| 470 // Release it if it was registered and in use. | |
| 471 ReleaseDecoder(ptr_decoder_); | |
| 472 ptr_decoder_ = NULL; | |
| 473 } | |
| 474 DeregisterReceiveCodec(payload_type); | |
| 475 delete (*it).second; | |
| 476 dec_external_map_.erase(it); | |
| 477 return true; | |
| 478 } | |
| 479 | |
| 480 // Add the external encoder object to the list of external decoders. | |
| 481 // Won't be registered as a receive codec until RegisterReceiveCodec is called. | |
| 482 bool VCMCodecDataBase::RegisterExternalDecoder( | |
| 483 VideoDecoder* external_decoder, | |
| 484 uint8_t payload_type, | |
| 485 bool internal_render_timing) { | |
| 486 // Check if payload value already exists, if so - erase old and insert new. | |
| 487 VCMExtDecoderMapItem* ext_decoder = new VCMExtDecoderMapItem( | |
| 488 external_decoder, payload_type, internal_render_timing); | |
| 489 if (!ext_decoder) { | |
| 490 return false; | |
| 491 } | |
| 492 DeregisterExternalDecoder(payload_type); | |
| 493 dec_external_map_[payload_type] = ext_decoder; | |
| 494 return true; | |
| 495 } | |
| 496 | |
| 497 bool VCMCodecDataBase::DecoderRegistered() const { | |
| 498 return !dec_map_.empty(); | |
| 499 } | |
| 500 | |
| 501 bool VCMCodecDataBase::RegisterReceiveCodec( | |
| 502 const VideoCodec* receive_codec, | |
| 503 int number_of_cores, | |
| 504 bool require_key_frame) { | |
| 505 if (number_of_cores < 0) { | |
| 506 return false; | |
| 507 } | |
| 508 // Check if payload value already exists, if so - erase old and insert new. | |
| 509 DeregisterReceiveCodec(receive_codec->plType); | |
| 510 if (receive_codec->codecType == kVideoCodecUnknown) { | |
| 511 return false; | |
| 512 } | |
| 513 VideoCodec* new_receive_codec = new VideoCodec(*receive_codec); | |
| 514 dec_map_[receive_codec->plType] = new VCMDecoderMapItem(new_receive_codec, | |
| 515 number_of_cores, | |
| 516 require_key_frame); | |
| 517 return true; | |
| 518 } | |
| 519 | |
| 520 bool VCMCodecDataBase::DeregisterReceiveCodec( | |
| 521 uint8_t payload_type) { | |
| 522 DecoderMap::iterator it = dec_map_.find(payload_type); | |
| 523 if (it == dec_map_.end()) { | |
| 524 return false; | |
| 525 } | |
| 526 VCMDecoderMapItem* dec_item = (*it).second; | |
| 527 delete dec_item; | |
| 528 dec_map_.erase(it); | |
| 529 if (receive_codec_.plType == payload_type) { | |
| 530 // This codec is currently in use. | |
| 531 memset(&receive_codec_, 0, sizeof(VideoCodec)); | |
| 532 } | |
| 533 return true; | |
| 534 } | |
| 535 | |
| 536 bool VCMCodecDataBase::ReceiveCodec(VideoCodec* current_receive_codec) const { | |
| 537 assert(current_receive_codec); | |
| 538 if (!ptr_decoder_) { | |
| 539 return false; | |
| 540 } | |
| 541 memcpy(current_receive_codec, &receive_codec_, sizeof(VideoCodec)); | |
| 542 return true; | |
| 543 } | |
| 544 | |
| 545 VideoCodecType VCMCodecDataBase::ReceiveCodec() const { | |
| 546 if (!ptr_decoder_) { | |
| 547 return kVideoCodecUnknown; | |
| 548 } | |
| 549 return receive_codec_.codecType; | |
| 550 } | |
| 551 | |
| 552 VCMGenericDecoder* VCMCodecDataBase::GetDecoder( | |
| 553 uint8_t payload_type, VCMDecodedFrameCallback* decoded_frame_callback) { | |
| 554 if (payload_type == receive_codec_.plType || payload_type == 0) { | |
| 555 return ptr_decoder_; | |
| 556 } | |
| 557 // Check for exisitng decoder, if exists - delete. | |
| 558 if (ptr_decoder_) { | |
| 559 ReleaseDecoder(ptr_decoder_); | |
| 560 ptr_decoder_ = NULL; | |
| 561 memset(&receive_codec_, 0, sizeof(VideoCodec)); | |
| 562 } | |
| 563 ptr_decoder_ = CreateAndInitDecoder(payload_type, &receive_codec_); | |
| 564 if (!ptr_decoder_) { | |
| 565 return NULL; | |
| 566 } | |
| 567 VCMReceiveCallback* callback = decoded_frame_callback->UserReceiveCallback(); | |
| 568 if (callback) callback->OnIncomingPayloadType(receive_codec_.plType); | |
| 569 if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) | |
| 570 < 0) { | |
| 571 ReleaseDecoder(ptr_decoder_); | |
| 572 ptr_decoder_ = NULL; | |
| 573 memset(&receive_codec_, 0, sizeof(VideoCodec)); | |
| 574 return NULL; | |
| 575 } | |
| 576 return ptr_decoder_; | |
| 577 } | |
| 578 | |
| 579 void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const { | |
| 580 if (decoder) { | |
| 581 assert(&decoder->_decoder); | |
| 582 decoder->Release(); | |
| 583 if (!decoder->External()) { | |
| 584 delete &decoder->_decoder; | |
| 585 } | |
| 586 delete decoder; | |
| 587 } | |
| 588 } | |
| 589 | |
| 590 bool VCMCodecDataBase::SupportsRenderScheduling() const { | |
| 591 const VCMExtDecoderMapItem* ext_item = FindExternalDecoderItem( | |
| 592 receive_codec_.plType); | |
| 593 if (ext_item == nullptr) | |
| 594 return true; | |
| 595 return ext_item->internal_render_timing; | |
| 596 } | |
| 597 | |
| 598 bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { | |
| 599 return send_codec_.width == width && send_codec_.height == height; | |
| 600 } | |
| 601 | |
| 602 VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder( | |
| 603 uint8_t payload_type, | |
| 604 VideoCodec* new_codec) const { | |
| 605 assert(new_codec); | |
| 606 const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); | |
| 607 if (!decoder_item) { | |
| 608 LOG(LS_ERROR) << "Can't find a decoder associated with payload type: " | |
| 609 << static_cast<int>(payload_type); | |
| 610 return NULL; | |
| 611 } | |
| 612 VCMGenericDecoder* ptr_decoder = NULL; | |
| 613 const VCMExtDecoderMapItem* external_dec_item = | |
| 614 FindExternalDecoderItem(payload_type); | |
| 615 if (external_dec_item) { | |
| 616 // External codec. | |
| 617 ptr_decoder = new VCMGenericDecoder( | |
| 618 *external_dec_item->external_decoder_instance, true); | |
| 619 } else { | |
| 620 // Create decoder. | |
| 621 ptr_decoder = CreateDecoder(decoder_item->settings->codecType); | |
| 622 } | |
| 623 if (!ptr_decoder) | |
| 624 return NULL; | |
| 625 | |
| 626 if (ptr_decoder->InitDecode(decoder_item->settings.get(), | |
| 627 decoder_item->number_of_cores) < 0) { | |
| 628 ReleaseDecoder(ptr_decoder); | |
| 629 return NULL; | |
| 630 } | |
| 631 memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); | |
| 632 return ptr_decoder; | |
| 633 } | |
| 634 | |
| 635 void VCMCodecDataBase::DeleteEncoder() { | |
| 636 if (!ptr_encoder_) | |
| 637 return; | |
| 638 ptr_encoder_->Release(); | |
| 639 ptr_encoder_.reset(); | |
| 640 } | |
| 641 | |
| 642 VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const { | |
| 643 switch (type) { | |
| 644 #ifdef VIDEOCODEC_VP8 | |
| 645 case kVideoCodecVP8: | |
| 646 return new VCMGenericDecoder(*(VP8Decoder::Create())); | |
| 647 #endif | |
| 648 #ifdef VIDEOCODEC_VP9 | |
| 649 case kVideoCodecVP9: | |
| 650 return new VCMGenericDecoder(*(VP9Decoder::Create())); | |
| 651 #endif | |
| 652 #ifdef VIDEOCODEC_I420 | |
| 653 case kVideoCodecI420: | |
| 654 return new VCMGenericDecoder(*(new I420Decoder)); | |
| 655 #endif | |
| 656 #ifdef VIDEOCODEC_H264 | |
| 657 case kVideoCodecH264: | |
| 658 if (H264Decoder::IsSupported()) { | |
| 659 return new VCMGenericDecoder(*(H264Decoder::Create())); | |
| 660 } | |
| 661 break; | |
| 662 #endif | |
| 663 default: | |
| 664 break; | |
| 665 } | |
| 666 LOG(LS_WARNING) << "No internal decoder of this type exists."; | |
| 667 return NULL; | |
| 668 } | |
| 669 | |
| 670 const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( | |
| 671 uint8_t payload_type) const { | |
| 672 DecoderMap::const_iterator it = dec_map_.find(payload_type); | |
| 673 if (it != dec_map_.end()) { | |
| 674 return (*it).second; | |
| 675 } | |
| 676 return NULL; | |
| 677 } | |
| 678 | |
| 679 const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( | |
| 680 uint8_t payload_type) const { | |
| 681 ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); | |
| 682 if (it != dec_external_map_.end()) { | |
| 683 return (*it).second; | |
| 684 } | |
| 685 return NULL; | |
| 686 } | |
| 687 } // namespace webrtc | |
| OLD | NEW |