diff --git a/src/modules/video_coding/main/source/codec_database.cc b/src/modules/video_coding/main/source/codec_database.cc index fbb983687..2953e0215 100644 --- a/src/modules/video_coding/main/source/codec_database.cc +++ b/src/modules/video_coding/main/source/codec_database.cc @@ -8,715 +8,568 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "codec_database.h" +#include "modules/video_coding/main/source/codec_database.h" #include -#include "../../../../engine_configurations.h" -#include "internal_defines.h" -#include "trace.h" - -#if defined(_WIN32) -// Don't warn for strncpy being unsecure. -// switch statement contains 'default' but no 'case' labels -#pragma warning(disable:4996; disable:4065) -#endif - -// Supported codecs -#ifdef VIDEOCODEC_VP8 -#include "vp8.h" -#endif +#include "engine_configurations.h" #ifdef VIDEOCODEC_I420 -#include "i420.h" +#include "modules/video_coding/codecs/i420/main/interface/i420.h" #endif +#ifdef VIDEOCODEC_VP8 +#include "modules/video_coding/codecs/vp8/include/vp8.h" +#endif +#include "modules/video_coding/main/source/internal_defines.h" +#include "system_wrappers/interface/trace.h" -namespace webrtc -{ +namespace webrtc { VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, - WebRtc_UWord32 numberOfCores, - bool requireKeyFrame) -: -_settings(settings), -_numberOfCores(numberOfCores), -_requireKeyFrame(requireKeyFrame) -{ + int number_of_cores, + bool require_key_frame) + : settings(settings), + number_of_cores(number_of_cores), + require_key_frame(require_key_frame) { + assert(number_of_cores >= 0); } -VCMExtDecoderMapItem::VCMExtDecoderMapItem(VideoDecoder* externalDecoderInstance, - WebRtc_UWord8 payloadType, - bool internalRenderTiming) -: -_payloadType(payloadType), -_externalDecoderInstance(externalDecoderInstance), -_internalRenderTiming(internalRenderTiming) -{ +VCMExtDecoderMapItem::VCMExtDecoderMapItem( + VideoDecoder* external_decoder_instance, + uint8_t payload_type, + bool internal_render_timing) + : payload_type(payload_type), + external_decoder_instance(external_decoder_instance), + internal_render_timing(internal_render_timing) { } -VCMCodecDataBase::VCMCodecDataBase(WebRtc_Word32 id): -_id(id), -_numberOfCores(0), -_maxPayloadSize(kDefaultPayloadSize), -_periodicKeyFrames(false), -_currentEncIsExternal(false), -_sendCodec(), -_receiveCodec(), -_externalPayloadType(0), -_externalEncoder(NULL), -_internalSource(false), -_ptrEncoder(NULL), -_ptrDecoder(NULL), -_currentDecIsExternal(false), -_decMap(), -_decExternalMap() -{ - // +VCMCodecDataBase::VCMCodecDataBase(int id) + : id_(id), + number_of_cores_(0), + max_payload_size_(kDefaultPayloadSize), + periodic_key_frames_(false), + current_enc_is_external_(false), + send_codec_(), + receive_codec_(), + external_payload_type_(0), + external_encoder_(NULL), + internal_source_(false), + ptr_encoder_(NULL), + ptr_decoder_(NULL), + current_dec_is_external_(false), + dec_map_(), + dec_external_map_() { } -VCMCodecDataBase::~VCMCodecDataBase() -{ - Reset(); +VCMCodecDataBase::~VCMCodecDataBase() { + ResetSender(); + ResetReceiver(); } -WebRtc_Word32 -VCMCodecDataBase::Reset() -{ - WebRtc_Word32 ret = ResetReceiver(); - if (ret < 0) - { - return ret; - } - ret = ResetSender(); - if (ret < 0) - { - return ret; - } - return VCM_OK; +int VCMCodecDataBase::NumberOfCodecs() { + return VCM_NUM_VIDEO_CODECS_AVAILABLE; } -WebRtc_Word32 -VCMCodecDataBase::ResetSender() -{ - DeleteEncoder(); - _periodicKeyFrames = false; - return VCM_OK; -} - -VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( - const VideoCodecType type) const { - - switch(type) - { +bool VCMCodecDataBase::Codec(int list_id, + VideoCodec* settings) { + if (!settings) { + return false; + } + if (list_id >= VCM_NUM_VIDEO_CODECS_AVAILABLE) { + return false; + } + memset(settings, 0, sizeof(VideoCodec)); + switch (list_id) { #ifdef VIDEOCODEC_VP8 - case kVideoCodecVP8: - return new VCMGenericEncoder(*(VP8Encoder::Create())); + case VCM_VP8_IDX: { + strncpy(settings->plName, "VP8", 4); + settings->codecType = kVideoCodecVP8; + // 96 to 127 dynamic payload types for video codecs. + settings->plType = VCM_VP8_PAYLOAD_TYPE; + settings->startBitrate = 100; + settings->minBitrate = VCM_MIN_BITRATE; + settings->maxBitrate = 0; + settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; + settings->width = VCM_DEFAULT_CODEC_WIDTH; + settings->height = VCM_DEFAULT_CODEC_HEIGHT; + settings->numberOfSimulcastStreams = 0; + settings->codecSpecific.VP8.resilience = kResilientStream; + settings->codecSpecific.VP8.numberOfTemporalLayers = 1; + settings->codecSpecific.VP8.denoisingOn = true; + settings->codecSpecific.VP8.errorConcealmentOn = false; + settings->codecSpecific.VP8.automaticResizeOn = false; + settings->codecSpecific.VP8.frameDroppingOn = true; + return true; + } #endif #ifdef VIDEOCODEC_I420 - case kVideoCodecI420: - return new VCMGenericEncoder(*(new I420Encoder)); + case VCM_I420_IDX: { + strncpy(settings->plName, "I420", 5); + settings->codecType = kVideoCodecI420; + // 96 to 127 dynamic payload types for video codecs. + settings->plType = VCM_I420_PAYLOAD_TYPE; + // Bitrate needed for this size and framerate. + settings->startBitrate = 3 * VCM_DEFAULT_CODEC_WIDTH * + VCM_DEFAULT_CODEC_HEIGHT * 8 * + VCM_DEFAULT_FRAME_RATE / 1000 / 2; + settings->maxBitrate = settings->startBitrate; + settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; + settings->width = VCM_DEFAULT_CODEC_WIDTH; + settings->height = VCM_DEFAULT_CODEC_HEIGHT; + settings->minBitrate = VCM_MIN_BITRATE; + settings->numberOfSimulcastStreams = 0; + return true; + } #endif - default: - return NULL; + default: { + return false; } + } } -void -VCMCodecDataBase::DeleteEncoder() -{ - if (_ptrEncoder) - { - _ptrEncoder->Release(); - if (!_currentEncIsExternal) - { - delete &_ptrEncoder->_encoder; - } - delete _ptrEncoder; - _ptrEncoder = NULL; +bool VCMCodecDataBase::Codec(VideoCodecType codec_type, + VideoCodec* settings) { + for (int i = 0; i < VCMCodecDataBase::NumberOfCodecs(); i++) { + const bool ret = VCMCodecDataBase::Codec(i, settings); + if (!ret) { + return false; } + if (codec_type == settings->codecType) { + return true; + } + } + return false; } -WebRtc_UWord8 -VCMCodecDataBase::NumberOfCodecs() -{ - return VCM_NUM_VIDEO_CODECS_AVAILABLE; +void VCMCodecDataBase::ResetSender() { + DeleteEncoder(); + periodic_key_frames_ = false; } -WebRtc_Word32 -VCMCodecDataBase::Codec(WebRtc_UWord8 listId, VideoCodec *settings) -{ - if (settings == NULL) - { - return VCM_PARAMETER_ERROR; - } +// Assuming only one registered encoder - since only one used, no need for more. +bool VCMCodecDataBase::RegisterSendCodec( + const VideoCodec* send_codec, + int number_of_cores, + int max_payload_size) { + if (!send_codec) { + return false; + } + if (max_payload_size <= 0) { + max_payload_size = kDefaultPayloadSize; + } + if (number_of_cores < 0 || number_of_cores > 32) { + return false; + } + if (send_codec->plType <= 0) { + return false; + } + // Make sure the start bit rate is sane... + if (send_codec->startBitrate > 1000000) { + return false; + } + if (send_codec->codecType == kVideoCodecUnknown) { + return false; + } + number_of_cores_ = number_of_cores; + max_payload_size_ = max_payload_size; - if (listId >= VCM_NUM_VIDEO_CODECS_AVAILABLE) - { - return VCM_PARAMETER_ERROR; - } - memset(settings, 0, sizeof(VideoCodec)); - switch (listId) - { -#ifdef VIDEOCODEC_VP8 - case VCM_VP8_IDX: - { - strncpy(settings->plName, "VP8", 4); - settings->codecType = kVideoCodecVP8; - // 96 to 127 dynamic payload types for video codecs - settings->plType = VCM_VP8_PAYLOAD_TYPE; - settings->startBitrate = 100; - settings->minBitrate = VCM_MIN_BITRATE; - settings->maxBitrate = 0; - settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; - settings->width = VCM_DEFAULT_CODEC_WIDTH; - settings->height = VCM_DEFAULT_CODEC_HEIGHT; - settings->numberOfSimulcastStreams = 0; - settings->codecSpecific.VP8.resilience = kResilientStream; - settings->codecSpecific.VP8.numberOfTemporalLayers = 1; - settings->codecSpecific.VP8.denoisingOn = true; - settings->codecSpecific.VP8.errorConcealmentOn = false; - settings->codecSpecific.VP8.automaticResizeOn = false; - settings->codecSpecific.VP8.frameDroppingOn = true; - break; - } -#endif -#ifdef VIDEOCODEC_I420 - case VCM_I420_IDX: - { - strncpy(settings->plName, "I420", 5); - settings->codecType = kVideoCodecI420; - // 96 to 127 dynamic payload types for video codecs - settings->plType = VCM_I420_PAYLOAD_TYPE; - // Bitrate needed for this size and framerate - settings->startBitrate = 3*VCM_DEFAULT_CODEC_WIDTH* - VCM_DEFAULT_CODEC_HEIGHT*8* - VCM_DEFAULT_FRAME_RATE/1000/2; - settings->maxBitrate = settings->startBitrate; - settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; - settings->width = VCM_DEFAULT_CODEC_WIDTH; - settings->height = VCM_DEFAULT_CODEC_HEIGHT; - settings->minBitrate = VCM_MIN_BITRATE; - settings->numberOfSimulcastStreams = 0; - break; - } -#endif - default: - { - return VCM_PARAMETER_ERROR; - } - } + memcpy(&send_codec_, send_codec, sizeof(VideoCodec)); - return VCM_OK; + if (send_codec_.maxBitrate == 0) { + // max is one bit per pixel + send_codec_.maxBitrate = (static_cast(send_codec_.height) * + static_cast(send_codec_.width) * + static_cast(send_codec_.maxFramerate)) / 1000; + if (send_codec_.startBitrate > send_codec_.maxBitrate) { + // But if the user tries to set a higher start bit rate we will + // increase the max accordingly. + send_codec_.maxBitrate = send_codec_.startBitrate; + } + } + + return true; } -WebRtc_Word32 -VCMCodecDataBase::Codec(VideoCodecType codecType, VideoCodec* settings) -{ - for (int i = 0; i < VCMCodecDataBase::NumberOfCodecs(); i++) - { - const WebRtc_Word32 ret = VCMCodecDataBase::Codec(i, settings); - if (ret != VCM_OK) - { - return ret; - } - if (codecType == settings->codecType) - { - return VCM_OK; - } - } - return VCM_PARAMETER_ERROR; +bool VCMCodecDataBase::SendCodec(VideoCodec* current_send_codec) const { + WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCoding, VCMId(id_), + "SendCodec"); + if (!ptr_encoder_) { + return false; + } + memcpy(current_send_codec, &send_codec_, sizeof(VideoCodec)); + return true; } -// assuming only one registered encoder - since only one used, no need for more -WebRtc_Word32 -VCMCodecDataBase::RegisterSendCodec(const VideoCodec* sendCodec, - WebRtc_UWord32 numberOfCores, - WebRtc_UWord32 maxPayloadSize) - { - if (sendCodec == NULL) - { - return VCM_UNINITIALIZED; - } - if (maxPayloadSize == 0) - { - maxPayloadSize = kDefaultPayloadSize; - } - if (numberOfCores > 32) - { - return VCM_PARAMETER_ERROR; - } - if (sendCodec->plType <= 0) - { - return VCM_PARAMETER_ERROR; - } - // Make sure the start bit rate is sane... - if (sendCodec->startBitrate > 1000000) - { - return VCM_PARAMETER_ERROR; - } - if (sendCodec->codecType == kVideoCodecUnknown) - { - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; - } - _numberOfCores = numberOfCores; - _maxPayloadSize = maxPayloadSize; - - memcpy(&_sendCodec, sendCodec, sizeof(VideoCodec)); - - if (_sendCodec.maxBitrate == 0) - { - // max is one bit per pixel - _sendCodec.maxBitrate = ((WebRtc_Word32)_sendCodec.height * - (WebRtc_Word32)_sendCodec.width * - (WebRtc_Word32)_sendCodec.maxFramerate) / 1000; - if (_sendCodec.startBitrate > _sendCodec.maxBitrate) - { - // but if the customer tries to set a higher start bit rate we will increase - // the max accordingly - _sendCodec.maxBitrate = _sendCodec.startBitrate; - } - } - - return VCM_OK; +VideoCodecType VCMCodecDataBase::SendCodec() const { + WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCoding, VCMId(id_), + "SendCodec type"); + if (!ptr_encoder_) { + return kVideoCodecUnknown; + } + return send_codec_.codecType; } -WebRtc_Word32 -VCMCodecDataBase::SendCodec(VideoCodec* currentSendCodec) const -{ - WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCoding, VCMId(_id), "SendCodec"); - - if(_ptrEncoder == NULL) - { - return VCM_UNINITIALIZED; - } - memcpy(currentSendCodec, &_sendCodec, sizeof(VideoCodec)); - return VCM_OK; -} - -VideoCodecType -VCMCodecDataBase::SendCodec() const -{ - WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCoding, VCMId(_id), - "SendCodec type"); - if (_ptrEncoder == NULL) - { - return kVideoCodecUnknown; - } - return _sendCodec.codecType; -} - -WebRtc_Word32 -VCMCodecDataBase::DeRegisterExternalEncoder(WebRtc_UWord8 payloadType, bool& wasSendCodec) -{ - wasSendCodec = false; - if (_externalPayloadType != payloadType) - { - return VCM_PARAMETER_ERROR; - } - if (_sendCodec.plType == payloadType) - { - //De-register as send codec if needed - DeleteEncoder(); - memset(&_sendCodec, 0, sizeof(VideoCodec)); - _currentEncIsExternal = false; - wasSendCodec = true; - } - _externalPayloadType = 0; - _externalEncoder = NULL; - _internalSource = false; - return VCM_OK; -} - -WebRtc_Word32 -VCMCodecDataBase::RegisterExternalEncoder(VideoEncoder* externalEncoder, - WebRtc_UWord8 payloadType, - bool internalSource) -{ - // since only one encoder can be used at a given time, - // only one external encoder can be registered/used - _externalEncoder = externalEncoder; - _externalPayloadType = payloadType; - _internalSource = internalSource; - - return VCM_OK; -} - -VCMGenericEncoder* -VCMCodecDataBase::SetEncoder(const VideoCodec* settings, - VCMEncodedFrameCallback* VCMencodedFrameCallback) - -{ - // if encoder exists, will destroy it and create new one +bool VCMCodecDataBase::DeregisterExternalEncoder( + uint8_t payload_type, bool* was_send_codec) { + assert(was_send_codec); + *was_send_codec = false; + if (external_payload_type_ != payload_type) { + return false; + } + if (send_codec_.plType == payload_type) { + // De-register as send codec if needed. DeleteEncoder(); - - if (settings->plType == _externalPayloadType) - { - // External encoder - _ptrEncoder = new VCMGenericEncoder(*_externalEncoder, _internalSource); - _currentEncIsExternal = true; - } - else - { - _ptrEncoder = CreateEncoder(settings->codecType); - _currentEncIsExternal = false; - } - VCMencodedFrameCallback->SetPayloadType(settings->plType); - - if (_ptrEncoder == NULL) - { - WEBRTC_TRACE(webrtc::kTraceError, - webrtc::kTraceVideoCoding, - VCMId(_id), - "Failed to create encoder: %s.", - settings->plName); - return NULL; - } - if (_ptrEncoder->InitEncode(settings, _numberOfCores, _maxPayloadSize) < 0) - { - WEBRTC_TRACE(webrtc::kTraceError, - webrtc::kTraceVideoCoding, - VCMId(_id), - "Failed to initialize encoder: %s.", - settings->plName); - DeleteEncoder(); - return NULL; - } - else if (_ptrEncoder->RegisterEncodeCallback(VCMencodedFrameCallback) < 0) - { - DeleteEncoder(); - return NULL; - } - // Intentionally don't check return value since the encoder registration - // shouldn't fail because the codec doesn't support changing the - // periodic key frame setting. - _ptrEncoder->SetPeriodicKeyFrames(_periodicKeyFrames); - return _ptrEncoder; + memset(&send_codec_, 0, sizeof(VideoCodec)); + current_enc_is_external_ = false; + *was_send_codec = true; + } + external_payload_type_ = 0; + external_encoder_ = NULL; + internal_source_ = false; + return true; } -WebRtc_Word32 -VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) -{ - _periodicKeyFrames = enable; - if (_ptrEncoder != NULL) - { - return _ptrEncoder->SetPeriodicKeyFrames(_periodicKeyFrames); - } - return VCM_OK; +void VCMCodecDataBase::RegisterExternalEncoder( + VideoEncoder* external_encoder, + uint8_t payload_type, + bool internal_source) { + // Since only one encoder can be used at a given time, only one external + // encoder can be registered/used. + external_encoder_ = external_encoder; + external_payload_type_ = payload_type; + internal_source_ = internal_source; } -WebRtc_Word32 -VCMCodecDataBase::RegisterReceiveCodec(const VideoCodec* receiveCodec, - WebRtc_UWord32 numberOfCores, - bool requireKeyFrame) -{ - WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCoding, VCMId(_id), - "Codec: %s, Payload type %d, Height %d, Width %d, Bitrate %d, Framerate %d.", - receiveCodec->plName, receiveCodec->plType, - receiveCodec->height, receiveCodec->width, - receiveCodec->startBitrate, receiveCodec->maxFramerate); - - // check if payload value already exists, if so - erase old and insert new - DeRegisterReceiveCodec(receiveCodec->plType); - if (receiveCodec->codecType == kVideoCodecUnknown) - { - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; - } - VideoCodec* newReceiveCodec = new VideoCodec(*receiveCodec); - _decMap[receiveCodec->plType] = - new VCMDecoderMapItem(newReceiveCodec, numberOfCores, requireKeyFrame); - - return VCM_OK; +VCMGenericEncoder* VCMCodecDataBase::GetEncoder( + const VideoCodec* settings, + VCMEncodedFrameCallback* encoded_frame_callback) { + // If encoder exists, will destroy it and create new one. + DeleteEncoder(); + if (settings->plType == external_payload_type_) { + // External encoder. + ptr_encoder_ = new VCMGenericEncoder(*external_encoder_, internal_source_); + current_enc_is_external_ = true; + } else { + ptr_encoder_ = CreateEncoder(settings->codecType); + current_enc_is_external_ = false; + } + encoded_frame_callback->SetPayloadType(settings->plType); + if (!ptr_encoder_) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + VCMId(id_), + "Failed to create encoder: %s.", + settings->plName); + return NULL; + } + if (ptr_encoder_->InitEncode(settings, number_of_cores_, max_payload_size_) < + 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + VCMId(id_), + "Failed to initialize encoder: %s.", + settings->plName); + DeleteEncoder(); + return NULL; + } else if (ptr_encoder_->RegisterEncodeCallback(encoded_frame_callback) < + 0) { + DeleteEncoder(); + return NULL; + } + // Intentionally don't check return value since the encoder registration + // shouldn't fail because the codec doesn't support changing the periodic key + // frame setting. + ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_); + return ptr_encoder_; } -WebRtc_Word32 VCMCodecDataBase::DeRegisterReceiveCodec( - WebRtc_UWord8 payloadType) -{ - DecoderMap::iterator it = _decMap.find(payloadType); - if (it == _decMap.end()) - { - return VCM_PARAMETER_ERROR; - } - VCMDecoderMapItem* decItem = (*it).second; - delete decItem->_settings; - delete decItem; - _decMap.erase(it); - if (_receiveCodec.plType == payloadType) - { - // This codec is currently in use. - memset(&_receiveCodec, 0, sizeof(VideoCodec)); - _currentDecIsExternal = false; - } - return VCM_OK; +bool VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) { + periodic_key_frames_ = enable; + if (ptr_encoder_) { + return (ptr_encoder_->SetPeriodicKeyFrames(periodic_key_frames_) == 0); + } + return true; } -WebRtc_Word32 -VCMCodecDataBase::ResetReceiver() -{ - ReleaseDecoder(_ptrDecoder); - _ptrDecoder = NULL; - memset(&_receiveCodec, 0, sizeof(VideoCodec)); - DecoderMap::iterator it = _decMap.begin(); - while (it != _decMap.end()) { - if ((*it).second->_settings != NULL) - { - delete (*it).second->_settings; - } - delete (*it).second; - _decMap.erase(it); - it = _decMap.begin(); - } - ExternalDecoderMap::iterator exterit = _decExternalMap.begin(); - while (exterit != _decExternalMap.end()) { - delete (*exterit).second; - _decExternalMap.erase(exterit); - exterit = _decExternalMap.begin(); - } - - _currentDecIsExternal = false; - return VCM_OK; -} - -WebRtc_Word32 -VCMCodecDataBase::DeRegisterExternalDecoder(WebRtc_UWord8 payloadType) -{ - ExternalDecoderMap::iterator it = _decExternalMap.find(payloadType); - if (it == _decExternalMap.end()) - { - // Not found - return VCM_PARAMETER_ERROR; - } - if (_receiveCodec.plType == payloadType) - { - // Release it if it was registered and in use - ReleaseDecoder(_ptrDecoder); - _ptrDecoder = NULL; - } - DeRegisterReceiveCodec(payloadType); +void VCMCodecDataBase::ResetReceiver() { + ReleaseDecoder(ptr_decoder_); + ptr_decoder_ = NULL; + memset(&receive_codec_, 0, sizeof(VideoCodec)); + while (!dec_map_.empty()) { + DecoderMap::iterator it = dec_map_.begin(); delete (*it).second; - _decExternalMap.erase(it); - return VCM_OK; + dec_map_.erase(it); + } + while (!dec_external_map_.empty()) { + ExternalDecoderMap::iterator external_it = dec_external_map_.begin(); + delete (*external_it).second; + dec_external_map_.erase(external_it); + } + current_dec_is_external_ = false; +} + +bool VCMCodecDataBase::DeregisterExternalDecoder(uint8_t payload_type) { + ExternalDecoderMap::iterator it = dec_external_map_.find(payload_type); + if (it == dec_external_map_.end()) { + // Not found + return false; + } + if (receive_codec_.plType == payload_type) { + // Release it if it was registered and in use. + ReleaseDecoder(ptr_decoder_); + ptr_decoder_ = NULL; + } + DeregisterReceiveCodec(payload_type); + delete (*it).second; + dec_external_map_.erase(it); + return true; } // Add the external encoder object to the list of external decoders. // Won't be registered as a receive codec until RegisterReceiveCodec is called. -WebRtc_Word32 -VCMCodecDataBase::RegisterExternalDecoder(VideoDecoder* externalDecoder, - WebRtc_UWord8 payloadType, - bool internalRenderTiming) -{ - // check if payload value already exists, if so - erase old and insert new - VCMExtDecoderMapItem* extDecoder = new VCMExtDecoderMapItem(externalDecoder, - payloadType, - internalRenderTiming); - if (extDecoder == NULL) - { - return VCM_MEMORY; - } - DeRegisterExternalDecoder(payloadType); - _decExternalMap[payloadType] = extDecoder; - - return VCM_OK; +bool VCMCodecDataBase::RegisterExternalDecoder( + VideoDecoder* external_decoder, + uint8_t payload_type, + bool internal_render_timing) { + // Check if payload value already exists, if so - erase old and insert new. + VCMExtDecoderMapItem* ext_decoder = new VCMExtDecoderMapItem( + external_decoder, payload_type, internal_render_timing); + if (!ext_decoder) { + return false; + } + DeregisterExternalDecoder(payload_type); + dec_external_map_[payload_type] = ext_decoder; + return true; } -bool -VCMCodecDataBase::DecoderRegistered() const -{ - return !_decMap.empty(); +bool VCMCodecDataBase::DecoderRegistered() const { + return !dec_map_.empty(); } -WebRtc_Word32 -VCMCodecDataBase::ReceiveCodec(VideoCodec* currentReceiveCodec) const -{ - if (_ptrDecoder == NULL) - { - return VCM_NO_FRAME_DECODED; - } - memcpy(currentReceiveCodec, &_receiveCodec, sizeof(VideoCodec)); - return VCM_OK; +bool VCMCodecDataBase::RegisterReceiveCodec( + const VideoCodec* receive_codec, + int number_of_cores, + bool require_key_frame) { + if (number_of_cores < 0) { + return false; + } + WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCoding, VCMId(id_), + "Codec: %s, Payload type %d, Height %d, Width %d, Bitrate %d," + "Framerate %d.", + receive_codec->plName, receive_codec->plType, + receive_codec->height, receive_codec->width, + receive_codec->startBitrate, receive_codec->maxFramerate); + // Check if payload value already exists, if so - erase old and insert new. + DeregisterReceiveCodec(receive_codec->plType); + if (receive_codec->codecType == kVideoCodecUnknown) { + return false; + } + VideoCodec* new_receive_codec = new VideoCodec(*receive_codec); + dec_map_[receive_codec->plType] = new VCMDecoderMapItem(new_receive_codec, + number_of_cores, + require_key_frame); + return true; } -VideoCodecType -VCMCodecDataBase::ReceiveCodec() const -{ - if (_ptrDecoder == NULL) - { - return kVideoCodecUnknown; - } - return _receiveCodec.codecType; +bool VCMCodecDataBase::DeregisterReceiveCodec( + uint8_t payload_type) { + DecoderMap::iterator it = dec_map_.find(payload_type); + if (it == dec_map_.end()) { + return false; + } + VCMDecoderMapItem* dec_item = (*it).second; + delete dec_item; + dec_map_.erase(it); + if (receive_codec_.plType == payload_type) { + // This codec is currently in use. + memset(&receive_codec_, 0, sizeof(VideoCodec)); + current_dec_is_external_ = false; + } + return true; } -VCMGenericDecoder* -VCMCodecDataBase::SetDecoder(WebRtc_UWord8 payloadType, - VCMDecodedFrameCallback& callback) -{ - if (payloadType == _receiveCodec.plType || payloadType == 0) - { - return _ptrDecoder; - } - // check for exisitng decoder, if exists - delete - if (_ptrDecoder) - { - ReleaseDecoder(_ptrDecoder); - _ptrDecoder = NULL; - memset(&_receiveCodec, 0, sizeof(VideoCodec)); - } - _ptrDecoder = CreateAndInitDecoder(payloadType, _receiveCodec, - _currentDecIsExternal); - if (_ptrDecoder == NULL) - { - return NULL; - } - if (_ptrDecoder->RegisterDecodeCompleteCallback(&callback) < 0) - { - ReleaseDecoder(_ptrDecoder); - _ptrDecoder = NULL; - memset(&_receiveCodec, 0, sizeof(VideoCodec)); - return NULL; - } - return _ptrDecoder; +bool VCMCodecDataBase::ReceiveCodec(VideoCodec* current_receive_codec) const { + assert(current_receive_codec); + if (!ptr_decoder_) { + return false; + } + memcpy(current_receive_codec, &receive_codec_, sizeof(VideoCodec)); + return true; } -VCMGenericDecoder* -VCMCodecDataBase::CreateAndInitDecoder(WebRtc_UWord8 payloadType, - VideoCodec& newCodec, - bool &external) const -{ - VCMDecoderMapItem* decoderItem = FindDecoderItem(payloadType); - if (decoderItem == NULL) - { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_id), - "Unknown payload type: %u", payloadType); - return NULL; - } - VCMGenericDecoder* ptrDecoder = NULL; - VCMExtDecoderMapItem* externalDecItem = FindExternalDecoderItem( - payloadType); - if (externalDecItem != NULL) - { - // External codec - ptrDecoder = new VCMGenericDecoder( - *externalDecItem->_externalDecoderInstance, - _id, - true); - external = true; - } - else - { - // create decoder - ptrDecoder = CreateDecoder(decoderItem->_settings->codecType); - external = false; - } - if (ptrDecoder == NULL) - { - return NULL; - } - - if (ptrDecoder->InitDecode(decoderItem->_settings, - decoderItem->_numberOfCores, - decoderItem->_requireKeyFrame) < 0) - { - ReleaseDecoder(ptrDecoder); - return NULL; - } - memcpy(&newCodec, decoderItem->_settings, sizeof(VideoCodec)); - return ptrDecoder; +VideoCodecType VCMCodecDataBase::ReceiveCodec() const { + if (!ptr_decoder_) { + return kVideoCodecUnknown; + } + return receive_codec_.codecType; } -VCMGenericDecoder* -VCMCodecDataBase::CreateDecoderCopy() const -{ - if (_ptrDecoder == NULL) - { - return NULL; - } - VideoDecoder* decoderCopy = _ptrDecoder->_decoder.Copy(); - if (decoderCopy == NULL) - { - return NULL; - } - return new VCMGenericDecoder(*decoderCopy, _id, _ptrDecoder->External()); -} - -void -VCMCodecDataBase::CopyDecoder(const VCMGenericDecoder& decoder) -{ - VideoDecoder* decoderCopy = decoder._decoder.Copy(); - if (decoderCopy != NULL) - { - VCMDecodedFrameCallback* cb = _ptrDecoder->_callback; - ReleaseDecoder(_ptrDecoder); - _ptrDecoder = new VCMGenericDecoder(*decoderCopy, _id, - decoder.External()); - if (cb && _ptrDecoder->RegisterDecodeCompleteCallback(cb)) - { - assert(false); - } - } -} - -bool -VCMCodecDataBase::RenderTiming() const -{ - bool renderTiming = true; - if (_currentDecIsExternal) - { - VCMExtDecoderMapItem* extItem = FindExternalDecoderItem(_receiveCodec.plType); - renderTiming = extItem->_internalRenderTiming; - } - return renderTiming; -} - -void -VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const -{ - if (decoder != NULL) - { - assert(&decoder->_decoder != NULL); - decoder->Release(); - if (!decoder->External()) - { - delete &decoder->_decoder; - } - delete decoder; - } -} - -VCMDecoderMapItem* -VCMCodecDataBase::FindDecoderItem(WebRtc_UWord8 payloadType) const -{ - DecoderMap::const_iterator it = _decMap.find(payloadType); - if (it != _decMap.end()) - { - return (*it).second; - } +VCMGenericDecoder* VCMCodecDataBase::GetDecoder( + uint8_t payload_type, VCMDecodedFrameCallback* decoded_frame_callback) { + if (payload_type == receive_codec_.plType || payload_type == 0) { + return ptr_decoder_; + } + // Check for exisitng decoder, if exists - delete. + if (ptr_decoder_) { + ReleaseDecoder(ptr_decoder_); + ptr_decoder_ = NULL; + memset(&receive_codec_, 0, sizeof(VideoCodec)); + } + ptr_decoder_ = CreateAndInitDecoder(payload_type, &receive_codec_, + ¤t_dec_is_external_); + if (!ptr_decoder_) { return NULL; -} - -VCMExtDecoderMapItem* -VCMCodecDataBase::FindExternalDecoderItem(WebRtc_UWord8 payloadType) const -{ - ExternalDecoderMap::const_iterator it = _decExternalMap.find(payloadType); - if (it != _decExternalMap.end()) - { - return (*it).second; - } + } + if (ptr_decoder_->RegisterDecodeCompleteCallback(decoded_frame_callback) + < 0) { + ReleaseDecoder(ptr_decoder_); + ptr_decoder_ = NULL; + memset(&receive_codec_, 0, sizeof(VideoCodec)); return NULL; + } + return ptr_decoder_; } -VCMGenericDecoder* -VCMCodecDataBase::CreateDecoder(VideoCodecType type) const -{ - switch(type) - { +VCMGenericDecoder* VCMCodecDataBase::CreateDecoderCopy() const { + if (!ptr_decoder_) { + return NULL; + } + VideoDecoder* decoder_copy = ptr_decoder_->_decoder.Copy(); + if (!decoder_copy) { + return NULL; + } + return new VCMGenericDecoder(*decoder_copy, id_, ptr_decoder_->External()); +} + +void VCMCodecDataBase::ReleaseDecoder(VCMGenericDecoder* decoder) const { + if (decoder) { + assert(&decoder->_decoder); + decoder->Release(); + if (!decoder->External()) { + delete &decoder->_decoder; + } + delete decoder; + } +} + +void VCMCodecDataBase::CopyDecoder(const VCMGenericDecoder& decoder) { + VideoDecoder* decoder_copy = decoder._decoder.Copy(); + if (decoder_copy) { + VCMDecodedFrameCallback* cb = ptr_decoder_->_callback; + ReleaseDecoder(ptr_decoder_); + ptr_decoder_ = new VCMGenericDecoder(*decoder_copy, id_, + decoder.External()); + if (cb && ptr_decoder_->RegisterDecodeCompleteCallback(cb)) { + assert(false); + } + } +} + +bool VCMCodecDataBase::SupportsRenderScheduling() const { + bool render_timing = true; + if (current_dec_is_external_) { + const VCMExtDecoderMapItem* ext_item = FindExternalDecoderItem( + receive_codec_.plType); + render_timing = ext_item->internal_render_timing; + } + return render_timing; +} + +VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder( + uint8_t payload_type, + VideoCodec* new_codec, + bool* external) const { + assert(external); + assert(new_codec); + const VCMDecoderMapItem* decoder_item = FindDecoderItem(payload_type); + if (!decoder_item) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(id_), + "Unknown payload type: %u", payload_type); + return NULL; + } + VCMGenericDecoder* ptr_decoder = NULL; + const VCMExtDecoderMapItem* external_dec_item = FindExternalDecoderItem( + payload_type); + if (external_dec_item) { + // External codec. + ptr_decoder = new VCMGenericDecoder( + *external_dec_item->external_decoder_instance, id_, true); + *external = true; + } else { + // Create decoder. + ptr_decoder = CreateDecoder(decoder_item->settings->codecType); + *external = false; + } + if (!ptr_decoder) { + return NULL; + } + + if (ptr_decoder->InitDecode(decoder_item->settings.get(), + decoder_item->number_of_cores, + decoder_item->require_key_frame) < 0) { + ReleaseDecoder(ptr_decoder); + return NULL; + } + memcpy(new_codec, decoder_item->settings.get(), sizeof(VideoCodec)); + return ptr_decoder; +} + +VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( + const VideoCodecType type) const { + switch (type) { #ifdef VIDEOCODEC_VP8 case kVideoCodecVP8: - return new VCMGenericDecoder(*(VP8Decoder::Create()), _id); + return new VCMGenericEncoder(*(VP8Encoder::Create())); #endif #ifdef VIDEOCODEC_I420 case kVideoCodecI420: - return new VCMGenericDecoder(*(new I420Decoder), _id); + return new VCMGenericEncoder(*(new I420Encoder)); #endif default: - return NULL; + return NULL; + } +} + +void VCMCodecDataBase::DeleteEncoder() { + if (ptr_encoder_) { + ptr_encoder_->Release(); + if (!current_enc_is_external_) { + delete &ptr_encoder_->_encoder; } + delete ptr_encoder_; + ptr_encoder_ = NULL; + } } + +VCMGenericDecoder* VCMCodecDataBase::CreateDecoder(VideoCodecType type) const { + switch (type) { +#ifdef VIDEOCODEC_VP8 + case kVideoCodecVP8: + return new VCMGenericDecoder(*(VP8Decoder::Create()), id_); +#endif +#ifdef VIDEOCODEC_I420 + case kVideoCodecI420: + return new VCMGenericDecoder(*(new I420Decoder), id_); +#endif + default: + return NULL; + } } + +const VCMDecoderMapItem* VCMCodecDataBase::FindDecoderItem( + uint8_t payload_type) const { + DecoderMap::const_iterator it = dec_map_.find(payload_type); + if (it != dec_map_.end()) { + return (*it).second; + } + return NULL; +} + +const VCMExtDecoderMapItem* VCMCodecDataBase::FindExternalDecoderItem( + uint8_t payload_type) const { + ExternalDecoderMap::const_iterator it = dec_external_map_.find(payload_type); + if (it != dec_external_map_.end()) { + return (*it).second; + } + return NULL; +} +} // namespace webrtc diff --git a/src/modules/video_coding/main/source/codec_database.h b/src/modules/video_coding/main/source/codec_database.h index aab8229ae..7d8e078ef 100644 --- a/src/modules/video_coding/main/source/codec_database.h +++ b/src/modules/video_coding/main/source/codec_database.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CODING_CODEC_DATABASE_H_ -#define WEBRTC_MODULES_VIDEO_CODING_CODEC_DATABASE_H_ +#ifndef WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_CODEC_DATABASE_H_ +#define WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_CODEC_DATABASE_H_ #include @@ -17,194 +17,184 @@ #include "modules/video_coding/main/interface/video_coding.h" #include "modules/video_coding/main/source/generic_decoder.h" #include "modules/video_coding/main/source/generic_encoder.h" +#include "system_wrappers/interface/scoped_ptr.h" #include "typedefs.h" -namespace webrtc -{ +namespace webrtc { -enum VCMCodecDBProperties -{ - kDefaultPayloadSize = 1440 +enum VCMCodecDBProperties { + kDefaultPayloadSize = 1440 }; -class VCMDecoderMapItem { -public: - VCMDecoderMapItem(VideoCodec* settings, - WebRtc_UWord32 numberOfCores, - bool requireKeyFrame); +struct VCMDecoderMapItem { + public: + VCMDecoderMapItem(VideoCodec* settings, + int number_of_cores, + bool require_key_frame); - VideoCodec* _settings; - WebRtc_UWord32 _numberOfCores; - bool _requireKeyFrame; + scoped_ptr settings; + int number_of_cores; + bool require_key_frame; }; -class VCMExtDecoderMapItem { -public: - VCMExtDecoderMapItem(VideoDecoder* externalDecoderInstance, - WebRtc_UWord8 payloadType, - bool internalRenderTiming); +struct VCMExtDecoderMapItem { + public: + VCMExtDecoderMapItem(VideoDecoder* external_decoder_instance, + uint8_t payload_type, + bool internal_render_timing); - WebRtc_UWord8 _payloadType; - VideoDecoder* _externalDecoderInstance; - bool _internalRenderTiming; + uint8_t payload_type; + VideoDecoder* external_decoder_instance; + bool internal_render_timing; }; -/*******************************/ -/* VCMCodecDataBase class */ -/*******************************/ -class VCMCodecDataBase -{ -public: - VCMCodecDataBase(WebRtc_Word32 id); - ~VCMCodecDataBase(); - /** - * Release codecdatabase - release all memory for both send and receive side - */ - WebRtc_Word32 Reset(); - /** - * Sender Side - */ - /** - * Returns the number of supported codecs (or -1 in case of error). - */ - static WebRtc_UWord8 NumberOfCodecs(); - /** - * Get supported codecs with ID - * Input Values: - * listnr : Requested codec id number - * codec_inst: Pointer to the struct in which the returned codec information is copied - * Return Values: 0 if successful, otherwise - */ - static WebRtc_Word32 Codec(WebRtc_UWord8 listId, VideoCodec* settings); - static WebRtc_Word32 Codec(VideoCodecType codecType, VideoCodec* settings); - /** - * Reset Sender side - */ - WebRtc_Word32 ResetSender(); - /** - * Setting the sender side codec and initiaiting the desired codec given the VideoCodec - * struct. - * Return Value: 0 if the codec and the settings are supported, otherwise - */ - WebRtc_Word32 RegisterSendCodec(const VideoCodec* sendCodec, - WebRtc_UWord32 numberOfCores, - WebRtc_UWord32 maxPayloadSize); - /** - * Get current send side codec. Relevant for internal codecs only. - */ - WebRtc_Word32 SendCodec(VideoCodec* currentSendCodec) const; - /** - * Get current send side codec type. Relevant for internal codecs only. - */ - VideoCodecType SendCodec() const; - /** - * Register external encoder - current assumption - if one is registered then it will also - * be used, and therefore it is also initialized - * Return value: A pointer to the encoder on success, or null, in case of an error. - */ - WebRtc_Word32 DeRegisterExternalEncoder(WebRtc_UWord8 payloadType, bool& wasSendCodec); - WebRtc_Word32 RegisterExternalEncoder(VideoEncoder* externalEncoder, - WebRtc_UWord8 payloadType, - bool internalSource); - /** - * Returns a encoder given a payloadname - to be used with internal encoders only. - * Special cases: - * Encoder exists - If payload matches, returns existing one, otherwise, - * deletes existing one and creates new one. - * No match found / Error - returns NULL. - */ - VCMGenericEncoder* SetEncoder(const VideoCodec* settings, - VCMEncodedFrameCallback* VCMencodedFrameCallback); +class VCMCodecDataBase { + public: + explicit VCMCodecDataBase(int id); + ~VCMCodecDataBase(); - WebRtc_Word32 SetPeriodicKeyFrames(bool enable); + // Sender Side + // Returns the number of supported codecs (or -1 in case of error). + static int NumberOfCodecs(); - bool InternalSource() const; + // Returns the default settings for the codec with id |list_id|. + static bool Codec(int list_id, VideoCodec* settings); - /* - * Receiver Side - */ - WebRtc_Word32 ResetReceiver(); - /** - * Register external decoder/render object - */ - WebRtc_Word32 DeRegisterExternalDecoder(WebRtc_UWord8 payloadType); - WebRtc_Word32 RegisterExternalDecoder(VideoDecoder* externalDecoder, - WebRtc_UWord8 payloadType, - bool internalRenderTiming); + // Returns the default settings for the codec with type |codec_type|. + static bool Codec(VideoCodecType codec_type, VideoCodec* settings); - bool DecoderRegistered() const; - /** - * Register recieve codec - */ - WebRtc_Word32 RegisterReceiveCodec(const VideoCodec* receiveCodec, - WebRtc_UWord32 numberOfCores, - bool requireKeyFrame); - WebRtc_Word32 DeRegisterReceiveCodec(WebRtc_UWord8 payloadType); - /** - * Get current receive side codec. Relevant for internal codecs only. - */ - WebRtc_Word32 ReceiveCodec(VideoCodec* currentReceiveCodec) const; - /** - * Get current receive side codec type. Relevant for internal codecs only. - */ - VideoCodecType ReceiveCodec() const; - /** - * Returns a decoder given which matches a payload type. - * Special cases: - * Decoder exists - If payload matches, returns existing one, otherwise, deletes - * existing one, and creates new one. - * No match found / Error - returns NULL. - */ - VCMGenericDecoder* SetDecoder(WebRtc_UWord8 payloadType, VCMDecodedFrameCallback& callback); + void ResetSender(); - VCMGenericDecoder* CreateAndInitDecoder(WebRtc_UWord8 payloadType, - VideoCodec& newCodec, - bool &external) const; + // Sets the sender side codec and initiates the desired codec given the + // VideoCodec struct. + // Returns true if the codec was successfully registered, false otherwise. + bool RegisterSendCodec(const VideoCodec* send_codec, + int number_of_cores, + int max_payload_size); - VCMGenericDecoder* CreateDecoderCopy() const; + // Gets the current send codec. Relevant for internal codecs only. + // Returns true if there is a send codec, false otherwise. + bool SendCodec(VideoCodec* current_send_codec) const; - void ReleaseDecoder(VCMGenericDecoder* decoder) const; + // Gets current send side codec type. Relevant for internal codecs only. + // Returns kVideoCodecUnknown if there is no send codec. + VideoCodecType SendCodec() const; - void CopyDecoder(const VCMGenericDecoder& decoder); + // Registers and initializes an external encoder object. + // |internal_source| should be set to true if the codec has an internal + // video source and doesn't need the user to provide it with frames via + // the Encode() method. + void RegisterExternalEncoder(VideoEncoder* external_encoder, + uint8_t payload_type, + bool internal_source); - bool RenderTiming() const; + // Deregisters an external encoder. Returns true if the encoder was + // found and deregistered, false otherwise. |was_send_codec| is set to true + // if the external encoder was the send codec before being deregistered. + bool DeregisterExternalEncoder(uint8_t payload_type, bool* was_send_codec); -protected: - /** - * Create an internal Encoder given a codec type - */ - VCMGenericEncoder* CreateEncoder(const VideoCodecType type) const; + // Returns an encoder specified by the payload type in |settings|. The + // encoded frame callback of the encoder is set to |encoded_frame_callback|. + // If no such encoder already exists an instance will be created and + // initialized using |settings|. + // NULL is returned if no encoder with the specified payload type was found + // and the function failed to create one. + VCMGenericEncoder* GetEncoder( + const VideoCodec* settings, + VCMEncodedFrameCallback* encoded_frame_callback); - void DeleteEncoder(); - /* - * Create an internal Decoder given a codec type - */ - VCMGenericDecoder* CreateDecoder(VideoCodecType type) const; + bool SetPeriodicKeyFrames(bool enable); - VCMDecoderMapItem* FindDecoderItem(WebRtc_UWord8 payloadType) const; + // Receiver Side + void ResetReceiver(); - VCMExtDecoderMapItem* FindExternalDecoderItem(WebRtc_UWord8 payloadType) const; + // Deregisters an external decoder object specified by |payload_type|. + bool DeregisterExternalDecoder(uint8_t payload_type); -private: - typedef std::map DecoderMap; - typedef std::map ExternalDecoderMap; - WebRtc_Word32 _id; - WebRtc_UWord32 _numberOfCores; - WebRtc_UWord32 _maxPayloadSize; - bool _periodicKeyFrames; - bool _currentEncIsExternal; - VideoCodec _sendCodec; - VideoCodec _receiveCodec; - WebRtc_UWord8 _externalPayloadType; - VideoEncoder* _externalEncoder; - bool _internalSource; - VCMGenericEncoder* _ptrEncoder; - VCMGenericDecoder* _ptrDecoder; - bool _currentDecIsExternal; - DecoderMap _decMap; - ExternalDecoderMap _decExternalMap; -}; // end of VCMCodecDataBase class definition + // Registers an external decoder object to the payload type |payload_type|. + // |internal_render_timing| is set to true if the |external_decoder| has + // built in rendering which is able to obey the render timestamps of the + // encoded frames. + bool RegisterExternalDecoder(VideoDecoder* external_decoder, + uint8_t payload_type, + bool internal_render_timing); -} // namespace webrtc + bool DecoderRegistered() const; -#endif // WEBRTC_MODULES_VIDEO_CODING_CODEC_DATABASE_H_ + bool RegisterReceiveCodec(const VideoCodec* receive_codec, + int number_of_cores, + bool require_key_frame); + + bool DeregisterReceiveCodec(uint8_t payload_type); + + // Get current receive side codec. Relevant for internal codecs only. + bool ReceiveCodec(VideoCodec* current_receive_codec) const; + + // Get current receive side codec type. Relevant for internal codecs only. + VideoCodecType ReceiveCodec() const; + + // Returns a decoder specified by |payload_type|. The decoded frame callback + // of the encoder is set to |decoded_frame_callback|. If no such decoder + // already exists an instance will be created and initialized. + // NULL is returned if no encoder with the specified payload type was found + // and the function failed to create one. + VCMGenericDecoder* GetDecoder( + uint8_t payload_type, VCMDecodedFrameCallback* decoded_frame_callback); + + // Returns a deep copy of the currently active decoder. + VCMGenericDecoder* CreateDecoderCopy() const; + + // Deletes the memory of the decoder instance |decoder|. Used to delete + // deep copies returned by CreateDecoderCopy(). + void ReleaseDecoder(VCMGenericDecoder* decoder) const; + + // Creates a deep copy of |decoder| and replaces the currently used decoder + // with it. + void CopyDecoder(const VCMGenericDecoder& decoder); + + // Returns true if the currently active decoder supports render scheduling, + // that is, it is able to render frames according to the render timestamp of + // the encoded frames. + bool SupportsRenderScheduling() const; + + private: + typedef std::map DecoderMap; + typedef std::map ExternalDecoderMap; + + VCMGenericDecoder* CreateAndInitDecoder(uint8_t payload_type, + VideoCodec* new_codec, + bool* external) const; + + // Create an internal encoder given a codec type. + VCMGenericEncoder* CreateEncoder(const VideoCodecType type) const; + + void DeleteEncoder(); + + // Create an internal Decoder given a codec type + VCMGenericDecoder* CreateDecoder(VideoCodecType type) const; + + const VCMDecoderMapItem* FindDecoderItem(uint8_t payload_type) const; + + const VCMExtDecoderMapItem* FindExternalDecoderItem( + uint8_t payload_type) const; + + int id_; + int number_of_cores_; + int max_payload_size_; + bool periodic_key_frames_; + bool current_enc_is_external_; + VideoCodec send_codec_; + VideoCodec receive_codec_; + uint8_t external_payload_type_; + VideoEncoder* external_encoder_; + bool internal_source_; + VCMGenericEncoder* ptr_encoder_; + VCMGenericDecoder* ptr_decoder_; + bool current_dec_is_external_; + DecoderMap dec_map_; + ExternalDecoderMap dec_external_map_; +}; // VCMCodecDataBase + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_MAIN_SOURCE_CODEC_DATABASE_H_ diff --git a/src/modules/video_coding/main/source/video_coding_impl.cc b/src/modules/video_coding/main/source/video_coding_impl.cc index ded4fb7d2..3e4e22b60 100644 --- a/src/modules/video_coding/main/source/video_coding_impl.cc +++ b/src/modules/video_coding/main/source/video_coding_impl.cc @@ -271,7 +271,7 @@ VideoCodingModule::Codec(WebRtc_UWord8 listId, VideoCodec* codec) { return VCM_PARAMETER_ERROR; } - return VCMCodecDataBase::Codec(listId, codec); + return VCMCodecDataBase::Codec(listId, codec) ? 0 : -1; } // Get supported codec with type @@ -282,7 +282,7 @@ VideoCodingModule::Codec(VideoCodecType codecType, VideoCodec* codec) { return VCM_PARAMETER_ERROR; } - return VCMCodecDataBase::Codec(codecType, codec); + return VCMCodecDataBase::Codec(codecType, codec) ? 0 : -1; } /* @@ -314,15 +314,14 @@ VideoCodingModuleImpl::RegisterSendCodec(const VideoCodec* sendCodec, { return VCM_PARAMETER_ERROR; } - WebRtc_Word32 ret = _codecDataBase.RegisterSendCodec(sendCodec, - numberOfCores, - maxPayloadSize); - if (ret < 0) + bool ret = _codecDataBase.RegisterSendCodec(sendCodec, numberOfCores, + maxPayloadSize); + if (!ret) { - return ret; + return -1; } - _encoder = _codecDataBase.SetEncoder(sendCodec, &_encodedFrameCallback); + _encoder = _codecDataBase.GetEncoder(sendCodec, &_encodedFrameCallback); if (_encoder == NULL) { WEBRTC_TRACE(webrtc::kTraceError, @@ -384,19 +383,18 @@ VideoCodingModuleImpl::RegisterExternalEncoder(VideoEncoder* externalEncoder, if (externalEncoder == NULL) { bool wasSendCodec = false; - const WebRtc_Word32 ret = _codecDataBase.DeRegisterExternalEncoder( - payloadType, - wasSendCodec); + const bool ret = _codecDataBase.DeregisterExternalEncoder( + payloadType, &wasSendCodec); if (wasSendCodec) { // Make sure the VCM doesn't use the de-registered codec _encoder = NULL; } - return ret; + return ret ? 0 : -1; } - return _codecDataBase.RegisterExternalEncoder(externalEncoder, - payloadType, - internalSource); + _codecDataBase.RegisterExternalEncoder(externalEncoder, payloadType, + internalSource); + return 0; } // Get codec config parameters @@ -802,14 +800,10 @@ VideoCodingModuleImpl::RegisterExternalDecoder(VideoDecoder* externalDecoder, { // Make sure the VCM updates the decoder next time it decodes. _decoder = NULL; - return _codecDataBase.DeRegisterExternalDecoder(payloadType); - } - else - { - return _codecDataBase.RegisterExternalDecoder(externalDecoder, - payloadType, - internalRenderTiming); + return _codecDataBase.DeregisterExternalDecoder(payloadType) ? 0 : -1; } + return _codecDataBase.RegisterExternalDecoder( + externalDecoder, payloadType, internalRenderTiming) ? 0 : -1; } // Register a frame type request callback. @@ -863,10 +857,10 @@ VideoCodingModuleImpl::Decode(WebRtc_UWord16 maxWaitTimeMs) _dualReceiver.NackMode() == kNackInfinite); VCMEncodedFrame* frame = _receiver.FrameForDecoding( - maxWaitTimeMs, - nextRenderTimeMs, - _codecDataBase.RenderTiming(), - &_dualReceiver); + maxWaitTimeMs, + nextRenderTimeMs, + _codecDataBase.SupportsRenderScheduling(), + &_dualReceiver); if (dualReceiverEnabledNotReceiving && _dualReceiver.State() == kReceiving) { @@ -1045,10 +1039,10 @@ WebRtc_Word32 VideoCodingModuleImpl::Decode(const VCMEncodedFrame& frame) { // Change decoder if payload type has changed - const bool renderTimingBefore = _codecDataBase.RenderTiming(); - _decoder = _codecDataBase.SetDecoder(frame.PayloadType(), - _decodedFrameCallback); - if (renderTimingBefore != _codecDataBase.RenderTiming()) + const bool renderTimingBefore = _codecDataBase.SupportsRenderScheduling(); + _decoder = _codecDataBase.GetDecoder(frame.PayloadType(), + &_decodedFrameCallback); + if (renderTimingBefore != _codecDataBase.SupportsRenderScheduling()) { // Make sure we reset the decode time estimate since it will // be zero for codecs without render timing. @@ -1157,8 +1151,11 @@ VideoCodingModuleImpl::RegisterReceiveCodec(const VideoCodec* receiveCodec, { return VCM_PARAMETER_ERROR; } - return _codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, - requireKeyFrame); + if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, + requireKeyFrame)) { + return -1; + } + return 0; } // Get current received codec diff --git a/src/modules/video_coding/main/test/codec_database_test.cc b/src/modules/video_coding/main/test/codec_database_test.cc index 7696300f0..98671ea52 100644 --- a/src/modules/video_coding/main/test/codec_database_test.cc +++ b/src/modules/video_coding/main/test/codec_database_test.cc @@ -125,8 +125,9 @@ CodecDataBaseTest::Perform(CmdArgs& args) sourceFrame.SetTimeStamp(_timeStamp); // Encoder registration TEST (VideoCodingModule::NumberOfCodecs() > 0); - TEST(VideoCodingModule::Codec(-1, &sendCodec) == VCM_PARAMETER_ERROR); - TEST(VideoCodingModule::Codec(VideoCodingModule::NumberOfCodecs() + 1, &sendCodec) == VCM_PARAMETER_ERROR); + TEST(VideoCodingModule::Codec(-1, &sendCodec) < 0); + TEST(VideoCodingModule::Codec(VideoCodingModule::NumberOfCodecs() + 1, + &sendCodec) < 0); VideoCodingModule::Codec(1, &sendCodec); sendCodec.plType = 0; // random value TEST(_vcm->RegisterSendCodec(&sendCodec, 1, 1440) < 0);