/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
#include "pvmf_omx_enc_port.h"
#include "pvmf_omx_enc_node.h"


PVMFOMXEncPort::PVMFOMXEncPort(int32 aTag, PVMFNodeInterface* aNode, const char*name)
        : PvmfPortBaseImpl(aTag, aNode, name)
{
    iOMXNode = (PVMFOMXEncNode *) aNode;
    Construct();
}

////////////////////////////////////////////////////////////////////////////
void PVMFOMXEncPort::Construct()
{
    iLogger = PVLogger::GetLoggerObject("PVMFOMXEncPort");
    oscl_memset(&iStats, 0, sizeof(PvmfPortBaseImplStats));
    iNumFramesGenerated = 0;
    iNumFramesConsumed = 0;
    iTrackConfig = NULL;
    iTrackConfigSize = 0;
    iTimescale = 0;

}


PVMFOMXEncPort::~PVMFOMXEncPort()
{
    if (iTrackConfig != NULL)
    {
        OSCL_FREE(iTrackConfig);
        iTrackConfigSize = 0;
    }

    Disconnect();
    ClearMsgQueues();
}

////////////////////////////////////////////////////////////////////////////
bool PVMFOMXEncPort::IsFormatSupported(PVMFFormatType aFmt)
{
    Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
    for (it = iOMXNode->iCapability.iInputFormatCapability.begin();
            it != iOMXNode->iCapability.iInputFormatCapability.end(); it++)
    {
        if (aFmt == *it)
        {
            return true;
        }
    }
    for (it = iOMXNode->iCapability.iOutputFormatCapability.begin();
            it != iOMXNode->iCapability.iOutputFormatCapability.end(); it++)
    {
        if (aFmt == *it)
        {
            return true;
        }
    }
    // Not found in the input or output format capability lists
    return false;
}

////////////////////////////////////////////////////////////////////////////
void PVMFOMXEncPort::FormatUpdated()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO
                    , (0, "PVMFOMXEncPort::FormatUpdated %s", iFormat.getMIMEStrPtr()));
}

bool
PVMFOMXEncPort::pvmiSetPortFormatSpecificInfoSync(OsclRefCounterMemFrag& aMemFrag)
{
    if ((iConnectedPort) &&
            (iTag == PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT))
    {
        OsclAny* temp = NULL;
        iConnectedPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
        PvmiCapabilityAndConfig *config = (PvmiCapabilityAndConfig*) temp;

        /*
         * Create PvmiKvp for capability settings
         */
        if ((config) && (aMemFrag.getMemFragSize() > 0))
        {
            OsclMemAllocator alloc;
            PvmiKvp kvp;
            kvp.key = NULL;
            kvp.length = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY) + 1; // +1 for \0
            kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
            if (kvp.key == NULL)
            {
                return false;
            }
            oscl_strncpy(kvp.key, PVMF_FORMAT_SPECIFIC_INFO_KEY, kvp.length);

            kvp.value.key_specific_value = (OsclAny*)(aMemFrag.getMemFragPtr());
            kvp.capacity = aMemFrag.getMemFragSize();
            kvp.length = aMemFrag.getMemFragSize();
            PvmiKvp* retKvp = NULL; // for return value
            int32 err;
            OSCL_TRY(err, config->setParametersSync(NULL, &kvp, 1, retKvp););
            /* ignore the error for now */
            alloc.deallocate((OsclAny*)(kvp.key));
        }
        return true;
    }
    return false;
}

PVMFStatus PVMFOMXEncPort::Connect(PVMFPortInterface* aPort)
{
    if (!aPort)
    {
        return PVMFErrArgument;
    }

    if (iConnectedPort)
    {
        return PVMFFailure;
    }

    OsclAny* temp = NULL;
    aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
    PvmiCapabilityAndConfig* config = (PvmiCapabilityAndConfig*) temp;
    if (!config)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - Peer port does not support capability interface"));
        return PVMFFailure;
    }

    PVMFStatus status = PVMFSuccess;
    switch (iTag)
    {
        case PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT:
            status = NegotiateInputSettings(config);
            break;
        case PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT:
            status = NegotiateOutputSettings(config);
            break;
        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - Invalid port tag"));
            status = PVMFFailure;
    }

    if (status != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - Settings negotiation failed. status=%d", status));
        return status;
    }



    // Automatically connect the peer.

    if (aPort->PeerConnect(this) != PVMFSuccess)
    {
        return PVMFFailure;
    }

    iConnectedPort = aPort;
    PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
    return PVMFSuccess;
}


PVMFStatus PVMFOMXEncPort::PeerConnect(PVMFPortInterface* aPort)
{
    if (!aPort)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x PVMFOMXEncPort::PeerConnect: Error - Connecting to invalid port", this));
        return PVMFErrArgument;
    }

    if (iConnectedPort)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x PVMFOMXEncPort::PeerConnect: Error - Already connected", this));
        return PVMFFailure;
    }

    OsclAny* temp = NULL;
    aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
    PvmiCapabilityAndConfig* config = (PvmiCapabilityAndConfig*) temp;
    if (!config)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::PeerConnect: Error - Peer port does not support capability interface"));
        return PVMFFailure;
    }

    PVMFStatus status = PVMFSuccess;
    switch (iTag)
    {
        case PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT:
            status = NegotiateInputSettings(config);
            break;
        case PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT:
            status = NegotiateOutputSettings(config);
            break;
        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::PeerConnect: Error - Invalid port tag"));
            status = PVMFFailure;
    }

    if (status != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - Settings negotiation failed. status=%d", status));
        return status;
    }

    iConnectedPort = aPort;
    PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
    return PVMFSuccess;
}



// needed for WMV port exchange
void PVMFOMXEncPort::setParametersSync(PvmiMIOSession aSession,
                                       PvmiKvp* aParameters,
                                       int num_elements,
                                       PvmiKvp * & aRet_kvp)
{

    OSCL_UNUSED_ARG(aSession);
    PVMFStatus status = PVMFSuccess;
    aRet_kvp = NULL;

    for (int32 i = 0; i < num_elements; i++)
    {
        status = VerifyAndSetParameter(&(aParameters[i]), true);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVMFOMXEncPort::setParametersSync: Error - VerifiyAndSetParameter failed on parameter #%d", i));
            aRet_kvp = &(aParameters[i]);
        }
    }


}




PVMFStatus PVMFOMXEncPort::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
{

    OSCL_UNUSED_ARG(aSession);

    PVMFStatus status = PVMFSuccess;
    for (int32 i = 0; (i < num_elements) && (status == PVMFSuccess); i++)
        status = VerifyAndSetParameter(&(aParameters[i]));

    return status;


}

PVMFStatus PVMFOMXEncPort::verifyConnectedPortParametersSync(const char* aFormatValType,
        OsclAny* aConfig)
{
    PVMFStatus status = PVMFErrNotSupported;
    PvmiCapabilityAndConfig *capConfig;
    if (iConnectedPort)
    {
        OsclAny* temp = NULL;
        iConnectedPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
        capConfig = (PvmiCapabilityAndConfig*) temp;
    }
    else
        return PVMFFailure;

    if (capConfig != NULL)
    {
        if (pv_mime_strcmp(aFormatValType, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0)
        {
            OsclRefCounterMemFrag* aFormatValue = (OsclRefCounterMemFrag*)aConfig;
            if (aFormatValue->getMemFragSize() > 0)
            {
                OsclMemAllocator alloc;
                PvmiKvp kvp;
                kvp.key = NULL;
                kvp.length = oscl_strlen(aFormatValType) + 1; // +1 for \0
                kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
                if (kvp.key == NULL)
                {
                    return PVMFErrNoMemory;
                }
                oscl_strncpy(kvp.key, aFormatValType, kvp.length);

                kvp.value.key_specific_value = (OsclAny*)(aFormatValue->getMemFragPtr());
                kvp.length = aFormatValue->getMemFragSize();
                kvp.capacity = aFormatValue->getMemFragSize();
                int32 err;
                OSCL_TRY(err, status = capConfig->verifyParametersSync(NULL, &kvp, 1););
                /* ignore the error for now */
                alloc.deallocate((OsclAny*)(kvp.key));

                return status;
            }
        }
        else if (pv_mime_strcmp(aFormatValType, PVMF_BITRATE_VALUE_KEY) == 0 ||
                 pv_mime_strcmp(aFormatValType, PVMF_FRAMERATE_VALUE_KEY) == 0)
        {
            if (aConfig != NULL)
            {
                OsclMemAllocator alloc;
                PvmiKvp kvp;
                kvp.key = NULL;
                kvp.length = oscl_strlen(aFormatValType) + 1; // +1 for \0
                kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
                if (kvp.key == NULL)
                {
                    return PVMFErrNoMemory;
                }
                oscl_strncpy(kvp.key, aFormatValType, kvp.length);
                uint32* bitrate = (uint32*)aConfig;
                kvp.value.uint32_value = *bitrate;

                int32 err;
                OSCL_TRY(err, status = capConfig->verifyParametersSync(NULL, &kvp, 1););
                /* ignore the error for now */
                alloc.deallocate((OsclAny*)(kvp.key));

                return status;
            }
        }
        return PVMFErrArgument;
    }
    return PVMFFailure;
}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////// ENCODER SPECIFIC EXCHANGE TO SET PARAMETERS
////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::GetInputParametersSync(PvmiKeyType identifier, PvmiKvp*& parameters,
        int& num_parameter_elements)
{
    if (iTag != PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT)
        return PVMFFailure;

    PVMFStatus status = PVMFSuccess;

    // this comparison only goes up to delimiter (i.e. ; or /)
    if (pv_mime_strcmp(identifier, INPUT_FORMATS_CAP_QUERY) == 0)
    {
        // get the first parameter as well to compare
        char *param1 = NULL;
        char *param2 = NULL;
        pv_mime_string_extract_param(0, identifier, param1);
        pv_mime_string_extract_param(0, (char*)INPUT_FORMATS_CAP_QUERY, param2);

        if (pv_mime_strcmp(param1, param2) == 0)
        {
            num_parameter_elements = iOMXNode->iCapability.iInputFormatCapability.size();
            status = AllocateKvp(parameters, (OMX_STRING)INPUT_FORMATS_VALTYPE, num_parameter_elements);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetInputParametersSync: Error - AllocateKvp failed. status=%d", status));
                return status;
            }

            uint32 ii = 0;
            Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
            for (it = iOMXNode->iCapability.iInputFormatCapability.begin();
                    it != iOMXNode->iCapability.iInputFormatCapability.end(); it++)
            {
                parameters[ii++].value.pChar_value = OSCL_STATIC_CAST(char*, it->getMIMEStrPtr());
            }
        }
    }

    if (pv_mime_strcmp(identifier, INPUT_FORMATS_CUR_QUERY) == 0)
    {
        // get the first parameter as well to compare
        char *param1 = NULL;
        char *param2 = NULL;
        pv_mime_string_extract_param(0, identifier, param1);
        pv_mime_string_extract_param(0, (char*)INPUT_FORMATS_CUR_QUERY, param2);

        if (pv_mime_strcmp(param1, param2) == 0)
        {
            num_parameter_elements = 1;
            status = AllocateKvp(parameters, (PvmiKeyType)INPUT_FORMATS_VALTYPE, num_parameter_elements);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetInputParametersSync: Error - AllocateKvp failed. status=%d", status));
                return status;
            }
            parameters[0].value.pChar_value = (char*)iFormat.getMIMEStrPtr();
        }
    }
    return status;
}

////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::GetOutputParametersSync(PvmiKeyType identifier, PvmiKvp*& parameters,
        int& num_parameter_elements)
{
    if (iTag != PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT)
        return PVMFFailure;

    PVMFStatus status = PVMFSuccess;

    // this comparison only goes up to the first delimiter i.e. ; or /
    if (pv_mime_strcmp(identifier, (OMX_STRING)OUTPUT_FORMATS_CAP_QUERY) == 0)
    {
        // get the first parameter as well to compare
        char *param1 = NULL;
        char *param2 = NULL;
        pv_mime_string_extract_param(0, identifier, param1);
        pv_mime_string_extract_param(0, (char*)OUTPUT_FORMATS_CAP_QUERY, param2);

        if (pv_mime_strcmp(param1, param2) == 0)
        {
            num_parameter_elements = iOMXNode->iCapability.iOutputFormatCapability.size();
            status = AllocateKvp(parameters, (OMX_STRING)OUTPUT_FORMATS_VALTYPE, num_parameter_elements);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
                return status;
            }

            uint32 ii = 0;
            Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
            for (it = iOMXNode->iCapability.iOutputFormatCapability.begin();
                    it != iOMXNode->iCapability.iOutputFormatCapability.end(); it++)
            {
                parameters[ii++].value.pChar_value = OSCL_STATIC_CAST(char*, it->getMIMEStrPtr());
            }
        }
    }

    if (pv_mime_strcmp(identifier, OUTPUT_FORMATS_CUR_QUERY) == 0)
    {
        // get the first parameter as well to compare
        char *param1 = NULL;
        char *param2 = NULL;
        pv_mime_string_extract_param(0, identifier, param1);
        pv_mime_string_extract_param(0, (char*)OUTPUT_FORMATS_CUR_QUERY, param2);

        if (pv_mime_strcmp(param1, param2) == 0)
        {
            num_parameter_elements = 1;
            status = AllocateKvp(parameters, (OMX_STRING)OUTPUT_FORMATS_VALTYPE, num_parameter_elements);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            }
            else
            {
                parameters[0].value.pChar_value = (char*)iOMXNode->GetCodecType().getMIMEStrPtr();
            }
        }
    }
    else if (pv_mime_strcmp(identifier, VIDEO_OUTPUT_WIDTH_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)VIDEO_OUTPUT_WIDTH_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }

        uint32 width, height;
        status = iOMXNode->GetOutputFrameSize(0, width, height);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error -iOMXNode->GetOutputFrameSize failed. status=%d", status));
        }
        else
        {
            parameters[0].value.uint32_value = width;
        }
    }
    else if (pv_mime_strcmp(identifier, VIDEO_OUTPUT_HEIGHT_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)VIDEO_OUTPUT_HEIGHT_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {
            uint32 width, height;
            status = iOMXNode->GetOutputFrameSize(0, width, height);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - iOMXNode->GetOutputFrameSize failed. status=%d", status));
            }
            else
            {
                parameters[0].value.uint32_value = height;
            }
        }
    }
    else if (pv_mime_strcmp(identifier, VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)VIDEO_OUTPUT_FRAME_RATE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {
            parameters[0].value.float_value = iOMXNode->GetOutputFrameRate(0);
        }
    }
    else if (pv_mime_strcmp(identifier, OUTPUT_BITRATE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)OUTPUT_BITRATE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {

            // NOTE: we assume that port format will be set before this call
            if ((iFormat == PVMF_MIME_AMR_IETF) || (iFormat == PVMF_MIME_AMRWB_IETF) || (iFormat == PVMF_MIME_AMR_IF2) ||
                    (iFormat == PVMF_MIME_ADTS) || (iFormat == PVMF_MIME_ADIF) || (iFormat == PVMF_MIME_MPEG4_AUDIO))
            {
                parameters[0].value.uint32_value = iOMXNode->GetAudioOutputBitRate(); // use audio version - void arg
            }
            else if (iFormat == PVMF_MIME_H2631998 ||
                     iFormat == PVMF_MIME_H2632000 ||
                     iFormat == PVMF_MIME_M4V ||
                     iFormat == PVMF_MIME_H264_VIDEO_RAW ||
                     iFormat == PVMF_MIME_H264_VIDEO_MP4
                    )

            {
                // use the video version
                parameters[0].value.uint32_value = iOMXNode->GetVideoOutputBitRate(0);
            }
            else
            {
                status = PVMFFailure;
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - status=%d", status));
                return status;
            }

        }
    }
    else if (pv_mime_strcmp(identifier, OUTPUT_MAX_BITRATE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)OUTPUT_MAX_BITRATE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {

            // NOTE: we assume that port format will be set before this call
            if ((iFormat == PVMF_MIME_AMR_IETF) || (iFormat == PVMF_MIME_AMRWB_IETF) || (iFormat == PVMF_MIME_AMR_IF2) ||
                    (iFormat == PVMF_MIME_ADTS) || (iFormat == PVMF_MIME_ADIF) || (iFormat == PVMF_MIME_MPEG4_AUDIO))
            {
                parameters[0].value.uint32_value = iOMXNode->GetAudioOutputBitRate(); // use audio version - void arg
            }
            else if (iFormat == PVMF_MIME_H2631998 ||
                     iFormat == PVMF_MIME_H2632000 ||
                     iFormat == PVMF_MIME_M4V ||
                     iFormat == PVMF_MIME_H264_VIDEO_RAW ||
                     iFormat == PVMF_MIME_H264_VIDEO_MP4
                    )

            {
                // use the video version
                parameters[0].value.uint32_value = iOMXNode->GetVideoMaxOutputBitRate(0);
            }
            else
            {
                status = PVMFFailure;
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - status=%d", status));
                return status;
            }

        }
    }
    else if (pv_mime_strcmp(identifier, OUTPUT_DEC_BUFFER_SIZE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)OUTPUT_DEC_BUFFER_SIZE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {
            parameters[0].value.uint32_value = iOMXNode->GetDecBufferSize();
        }
    }
    else if (pv_mime_strcmp(identifier, VIDEO_OUTPUT_IFRAME_INTERVAL_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (OMX_STRING)VIDEO_OUTPUT_IFRAME_INTERVAL_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {
            parameters[0].value.uint32_value = iOMXNode->GetIFrameInterval();
        }
    }
    else if (pv_mime_strcmp(identifier, AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (PvmiKeyType)AUDIO_OUTPUT_SAMPLING_RATE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }

        parameters[0].value.uint32_value = (uint32) iOMXNode->GetOutputSamplingRate();

    }
    else if (pv_mime_strcmp(identifier, AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (PvmiKeyType)AUDIO_OUTPUT_NUM_CHANNELS_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }

        parameters[0].value.uint32_value = (uint32) iOMXNode->GetOutputNumChannels();
    }
    else if (pv_mime_strcmp(identifier, AUDIO_OUTPUT_BITS_PER_SAMPLE_CUR_QUERY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (PvmiKeyType)AUDIO_OUTPUT_BITS_PER_SAMPLE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }

        parameters[0].value.uint32_value = (uint32) iOMXNode->iAudioInputFormat.iInputBitsPerSample;
    }
    else if ((pv_mime_strcmp(identifier, OUTPUT_TIMESCALE_CUR_QUERY) == 0) &&
             ((iFormat == PVMF_MIME_AMR_IETF) ||
              (iFormat == PVMF_MIME_AMRWB_IETF) ||
              (iFormat == PVMF_MIME_AMR_IF2) ||
              (iFormat == PVMF_MIME_ADTS) ||
              (iFormat == PVMF_MIME_ADIF) ||
              (iFormat == PVMF_MIME_MPEG4_AUDIO)
             ))
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_VALUE, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {

            parameters[0].value.uint32_value = (uint32) iOMXNode->GetOutputSamplingRate();

        }
    }
    else if (pv_mime_strcmp(identifier, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0)
    {
        num_parameter_elements = 1;
        status = AllocateKvp(parameters, (PvmiKeyType)PVMF_FORMAT_SPECIFIC_INFO_KEY, num_parameter_elements);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status));
            return status;
        }
        else
        {
            OsclRefCounterMemFrag refMemFrag;
            if (iOMXNode->GetVolHeaderForPort(refMemFrag))
            {
                parameters[0].value.key_specific_value = refMemFrag.getMemFragPtr();
                parameters[0].capacity = refMemFrag.getMemFragSize();
                parameters[0].length = refMemFrag.getMemFragSize();
            }
            else
            {
                releaseParameters(NULL, parameters, num_parameter_elements);
                return PVMFFailure;
            }
        }
    }

    return status;
}

////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::AllocateKvp(PvmiKvp*& aKvp, PvmiKeyType aKey, int32 aNumParams)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncPort::AllocateKvp"));
    uint8* buf = NULL;
    uint32 keyLen = oscl_strlen(aKey) + 1;
    int32 err = 0;

    OSCL_TRY(err,
             buf = (uint8*)iAlloc.allocate(aNumParams * (sizeof(PvmiKvp) + keyLen));
             if (!buf)
             OSCL_LEAVE(OsclErrNoMemory);
            );
    OSCL_FIRST_CATCH_ANY(err,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::AllocateKvp: Error - kvp allocation failed"));
                         return PVMFErrNoMemory;
                        );

    int32 i = 0;
    PvmiKvp* curKvp = aKvp = new(buf) PvmiKvp;
    buf += sizeof(PvmiKvp);
    for (i = 1; i < aNumParams; i++)
    {
        curKvp += i;
        curKvp = new(buf) PvmiKvp;
        buf += sizeof(PvmiKvp);
    }

    for (i = 0; i < aNumParams; i++)
    {
        aKvp[i].key = (char*)buf;
        oscl_strncpy(aKvp[i].key, aKey, keyLen);
        buf += keyLen;
    }

    return PVMFSuccess;
}

////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::VerifyAndSetParameter(PvmiKvp* aKvp, bool aSetParam)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncPort::VerifyAndSetParameter: aKvp=0x%x, aSetParam=%d", aKvp, aSetParam));

    if (!aKvp)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::VerifyAndSetParameter: Error - Invalid key-value pair"));
        return PVMFFailure;
    }

    if (pv_mime_strcmp(aKvp->key, INPUT_FORMATS_VALTYPE) == 0 &&
            iTag == PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT)
    {
        Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
        for (it = iOMXNode->iCapability.iInputFormatCapability.begin();
                it != iOMXNode->iCapability.iInputFormatCapability.end(); it++)
        {
            if (pv_mime_strcmp(aKvp->value.pChar_value, it->getMIMEStrPtr()) == 0)
            {
                if (aSetParam)
                {
                    iFormat = aKvp->value.pChar_value;
                    if (iOMXNode->SetInputFormat(iFormat) != PVMFSuccess)
                        return PVMFFailure;
                }
                return PVMFSuccess;
            }
        }
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::VerifyAndSetParameter: Error - Input format %s not supported",
                        aKvp->value.pChar_value));
        return PVMFFailure;
    }
    else if (pv_mime_strcmp(aKvp->key, OUTPUT_FORMATS_VALTYPE) == 0 &&
             iTag == PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT)
    {

        Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
        for (it = iOMXNode->iCapability.iInputFormatCapability.begin();
                it != iOMXNode->iCapability.iInputFormatCapability.end(); it++)
        {
            if (pv_mime_strcmp(aKvp->value.pChar_value, it->getMIMEStrPtr()) == 0)
            {
                if (aSetParam)
                {
                    iFormat = aKvp->value.pChar_value;
                    if (iOMXNode->SetCodecType(iFormat) != PVMFSuccess)
                        return PVMFFailure;
                }
            }
            return PVMFSuccess;
        }
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::VerifyAndSetParameter: Error - Output format %s not supported",
                        aKvp->value.pChar_value));
        return PVMFFailure;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::VerifyAndSetParameter: Error - Unsupported parameter"));
    return PVMFFailure;
}


////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::NegotiateInputSettings(PvmiCapabilityAndConfig* aConfig)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncPort::NegotiateInputSettings: aConfig=0x%x", aConfig));
    if (!aConfig)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: Error - Invalid config object"));
        return PVMFFailure;
    }

    PvmiKvp* kvp = NULL;
    int numParams = 0;
    int32 err = 0;
    PVMFFormatType videoFormat = 0;
    // Get supported output formats from peer
    PVMFStatus status = aConfig->getParametersSync(NULL, (OMX_STRING)OUTPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL);
    if (status != PVMFSuccess || numParams == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: Error - config->getParametersSync(output_formats) failed"));
        return status;
    }

    OsclPriorityQueue < PvmiKvp*, OsclMemAllocator,
    Oscl_Vector<PvmiKvp*, OsclMemAllocator>,
    PVMFOMXEncInputFormatCompareLess > sortedKvp;

    // Using a priority queue, sort the kvp's returned from aConfig->getParametersSync
    // according to the preference of this port. Formats that are not supported are
    // not pushed to the priority queue and hence dropped from consideration.
    PvmiKvp* selectedAudioKvp = NULL;
    for (int32 i = 0; i < numParams; i++)
    {
        Oscl_Vector<PVMFFormatType, OsclMemAllocator>::iterator it;
        for (it = iOMXNode->iCapability.iInputFormatCapability.begin(); it != iOMXNode->iCapability.iInputFormatCapability.end(); it++)
        {
            // Is the format on the input list?
            if (pv_mime_strcmp(kvp->value.pChar_value, it->getMIMEStrPtr()) == 0)
            {
                // Found.  Is it audio or video?
                if (it->isAudio())
                {
                    // WARNING there should be only one entry for audio!
                    selectedAudioKvp = &kvp[i];
                }
                else // Must be video
                {
                    videoFormat = kvp[i].value.pChar_value;
                    err = PushKVP(sortedKvp, &(kvp[i]));
                    OSCL_FIRST_CATCH_ANY(err,
                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: Error - sortedKvp.push failed"));
                                         return PVMFErrNoMemory;
                                        );
                }
            }
        }
    }

    if (sortedKvp.size() == 0 && (selectedAudioKvp == NULL))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: Error - No matching supported input format"));
        // Release parameters back to peer
        aConfig->releaseParameters(NULL, kvp, numParams);
        kvp = NULL;
        numParams = 0;
        return PVMFFailure;
    }

    PvmiKvp* selectedKvp = NULL;
    if (sortedKvp.size() != 0)
    {
        selectedKvp = sortedKvp.top();
    }
    else
    {
        selectedKvp = selectedAudioKvp;
    }
    PvmiKvp* retKvp = NULL;

    // Set format of this port, peer port and container node
    iFormat = selectedKvp->value.pChar_value;
    if (iOMXNode->SetInputFormat(iFormat) != PVMFSuccess)
        return PVMFFailure;

    err = Config_ParametersSync(aConfig, selectedKvp, retKvp);
    OSCL_FIRST_CATCH_ANY(err,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: Error - aConfig->setParametersSync failed. err=%d", err));
                         return PVMFFailure;
                        );

    // Release parameters back to peer and reset for the next query
    aConfig->releaseParameters(NULL, kvp, numParams);
    kvp = NULL;
    numParams = 0;

    // audio/video negotiation differ
    if (iFormat == PVMF_MIME_PCM16)
    {
        // audio i.e. AMR for now

        // first set bitspersample to 16
        status = iOMXNode->SetInputBitsPerSample(PVMF_AMRENC_DEFAULT_BITSPERSAMPLE);
        if (status != PVMFSuccess)
            return status;


        status = aConfig->getParametersSync(NULL, (PvmiKeyType)AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY, kvp, numParams, NULL);
        uint32 samplingRate = 0;
        if (status != PVMFSuccess || !kvp || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: config->getParametersSync(sampling rate) not supported. Use default."));
            samplingRate = PVMF_AMRENC_DEFAULT_SAMPLING_RATE;
        }
        else
        {
            samplingRate = kvp[0].value.uint32_value;

            aConfig->releaseParameters(NULL, kvp, numParams);
        }


        // Forward settings to encoder
        status = iOMXNode->SetInputSamplingRate(samplingRate);
        if (status != PVMFSuccess)
            return status;

        kvp = NULL;
        numParams = 0;

        status = aConfig->getParametersSync(NULL, (PvmiKeyType)AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY, kvp, numParams, NULL);
        uint32 numChannels = 0;
        if (status != PVMFSuccess || !kvp || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: config->getParametersSync(num channels) not supported. Use default"));
            numChannels = PVMF_AMRENC_DEFAULT_NUM_CHANNELS;
        }
        else
        {
            numChannels = kvp[0].value.uint32_value;

            aConfig->releaseParameters(NULL, kvp, numParams);
        }

        // Forward settings to encoder
        status = iOMXNode->SetInputNumChannels(numChannels);
        if (status != PVMFSuccess)
            return status;

        kvp = NULL;
        numParams = 0;

        // do the "TIMESCALE" query
        status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_QUERY, kvp, numParams, NULL);
        iTimescale = 0;
        if (status != PVMFSuccess || !kvp || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateInputSettings: config->getParametersSync(sampling rate) not supported. Use default."));
            iTimescale = PVMF_AMRENC_DEFAULT_SAMPLING_RATE;
        }
        else
        {
            iTimescale = kvp[0].value.uint32_value;

            aConfig->releaseParameters(NULL, kvp, numParams);
        }

        kvp = NULL;
        numParams = 0;

        return PVMFSuccess;

    }
    else
    {
        // video
        // Get size (in pixels) of video data from peer
        uint32 width = 0;
        uint32 height = 0;
        uint8 orientation = 0;
        status = aConfig->getParametersSync(NULL, (OMX_STRING)VIDEO_OUTPUT_WIDTH_CUR_QUERY, kvp, numParams, NULL);
        if (status != PVMFSuccess || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - config->getParametersSync(current width) failed"));
            return status;
        }
        width = kvp[0].value.uint32_value;
        aConfig->releaseParameters(NULL, kvp, numParams);
        kvp = NULL;
        numParams = 0;

        status = aConfig->getParametersSync(NULL, (OMX_STRING)VIDEO_OUTPUT_HEIGHT_CUR_QUERY, kvp, numParams, NULL);
        if (status != PVMFSuccess || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - config->getParametersSync(current height) failed"));
            return status;
        }
        height = kvp[0].value.uint32_value;
        aConfig->releaseParameters(NULL, kvp, numParams);
        kvp = NULL;
        numParams = 0;

        if ((videoFormat == PVMF_MIME_RGB12) || (videoFormat == PVMF_MIME_RGB24))
        {
            status = aConfig->getParametersSync(NULL, (OMX_STRING)VIDEO_FRAME_ORIENTATION_CUR_QUERY, kvp, numParams, NULL);
            if (status != PVMFSuccess || numParams != 1)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - config->getParametersSync(current height) failed"));
                return status;
            }

            orientation = kvp[0].value.uint8_value;
            aConfig->releaseParameters(NULL, kvp, numParams);
            kvp = NULL;
            numParams = 0;

        }
        // Set input frame size of container node
        status = iOMXNode->SetInputFrameSize(width, height, orientation);
        if (status != PVMFSuccess)
            return status;


        // Get video frame rate from peer
        status = aConfig->getParametersSync(NULL, (OMX_STRING)VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY, kvp, numParams, NULL);
        if (status != PVMFSuccess || numParams != 1)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::Connect: Error - config->getParametersSync(current frame rate) failed"));
            return status;
        }

        // Set input frame rate of container node
        status = iOMXNode->SetInputFrameRate(kvp[0].value.float_value);
        aConfig->releaseParameters(NULL, kvp, numParams);
        kvp = NULL;
        numParams = 0;
        return status;
    }
}

////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFOMXEncPort::NegotiateOutputSettings(PvmiCapabilityAndConfig* aConfig)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncPort::NegotiateOutputSettings: aConfig=0x%x", aConfig));
    if (!aConfig)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateOutputSettings: Error - Invalid config object"));
        return PVMFFailure;
    }

    PvmiKvp* kvp = NULL;
    int numParams = 0;
    int32 i = 0;
    int32 err = 0;

    // Get supported input formats from peer
    PVMFStatus status = aConfig->getParametersSync(NULL, (OMX_STRING)INPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL);
    if (status != PVMFSuccess || numParams == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateOutputSettings: Error - config->getParametersSync(input_formats) failed"));
        return status;
    }

    PvmiKvp* selectedKvp = NULL;
    PvmiKvp* retKvp = NULL;
    for (i = 0; i < numParams && !selectedKvp; i++)
    {
        if (pv_mime_strcmp(kvp[i].value.pChar_value, (char*)iFormat.getMIMEStrPtr()) == 0)
            selectedKvp = &(kvp[i]);
    }

    if (!selectedKvp)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateOutputSettings: Error - Output format not supported by peer"));
        return PVMFFailure;
    }

    err = Config_ParametersSync(aConfig, selectedKvp, retKvp);
    OSCL_FIRST_CATCH_ANY(err,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::NegotiateOutputSettings: Error - aConfig->setParametersSync failed. err=%d", err));
                         return PVMFFailure;
                        );

    aConfig->releaseParameters(NULL, kvp, numParams);
    kvp = NULL;
    numParams = 0;

    return PVMFSuccess;
}
////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF PVMFStatus PVMFOMXEncPort::getParametersSync(PvmiMIOSession session,
        PvmiKeyType identifier,
        PvmiKvp*& parameters,
        int& num_parameter_elements,
        PvmiCapabilityContext context)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncPort::getParametersSync"));
    OSCL_UNUSED_ARG(session);
    OSCL_UNUSED_ARG(context);

    parameters = NULL;
    num_parameter_elements = 0;
    PVMFStatus status = PVMFFailure;

    switch (iTag)
    {
        case PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT:
            return GetInputParametersSync(identifier, parameters, num_parameter_elements);
        case PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT:
            return GetOutputParametersSync(identifier, parameters, num_parameter_elements);
        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncPort::getParametersSync: Error - Invalid port tag"));
            break;
    }

    return status;
}
////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF PVMFStatus PVMFOMXEncPort::releaseParameters(PvmiMIOSession session,
        PvmiKvp* parameters,
        int num_elements)
{
    OSCL_UNUSED_ARG(session);
    OSCL_UNUSED_ARG(num_elements);

    if (parameters)
    {
        iAlloc.deallocate((OsclAny*)parameters);
        return PVMFSuccess;
    }
    else
    {
        return PVMFFailure;
    }
}


// AVC Encoder specific call to send set of SPS and PPS nals to the composer
void PVMFOMXEncPort::SendSPS_PPS(OsclMemoryFragment *aSPSs, int aNumSPSs, OsclMemoryFragment *aPPSs, int aNumPPSs)
{
    int ii;

    OsclAny* temp = NULL;
    iConnectedPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
    PvmiCapabilityAndConfig* config = (PvmiCapabilityAndConfig*) temp;
    if (config)
    {
        for (ii = 0; ii < aNumSPSs; ii++)
        {
            // send SPS
            PvmiKvp* sps, *ret;
            AllocateKvp(sps, (OMX_STRING)VIDEO_AVC_OUTPUT_SPS_CUR_VALUE, 1);

            sps->value.key_specific_value = aSPSs[ii].ptr;
            sps->capacity = aSPSs[ii].len;
            sps->length = aSPSs[ii].len;
            config->setParametersSync(NULL, sps, 1, ret);
            if (ret)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVMFOmxEncPort::SendSPS_PPS: Error returned Kvp is not null."));
            }
            // Release parameters back to peer and reset for the next query
            config->releaseParameters(NULL, sps, 1);
        }
        for (ii = 0; ii < aNumPPSs; ii++)
        {
            // send PPS
            PvmiKvp* pps, *ret;
            AllocateKvp(pps, (OMX_STRING)VIDEO_AVC_OUTPUT_PPS_CUR_VALUE, 1);

            pps->value.key_specific_value = aPPSs[ii].ptr;
            pps->capacity = aPPSs[ii].len;
            pps->length = aPPSs[ii].len;
            config->setParametersSync(NULL, pps, 1, ret);
            if (ret)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVMFOmxEncPort::SendSPS_PPS: Error returned Kvp is not null."));
            }
            // Release parameters back to peer and reset for the next query
            config->releaseParameters(NULL, pps, 1);
        }
    }

    return ;
}

int32 PVMFOMXEncPort::Config_ParametersSync(PvmiCapabilityAndConfig *&aConfig, PvmiKvp *&aSelectedKvp, PvmiKvp *&aRetKvp)
{
    int32 err = 0;
    OSCL_TRY(err, aConfig->setParametersSync(NULL, aSelectedKvp, 1, aRetKvp););
    return err;
}

int32 PVMFOMXEncPort::PushKVP(OsclPriorityQueue<PvmiKvp*, OsclMemAllocator, Oscl_Vector<PvmiKvp*, OsclMemAllocator>, PVMFOMXEncInputFormatCompareLess> &aSortedKvp, PvmiKvp *aKvp)
{
    int32 err = 0;
    OSCL_TRY(err, aSortedKvp.push(aKvp););
    return err;
}

