| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "codec_database.h" |
| #include "../../../../engine_configurations.h" |
| #include "internal_defines.h" |
| #include "trace.h" |
| |
| #if defined(_WIN32) |
| // VS 2005: Don't warn for default initialized arrays. See help for more info. |
| // Don't warn for strncpy being unsecure. |
| // switch statement contains 'default' but no 'case' labels |
| #pragma warning(disable:4351; disable:4996; disable:4065) |
| #endif |
| |
| // Supported codecs |
| #ifdef VIDEOCODEC_VP8 |
| #include "vp8.h" |
| #include "vp8_simulcast.h" |
| #endif |
| #ifdef VIDEOCODEC_I420 |
| #include "i420.h" |
| #endif |
| |
| namespace webrtc |
| { |
| |
| VCMDecoderMapItem::VCMDecoderMapItem(VideoCodec* settings, |
| WebRtc_UWord32 numberOfCores, |
| bool requireKeyFrame) |
| : |
| _settings(settings), |
| _numberOfCores(numberOfCores), |
| _requireKeyFrame(requireKeyFrame) |
| { |
| } |
| |
| VCMExtDecoderMapItem::VCMExtDecoderMapItem(VideoDecoder* externalDecoderInstance, |
| WebRtc_UWord8 payloadType, |
| bool internalRenderTiming) |
| : |
| _payloadType(payloadType), |
| _externalDecoderInstance(externalDecoderInstance), |
| _internalRenderTiming(internalRenderTiming) |
| { |
| } |
| |
| 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() |
| { |
| Reset(); |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::Version(WebRtc_Word8* version, |
| WebRtc_UWord32& remainingBufferInBytes, |
| WebRtc_UWord32& position) const |
| { |
| VCMGenericEncoder* encoder = NULL; |
| VideoCodec settings; |
| WebRtc_Word32 ret; |
| for (int i = 0; i < VCMCodecDataBase::NumberOfCodecs(); i++) |
| { |
| ret = VCMCodecDataBase::Codec(i, &settings); |
| if (ret < 0) |
| { |
| return ret; |
| } |
| encoder = CreateEncoder(settings.codecType, false); |
| if (encoder == NULL) |
| { |
| return VCM_MEMORY; |
| } |
| ret = encoder->_encoder.Version(&version[position], remainingBufferInBytes); |
| if (ret < 0) |
| { |
| return ret; |
| } |
| remainingBufferInBytes -= ret; |
| position += ret; |
| delete &encoder->_encoder; |
| delete encoder; |
| } |
| return VCM_OK; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::Reset() |
| { |
| WebRtc_Word32 ret = ResetReceiver(); |
| if (ret < 0) |
| { |
| return ret; |
| } |
| ret = ResetSender(); |
| if (ret < 0) |
| { |
| return ret; |
| } |
| return VCM_OK; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::ResetSender() |
| { |
| DeleteEncoder(); |
| _periodicKeyFrames = false; |
| return VCM_OK; |
| } |
| |
| VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( |
| const VideoCodecType type, |
| const bool simulcast) const { |
| |
| switch(type) |
| { |
| #ifdef VIDEOCODEC_VP8 |
| case kVideoCodecVP8: |
| if (simulcast) { |
| return new VCMGenericEncoder(*(new VP8SimulcastEncoder)); |
| } else { |
| return new VCMGenericEncoder(*(new VP8Encoder)); |
| } |
| #endif |
| #ifdef VIDEOCODEC_I420 |
| case kVideoCodecI420: |
| if (!simulcast) { |
| return new VCMGenericEncoder(*(new I420Encoder)); |
| } |
| return NULL; |
| #endif |
| default: |
| return NULL; |
| } |
| } |
| |
| void |
| VCMCodecDataBase::DeleteEncoder() |
| { |
| if (_ptrEncoder) |
| { |
| _ptrEncoder->Release(); |
| if (!_currentEncIsExternal) |
| { |
| delete &_ptrEncoder->_encoder; |
| } |
| delete _ptrEncoder; |
| _ptrEncoder = NULL; |
| } |
| } |
| |
| WebRtc_UWord8 |
| VCMCodecDataBase::NumberOfCodecs() |
| { |
| return VCM_NUM_VIDEO_CODECS_AVAILABLE; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::Codec(WebRtc_UWord8 listId, VideoCodec *settings) |
| { |
| if (settings == NULL) |
| { |
| return VCM_PARAMETER_ERROR; |
| } |
| |
| 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", 3); |
| 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.numberOfTemporalLayers = 1; |
| break; |
| } |
| #endif |
| #ifdef VIDEOCODEC_I420 |
| case VCM_I420_IDX: |
| { |
| strncpy(settings->plName, "I420", 4); |
| 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; |
| } |
| } |
| |
| return VCM_OK; |
| } |
| |
| 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; |
| } |
| |
| // 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 (strcmp(sendCodec->plName, "H263") == 0 && |
| (sendCodec->plType != 34)) |
| { |
| 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; |
| } |
| |
| 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 |
| DeleteEncoder(); |
| |
| if (settings->plType == _externalPayloadType) |
| { |
| // External encoder |
| _ptrEncoder = new VCMGenericEncoder(*_externalEncoder, _internalSource); |
| _currentEncIsExternal = true; |
| } |
| else |
| { |
| bool simulcast = false; |
| if (settings->numberOfSimulcastStreams > 1) |
| { |
| simulcast = true; |
| } |
| _ptrEncoder = CreateEncoder(settings->codecType, simulcast); |
| _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; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::SetPeriodicKeyFrames(bool enable) |
| { |
| _periodicKeyFrames = enable; |
| if (_ptrEncoder != NULL) |
| { |
| return _ptrEncoder->SetPeriodicKeyFrames(_periodicKeyFrames); |
| } |
| return VCM_OK; |
| } |
| |
| 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.Insert(receiveCodec->plType, |
| new VCMDecoderMapItem(newReceiveCodec, numberOfCores, requireKeyFrame)); |
| |
| return VCM_OK; |
| } |
| |
| WebRtc_Word32 VCMCodecDataBase::DeRegisterReceiveCodec(WebRtc_UWord8 payloadType) |
| { |
| MapItem* item = _decMap.Find(payloadType); |
| if (item == NULL) |
| { |
| return VCM_PARAMETER_ERROR; |
| } |
| VCMDecoderMapItem* decItem = static_cast<VCMDecoderMapItem*>(item->GetItem()); |
| delete decItem->_settings; |
| delete decItem; |
| _decMap.Erase(item); |
| if (_receiveCodec.plType == payloadType) |
| { |
| // This codec is currently in use. |
| memset(&_receiveCodec, 0, sizeof(VideoCodec)); |
| _currentDecIsExternal = false; |
| } |
| return VCM_OK; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::ResetReceiver() |
| { |
| ReleaseDecoder(_ptrDecoder); |
| _ptrDecoder = NULL; |
| memset(&_receiveCodec, 0, sizeof(VideoCodec)); |
| MapItem* item = _decMap.First(); |
| while (item != NULL) |
| { |
| VCMDecoderMapItem* decItem = static_cast<VCMDecoderMapItem*>(item->GetItem()); |
| if (decItem != NULL) |
| { |
| if (decItem->_settings != NULL) |
| { |
| delete decItem->_settings; |
| } |
| delete decItem; |
| } |
| _decMap.Erase(item); |
| item = _decMap.First(); |
| } |
| item = _decExternalMap.First(); |
| while (item != NULL) |
| { |
| VCMExtDecoderMapItem* decItem = static_cast<VCMExtDecoderMapItem*>(item->GetItem()); |
| if (decItem != NULL) |
| { |
| delete decItem; |
| } |
| _decExternalMap.Erase(item); |
| item = _decExternalMap.First(); |
| } |
| _currentDecIsExternal = false; |
| return VCM_OK; |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::DeRegisterExternalDecoder(WebRtc_UWord8 payloadType) |
| { |
| MapItem* item = _decExternalMap.Find(payloadType); |
| if (item == NULL) |
| { |
| // 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); |
| VCMExtDecoderMapItem* decItem = static_cast<VCMExtDecoderMapItem*>(item->GetItem()); |
| delete decItem; |
| _decExternalMap.Erase(item); |
| return VCM_OK; |
| } |
| |
| // 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.Insert(payloadType, extDecoder); |
| |
| return VCM_OK; |
| } |
| |
| bool |
| VCMCodecDataBase::DecoderRegistered() const |
| { |
| return (_decMap.Size() > 0); |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::ReceiveCodec(VideoCodec* currentReceiveCodec) const |
| { |
| if (_ptrDecoder == NULL) |
| { |
| return VCM_NO_FRAME_DECODED; |
| } |
| memcpy(currentReceiveCodec, &_receiveCodec, sizeof(VideoCodec)); |
| return VCM_OK; |
| } |
| |
| VideoCodecType |
| VCMCodecDataBase::ReceiveCodec() const |
| { |
| if (_ptrDecoder == NULL) |
| { |
| return kVideoCodecUnknown; |
| } |
| return _receiveCodec.codecType; |
| } |
| |
| 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; |
| } |
| |
| 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; |
| } |
| |
| SetCodecConfigParameters(*ptrDecoder, *decoderItem->_settings); |
| |
| memcpy(&newCodec, decoderItem->_settings, sizeof(VideoCodec)); |
| return ptrDecoder; |
| } |
| |
| 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) |
| { |
| ReleaseDecoder(_ptrDecoder); |
| _ptrDecoder = new VCMGenericDecoder(*decoderCopy, _id, decoder.External()); |
| } |
| } |
| |
| 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) |
| { |
| decoder->Release(); |
| if (!decoder->External() && &decoder->_decoder != NULL) |
| { |
| delete &decoder->_decoder; |
| } |
| delete decoder; |
| } |
| } |
| |
| WebRtc_Word32 |
| VCMCodecDataBase::SetCodecConfigParameters(WebRtc_UWord8 payloadType, |
| const WebRtc_UWord8* buffer, |
| WebRtc_Word32 length) |
| { |
| VCMDecoderMapItem* decItem = FindDecoderItem(payloadType); |
| if (decItem == NULL) |
| { |
| return VCM_PARAMETER_ERROR; |
| } |
| switch (decItem->_settings->codecType) |
| { |
| case kVideoCodecMPEG4: |
| { |
| memcpy(decItem->_settings->codecSpecific.MPEG4.configParameters, buffer, length); |
| decItem->_settings->codecSpecific.MPEG4.configParametersSize = |
| static_cast<WebRtc_UWord8>(length); |
| break; |
| } |
| default: |
| // This codec doesn't have codec config parameters |
| return VCM_GENERAL_ERROR; |
| } |
| if (_ptrDecoder != NULL && _receiveCodec.plType == decItem->_settings->plType) |
| { |
| return _ptrDecoder->SetCodecConfigParameters(buffer, length); |
| } |
| return VCM_OK; |
| } |
| |
| VCMDecoderMapItem* |
| VCMCodecDataBase::FindDecoderItem(WebRtc_UWord8 payloadType) const |
| { |
| MapItem* item = _decMap.Find(payloadType); |
| if (item != NULL) |
| { |
| return static_cast<VCMDecoderMapItem*>(item->GetItem()); |
| } |
| return NULL; |
| } |
| |
| VCMExtDecoderMapItem* |
| VCMCodecDataBase::FindExternalDecoderItem(WebRtc_UWord8 payloadType) const |
| { |
| MapItem* item = _decExternalMap.Find(payloadType); |
| if (item != NULL) |
| { |
| return static_cast<VCMExtDecoderMapItem*>(item->GetItem()); |
| } |
| return NULL; |
| } |
| |
| VCMGenericDecoder* |
| VCMCodecDataBase::CreateDecoder(VideoCodecType type) const |
| { |
| switch(type) |
| { |
| #ifdef VIDEOCODEC_VP8 |
| case kVideoCodecVP8: |
| return new VCMGenericDecoder(*(new VP8Decoder), _id); |
| #endif |
| #ifdef VIDEOCODEC_I420 |
| case kVideoCodecI420: |
| return new VCMGenericDecoder(*(new I420Decoder), _id); |
| #endif |
| default: |
| return NULL; |
| } |
| } |
| |
| void |
| VCMCodecDataBase::SetCodecConfigParameters(VCMGenericDecoder& decoder, |
| const VideoCodec& settings) |
| { |
| switch (settings.codecType) |
| { |
| case kVideoCodecMPEG4: |
| { |
| if (settings.codecSpecific.MPEG4.configParametersSize > 0) |
| { |
| decoder.SetCodecConfigParameters( |
| settings.codecSpecific.MPEG4.configParameters, |
| settings.codecSpecific.MPEG4.configParametersSize); |
| } |
| break; |
| } |
| default: |
| // No codec config parameters for this codec |
| return; |
| } |
| return; |
| } |
| |
| } |