/*
 *  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 <assert.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.resilience = kResilientStream;
            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)
    {
        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)
    {
        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;
}

}
