int WebRtcNetEQ_SplitAndInsertPayload(RTPPacket_t *packet, PacketBuf_t *Buffer_inst,
                                      SplitInfo_t *split_inst, int16_t *flushed)
{

    int i_ok;
    int len;
    int i;
    RTPPacket_t temp_packet;
    int16_t localFlushed = 0;
    const int16_t *pw16_startPayload;
    *flushed = 0;

    len = packet->payloadLen;

    /* Copy to temp packet that can be modified. */

    WEBRTC_SPL_MEMCPY_W8(&temp_packet,packet,sizeof(RTPPacket_t));

    if (split_inst->deltaBytes == NO_SPLIT)
    {
        /* Not splittable codec */
        i_ok = WebRtcNetEQ_PacketBufferInsert(Buffer_inst, packet, &localFlushed);
        *flushed |= localFlushed;
        if (i_ok < 0)
        {
            return PBUFFER_INSERT_ERROR5;
        }
    }
    else if (split_inst->deltaBytes < -10)
    {
        /* G711, PCM16B or G722, use "soft splitting" */
        int split_size = packet->payloadLen;
        int mult = WEBRTC_SPL_ABS_W32(split_inst->deltaBytes) - 10;

        /* Find "chunk size" >= 20 ms and < 40 ms
         * split_inst->deltaTime in this case contains the number of bytes per
         * timestamp unit times 2
         */
        while (split_size >= ((80 << split_inst->deltaTime) * mult))
        {
            split_size >>= 1;
        }

        /* Make the size an even value. */
        if (split_size > 1)
        {
            split_size >>= 1;
            split_size *= 2;
        }
Exemple #2
0
int WebRtcNetEQ_RecInInternal(MCUInst_t *MCU_inst, RTPPacket_t *RTPpacketInput,
                              WebRtc_UWord32 uw32_timeRec)
{
    RTPPacket_t RTPpacket[2];
    int i_k;
    int i_ok = 0, i_No_Of_Payloads = 1;
    WebRtc_Word16 flushed = 0;
    WebRtc_Word16 codecPos;
    WebRtc_UWord32 diffTS, uw32_tmp;
    int curr_Codec;
    WebRtc_Word16 isREDPayload = 0;
    WebRtc_Word32 temp_bufsize = MCU_inst->PacketBuffer_inst.numPacketsInBuffer;
#ifdef NETEQ_RED_CODEC
    RTPPacket_t* RTPpacketPtr[2]; /* Support for redundancy up to 2 payloads */
    RTPpacketPtr[0] = &RTPpacket[0];
    RTPpacketPtr[1] = &RTPpacket[1];
#endif

    /*
     * Copy from input RTP packet to local copy
     * (mainly to enable multiple payloads using RED)
     */

    WEBRTC_SPL_MEMCPY_W8(&RTPpacket[0], RTPpacketInput, sizeof(RTPPacket_t));

    /* Reinitialize NetEq if it's needed (changed SSRC or first call) */

    if ((RTPpacket[0].ssrc != MCU_inst->ssrc) || (MCU_inst->first_packet == 1))
    {
        WebRtcNetEQ_RTCPInit(&MCU_inst->RTCP_inst, RTPpacket[0].seqNumber);
        MCU_inst->first_packet = 0;

        /* Flush the buffer */
        WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);

        /* Store new SSRC */
        MCU_inst->ssrc = RTPpacket[0].ssrc;

        /* Update codecs */
        MCU_inst->timeStamp = RTPpacket[0].timeStamp;
        MCU_inst->current_Payload = RTPpacket[0].payloadType;

        /*Set MCU to update codec on next SignalMCU call */
        MCU_inst->new_codec = 1;

        /* Reset timestamp scaling */
        MCU_inst->TSscalingInitialized = 0;

    }

    /* Call RTCP statistics */
    i_ok |= WebRtcNetEQ_RTCPUpdate(&(MCU_inst->RTCP_inst), RTPpacket[0].seqNumber,
        RTPpacket[0].timeStamp, uw32_timeRec);

    /* If Redundancy is supported and this is the redundancy payload, separate the payloads */
#ifdef NETEQ_RED_CODEC
    if (RTPpacket[0].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
        kDecoderRED))
    {

        /* Split the payload into a main and a redundancy payloads */
        i_ok = WebRtcNetEQ_RedundancySplit(RTPpacketPtr, 2, &i_No_Of_Payloads);
        if (i_ok < 0)
        {
            /* error returned */
            return i_ok;
        }

        /*
         * Only accept a few redundancies of the same type as the main data,
         * AVT events and CNG.
         */
        if ((i_No_Of_Payloads > 1) && (RTPpacket[0].payloadType != RTPpacket[1].payloadType)
            && (RTPpacket[0].payloadType != WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
                kDecoderAVT)) && (RTPpacket[1].payloadType != WebRtcNetEQ_DbGetPayload(
            &MCU_inst->codec_DB_inst, kDecoderAVT)) && (!WebRtcNetEQ_DbIsCNGPayload(
            &MCU_inst->codec_DB_inst, RTPpacket[0].payloadType))
            && (!WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst, RTPpacket[1].payloadType)))
        {
            i_No_Of_Payloads = 1;
        }
        isREDPayload = 1;
    }
#endif

    /* loop over the number of payloads */
    for (i_k = 0; i_k < i_No_Of_Payloads; i_k++)
    {

        if (isREDPayload == 1)
        {
            RTPpacket[i_k].rcuPlCntr = i_k;
        }
        else
        {
            RTPpacket[i_k].rcuPlCntr = 0;
        }

        /* Force update of SplitInfo if it's iLBC because of potential change between 20/30ms */
        if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
            kDecoderILBC))
        {
            i_ok = WebRtcNetEQ_DbGetSplitInfo(
                &MCU_inst->PayloadSplit_inst,
                (enum WebRtcNetEQDecoder) WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
                    RTPpacket[i_k].payloadType), RTPpacket[i_k].payloadLen);
            if (i_ok < 0)
            {
                /* error returned */
                return i_ok;
            }
        }

        /* Get information about timestamp scaling for this payload type */
        i_ok = WebRtcNetEQ_GetTimestampScaling(MCU_inst, RTPpacket[i_k].payloadType);
        if (i_ok < 0)
        {
            /* error returned */
            return i_ok;
        }

        if (MCU_inst->TSscalingInitialized == 0 && MCU_inst->scalingFactor != kTSnoScaling)
        {
            /* Must initialize scaling with current timestamps */
            MCU_inst->externalTS = RTPpacket[i_k].timeStamp;
            MCU_inst->internalTS = RTPpacket[i_k].timeStamp;
            MCU_inst->TSscalingInitialized = 1;
        }

        /* Adjust timestamp if timestamp scaling is needed (e.g. SILK or G.722) */
        if (MCU_inst->TSscalingInitialized == 1)
        {
            WebRtc_UWord32 newTS = WebRtcNetEQ_ScaleTimestampExternalToInternal(MCU_inst,
                RTPpacket[i_k].timeStamp);

            /* save the incoming timestamp for next time */
            MCU_inst->externalTS = RTPpacket[i_k].timeStamp;

            /* add the scaled difference to last scaled timestamp and save ... */
            MCU_inst->internalTS = newTS;

            RTPpacket[i_k].timeStamp = newTS;
        }

        /* Is this a DTMF packet?*/
        if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
            kDecoderAVT))
        {
#ifdef NETEQ_ATEVENT_DECODE
            if (MCU_inst->AVT_PlayoutOn)
            {
                i_ok = WebRtcNetEQ_DtmfInsertEvent(&MCU_inst->DTMF_inst,
                    RTPpacket[i_k].payload, RTPpacket[i_k].payloadLen,
                    RTPpacket[i_k].timeStamp);
                if (i_ok != 0)
                {
                    return i_ok;
                }
            }
#endif
#ifdef NETEQ_STEREO
            if (MCU_inst->usingStereo == 0)
            {
                /* do not set this for DTMF packets when using stereo mode */
                MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
            }
#else
            MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
#endif
        }
        else if (WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst,
            RTPpacket[i_k].payloadType))
        {
            /* Is this a CNG packet? how should we handle this?*/
#ifdef NETEQ_CNG_CODEC
            /* Get CNG sample rate */
            WebRtc_UWord16 fsCng = WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
                RTPpacket[i_k].payloadType);
            if ((fsCng != MCU_inst->fs) && (fsCng > 8000))
            {
                /*
                 * We have received CNG with a different sample rate from what we are using
                 * now (must be > 8000, since we may use only one CNG type (default) for all
                 * frequencies). Flush buffer and signal new codec.
                 */
                WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
                MCU_inst->new_codec = 1;
                MCU_inst->current_Codec = -1;
            }
            i_ok = WebRtcNetEQ_PacketBufferInsert(&MCU_inst->PacketBuffer_inst,
                &RTPpacket[i_k], &flushed);
            if (i_ok < 0)
            {
                return RECIN_CNG_ERROR;
            }
            MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
#else /* NETEQ_CNG_CODEC not defined */
            return RECIN_UNKNOWNPAYLOAD;
#endif /* NETEQ_CNG_CODEC */
        }
        else
        {
            /* Reinitialize the splitting if the payload and/or the payload length has changed */
            curr_Codec = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
                RTPpacket[i_k].payloadType);
            if (curr_Codec != MCU_inst->current_Codec)
            {
                if (curr_Codec < 0)
                {
                    return RECIN_UNKNOWNPAYLOAD;
                }
                MCU_inst->current_Codec = curr_Codec;
                MCU_inst->current_Payload = RTPpacket[i_k].payloadType;
                i_ok = WebRtcNetEQ_DbGetSplitInfo(&MCU_inst->PayloadSplit_inst,
                    (enum WebRtcNetEQDecoder) MCU_inst->current_Codec,
                    RTPpacket[i_k].payloadLen);
                if (i_ok < 0)
                { /* error returned */
                    return i_ok;
                }
                WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
                MCU_inst->new_codec = 1;
            }

            /* update post-call statistics */
            if (MCU_inst->new_codec != 1) /* not if in codec change */
            {
                diffTS = RTPpacket[i_k].timeStamp - MCU_inst->timeStamp; /* waiting time */
                if (diffTS < 0x0FFFFFFF) /* guard against re-ordering */
                {
                    /* waiting time in ms */
                    diffTS = WEBRTC_SPL_UDIV(diffTS,
                        WEBRTC_SPL_UDIV((WebRtc_UWord32) MCU_inst->fs, 1000) );
                    if (diffTS < MCU_inst->statInst.minPacketDelayMs)
                    {
                        /* new all-time low */
                        MCU_inst->statInst.minPacketDelayMs = diffTS;
                    }
                    if (diffTS > MCU_inst->statInst.maxPacketDelayMs)
                    {
                        /* new all-time high */
                        MCU_inst->statInst.maxPacketDelayMs = diffTS;
                    }

                    /* Update avg waiting time:
                     * avgPacketDelayMs =
                     *    (avgPacketCount * avgPacketDelayMs + diffTS)/(avgPacketCount+1)
                     * with proper rounding.
                     */
                    uw32_tmp
                        = WEBRTC_SPL_UMUL((WebRtc_UWord32) MCU_inst->statInst.avgPacketCount,
                            (WebRtc_UWord32) MCU_inst->statInst.avgPacketDelayMs);
                    uw32_tmp
                        = WEBRTC_SPL_ADD_SAT_W32(uw32_tmp,
                            (diffTS + (MCU_inst->statInst.avgPacketCount>>1)));
                    uw32_tmp = WebRtcSpl_DivU32U16(uw32_tmp,
                        (WebRtc_UWord16) (MCU_inst->statInst.avgPacketCount + 1));
                    MCU_inst->statInst.avgPacketDelayMs
                        = (WebRtc_UWord16) WEBRTC_SPL_MIN(uw32_tmp, (WebRtc_UWord32) 65535);

                    /* increase counter, but not to more than 65534 */
                    if (MCU_inst->statInst.avgPacketCount < (0xFFFF - 1))
                    {
                        MCU_inst->statInst.avgPacketCount++;
                    }
                }
            }

            /* Parse the payload and insert it into the buffer */
            i_ok = WebRtcNetEQ_SplitAndInsertPayload(&RTPpacket[i_k],
                &MCU_inst->PacketBuffer_inst, &MCU_inst->PayloadSplit_inst, &flushed);
            if (i_ok < 0)
            {
                return i_ok;
            }
            if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF != 0)
            {
                /* first normal packet after CNG or DTMF */
                MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = -1;
            }
        }
Exemple #3
0
int WebRtcNetEQ_RecInInternal(MCUInst_t *MCU_inst, RTPPacket_t *RTPpacketInput,
                              WebRtc_UWord32 uw32_timeRec)
{
    RTPPacket_t RTPpacket[2];
    int i_k;
    int i_ok = 0, i_No_Of_Payloads = 1;
    WebRtc_Word16 flushed = 0;
    WebRtc_Word16 codecPos;
    int curr_Codec;
    WebRtc_Word16 isREDPayload = 0;
    WebRtc_Word32 temp_bufsize = MCU_inst->PacketBuffer_inst.numPacketsInBuffer;
#ifdef NETEQ_RED_CODEC
    RTPPacket_t* RTPpacketPtr[2]; /* Support for redundancy up to 2 payloads */
    RTPpacketPtr[0] = &RTPpacket[0];
    RTPpacketPtr[1] = &RTPpacket[1];
#endif

    /*
     * Copy from input RTP packet to local copy
     * (mainly to enable multiple payloads using RED)
     */

    WEBRTC_SPL_MEMCPY_W8(&RTPpacket[0], RTPpacketInput, sizeof(RTPPacket_t));

    /* Reinitialize NetEq if it's needed (changed SSRC or first call) */

    if ((RTPpacket[0].ssrc != MCU_inst->ssrc) || (MCU_inst->first_packet == 1))
    {
        WebRtcNetEQ_RTCPInit(&MCU_inst->RTCP_inst, RTPpacket[0].seqNumber);
        MCU_inst->first_packet = 0;

        /* Flush the buffer */
        WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);

        /* Store new SSRC */
        MCU_inst->ssrc = RTPpacket[0].ssrc;

        /* Update codecs */
        MCU_inst->timeStamp = RTPpacket[0].timeStamp;
        MCU_inst->current_Payload = RTPpacket[0].payloadType;

        /*Set MCU to update codec on next SignalMCU call */
        MCU_inst->new_codec = 1;

        /* Reset timestamp scaling */
        MCU_inst->TSscalingInitialized = 0;

    }

    /* Call RTCP statistics */
    i_ok |= WebRtcNetEQ_RTCPUpdate(&(MCU_inst->RTCP_inst), RTPpacket[0].seqNumber,
        RTPpacket[0].timeStamp, uw32_timeRec);

    /* If Redundancy is supported and this is the redundancy payload, separate the payloads */
#ifdef NETEQ_RED_CODEC
    if (RTPpacket[0].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
        kDecoderRED))
    {

        /* Split the payload into a main and a redundancy payloads */
        i_ok = WebRtcNetEQ_RedundancySplit(RTPpacketPtr, 2, &i_No_Of_Payloads);
        if (i_ok < 0)
        {
            /* error returned */
            return i_ok;
        }

        /*
         * Only accept a few redundancies of the same type as the main data,
         * AVT events and CNG.
         */
        if ((i_No_Of_Payloads > 1) && (RTPpacket[0].payloadType != RTPpacket[1].payloadType)
            && (RTPpacket[0].payloadType != WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
                kDecoderAVT)) && (RTPpacket[1].payloadType != WebRtcNetEQ_DbGetPayload(
            &MCU_inst->codec_DB_inst, kDecoderAVT)) && (!WebRtcNetEQ_DbIsCNGPayload(
            &MCU_inst->codec_DB_inst, RTPpacket[0].payloadType))
            && (!WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst, RTPpacket[1].payloadType)))
        {
            i_No_Of_Payloads = 1;
        }
        isREDPayload = 1;
    }
#endif

    /* loop over the number of payloads */
    for (i_k = 0; i_k < i_No_Of_Payloads; i_k++)
    {

        if (isREDPayload == 1)
        {
            RTPpacket[i_k].rcuPlCntr = i_k;
        }
        else
        {
            RTPpacket[i_k].rcuPlCntr = 0;
        }

        /* Force update of SplitInfo if it's iLBC because of potential change between 20/30ms */
        if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
            kDecoderILBC))
        {
            i_ok = WebRtcNetEQ_DbGetSplitInfo(
                &MCU_inst->PayloadSplit_inst,
                (enum WebRtcNetEQDecoder) WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
                    RTPpacket[i_k].payloadType), RTPpacket[i_k].payloadLen);
            if (i_ok < 0)
            {
                /* error returned */
                return i_ok;
            }
        }

        /* Get information about timestamp scaling for this payload type */
        i_ok = WebRtcNetEQ_GetTimestampScaling(MCU_inst, RTPpacket[i_k].payloadType);
        if (i_ok < 0)
        {
            /* error returned */
            return i_ok;
        }

        if (MCU_inst->TSscalingInitialized == 0 && MCU_inst->scalingFactor != kTSnoScaling)
        {
            /* Must initialize scaling with current timestamps */
            MCU_inst->externalTS = RTPpacket[i_k].timeStamp;
            MCU_inst->internalTS = RTPpacket[i_k].timeStamp;
            MCU_inst->TSscalingInitialized = 1;
        }

        /* Adjust timestamp if timestamp scaling is needed (e.g. SILK or G.722) */
        if (MCU_inst->TSscalingInitialized == 1)
        {
            WebRtc_UWord32 newTS = WebRtcNetEQ_ScaleTimestampExternalToInternal(MCU_inst,
                RTPpacket[i_k].timeStamp);

            /* save the incoming timestamp for next time */
            MCU_inst->externalTS = RTPpacket[i_k].timeStamp;

            /* add the scaled difference to last scaled timestamp and save ... */
            MCU_inst->internalTS = newTS;

            RTPpacket[i_k].timeStamp = newTS;
        }

        /* Is this a DTMF packet?*/
        if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
            kDecoderAVT))
        {
#ifdef NETEQ_ATEVENT_DECODE
            if (MCU_inst->AVT_PlayoutOn)
            {
                i_ok = WebRtcNetEQ_DtmfInsertEvent(&MCU_inst->DTMF_inst,
                    RTPpacket[i_k].payload, RTPpacket[i_k].payloadLen,
                    RTPpacket[i_k].timeStamp);
                if (i_ok != 0)
                {
                    return i_ok;
                }
            }
#endif
#ifdef NETEQ_STEREO
            if (MCU_inst->usingStereo == 0)
            {
                /* do not set this for DTMF packets when using stereo mode */
                MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
            }
#else
            MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
#endif
        }
        else if (WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst,
            RTPpacket[i_k].payloadType))
        {
            /* Is this a CNG packet? how should we handle this?*/
#ifdef NETEQ_CNG_CODEC
            /* Get CNG sample rate */
            WebRtc_UWord16 fsCng = WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
                RTPpacket[i_k].payloadType);

            /* Force sampling frequency to 32000 Hz CNG 48000 Hz. */
            /* TODO(tlegrand): remove limitation once ACM has full 48 kHz
             * support. */
            if (fsCng > 32000) {
                fsCng = 32000;
            }
            if ((fsCng != MCU_inst->fs) && (fsCng > 8000))
            {
                /*
                 * We have received CNG with a different sample rate from what we are using
                 * now (must be > 8000, since we may use only one CNG type (default) for all
                 * frequencies). Flush buffer and signal new codec.
                 */
                WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
                MCU_inst->new_codec = 1;
                MCU_inst->current_Codec = -1;
            }
            i_ok = WebRtcNetEQ_PacketBufferInsert(&MCU_inst->PacketBuffer_inst,
                &RTPpacket[i_k], &flushed);
            if (i_ok < 0)
            {
                return RECIN_CNG_ERROR;
            }
            MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
#else /* NETEQ_CNG_CODEC not defined */
            return RECIN_UNKNOWNPAYLOAD;
#endif /* NETEQ_CNG_CODEC */
        }
        else
        {
            /* Reinitialize the splitting if the payload and/or the payload length has changed */
            curr_Codec = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
                RTPpacket[i_k].payloadType);
            if (curr_Codec != MCU_inst->current_Codec)
            {
                if (curr_Codec < 0)
                {
                    return RECIN_UNKNOWNPAYLOAD;
                }
                MCU_inst->current_Codec = curr_Codec;
                MCU_inst->current_Payload = RTPpacket[i_k].payloadType;
                i_ok = WebRtcNetEQ_DbGetSplitInfo(&MCU_inst->PayloadSplit_inst,
                    (enum WebRtcNetEQDecoder) MCU_inst->current_Codec,
                    RTPpacket[i_k].payloadLen);
                if (i_ok < 0)
                { /* error returned */
                    return i_ok;
                }
                WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
                MCU_inst->new_codec = 1;
            }

            /* Parse the payload and insert it into the buffer */
            i_ok = WebRtcNetEQ_SplitAndInsertPayload(&RTPpacket[i_k],
                &MCU_inst->PacketBuffer_inst, &MCU_inst->PayloadSplit_inst, &flushed);
            if (i_ok < 0)
            {
                return i_ok;
            }
            if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF != 0)
            {
                /* first normal packet after CNG or DTMF */
                MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = -1;
            }
        }
        /* Reset DSP timestamp etc. if packet buffer flushed */
        if (flushed)
        {
            MCU_inst->new_codec = 1;
        }
    }

    /*
     * Update Bandwidth Estimate
     * Only send the main payload to BWE
     */
    if ((curr_Codec = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
        RTPpacket[0].payloadType)) >= 0)
    {
        codecPos = MCU_inst->codec_DB_inst.position[curr_Codec];
        if (MCU_inst->codec_DB_inst.funcUpdBWEst[codecPos] != NULL) /* codec has BWE function */
        {
            if (RTPpacket[0].starts_byte1) /* check for shifted byte alignment */
            {
                /* re-align to 16-bit alignment */
                for (i_k = 0; i_k < RTPpacket[0].payloadLen; i_k++)
                {
                    WEBRTC_SPL_SET_BYTE(RTPpacket[0].payload,
                        WEBRTC_SPL_GET_BYTE(RTPpacket[0].payload, i_k+1),
                        i_k);
                }
                RTPpacket[0].starts_byte1 = 0;
            }

            MCU_inst->codec_DB_inst.funcUpdBWEst[codecPos](
                MCU_inst->codec_DB_inst.codec_state[codecPos],
                (G_CONST WebRtc_UWord16 *) RTPpacket[0].payload,
                (WebRtc_Word32) RTPpacket[0].payloadLen, RTPpacket[0].seqNumber,
                (WebRtc_UWord32) RTPpacket[0].timeStamp, (WebRtc_UWord32) uw32_timeRec);
        }
    }

    if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF == 0)
    {
        /* Calculate the total speech length carried in each packet */
        temp_bufsize = MCU_inst->PacketBuffer_inst.numPacketsInBuffer - temp_bufsize;
        temp_bufsize *= MCU_inst->PacketBuffer_inst.packSizeSamples;

        if ((temp_bufsize > 0) && (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF
            == 0) && (temp_bufsize
            != MCU_inst->BufferStat_inst.Automode_inst.packetSpeechLenSamp))
        {
            /* Change the auto-mode parameters if packet length has changed */
            WebRtcNetEQ_SetPacketSpeechLen(&(MCU_inst->BufferStat_inst.Automode_inst),
                (WebRtc_Word16) temp_bufsize, MCU_inst->fs);
        }

        /* update statistics */
        if ((WebRtc_Word32) (RTPpacket[0].timeStamp - MCU_inst->timeStamp) >= 0
            && !MCU_inst->new_codec)
        {
            /*
             * Only update statistics if incoming packet is not older than last played out
             * packet, and if new codec flag is not set.
             */
            WebRtcNetEQ_UpdateIatStatistics(&MCU_inst->BufferStat_inst.Automode_inst,
                MCU_inst->PacketBuffer_inst.maxInsertPositions, RTPpacket[0].seqNumber,
                RTPpacket[0].timeStamp, MCU_inst->fs,
                WebRtcNetEQ_DbIsMDCodec((enum WebRtcNetEQDecoder) MCU_inst->current_Codec),
                (MCU_inst->NetEqPlayoutMode == kPlayoutStreaming));
        }
    }
    else if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF == -1)
    {
        /*
         * This is first "normal" packet after CNG or DTMF.
         * Reset packet time counter and measure time until next packet,
         * but don't update statistics.
         */
        MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 0;
        MCU_inst->BufferStat_inst.Automode_inst.packetIatCountSamp = 0;
    }
    return 0;

}
/*
 * Signals the MCU that DSP status data is available.
 */
int WebRtcNetEQ_SignalMcu(MCUInst_t *inst)
{

    int i_bufferpos, i_res;
    WebRtc_UWord16 uw16_instr;
    DSP2MCU_info_t dspInfo;
    WebRtc_Word16 *blockPtr, blockLen;
    WebRtc_UWord32 uw32_availableTS;
    RTPPacket_t temp_pkt;
    WebRtc_Word32 w32_bufsize, w32_tmp;
    WebRtc_Word16 payloadType = -1;
    WebRtc_Word16 wantedNoOfTimeStamps;
    WebRtc_Word32 totalTS;
    WebRtc_Word16 oldPT, latePacketExist = 0;
    WebRtc_UWord32 oldTS, prevTS, uw32_tmp;
    WebRtc_UWord16 prevSeqNo;
    WebRtc_Word16 nextSeqNoAvail;
    WebRtc_Word16 fs_mult, w16_tmp;
    WebRtc_Word16 lastModeBGNonly = 0;
#ifdef NETEQ_DELAY_LOGGING
    int temp_var;
#endif
    int playDtmf = 0;

    fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000);

    /* Increment counter since last statistics report */
    inst->lastReportTS += inst->timestampsPerCall;

    /* Increment waiting time for all packets. */
    WebRtcNetEQ_IncrementWaitingTimes(&inst->PacketBuffer_inst);

    /* Read info from DSP so we now current status */

    WEBRTC_SPL_MEMCPY_W8(&dspInfo,inst->pw16_readAddress,sizeof(DSP2MCU_info_t));

    /* Set blockPtr to first payload block */
    blockPtr = &inst->pw16_writeAddress[3];

    /* Clear instruction word and number of lost samples (2*WebRtc_Word16) */
    inst->pw16_writeAddress[0] = 0;
    inst->pw16_writeAddress[1] = 0;
    inst->pw16_writeAddress[2] = 0;

    if ((dspInfo.lastMode & MODE_AWAITING_CODEC_PTR) != 0)
    {
        /*
         * Make sure state is adjusted so that a codec update is
         * performed when first packet arrives.
         */
        if (inst->new_codec != 1)
        {
            inst->current_Codec = -1;
        }
        dspInfo.lastMode = (dspInfo.lastMode ^ MODE_AWAITING_CODEC_PTR);
    }

#ifdef NETEQ_STEREO
    if ((dspInfo.lastMode & MODE_MASTER_DTMF_SIGNAL) != 0)
    {
        playDtmf = 1; /* force DTMF decision */
        dspInfo.lastMode = (dspInfo.lastMode ^ MODE_MASTER_DTMF_SIGNAL);
    }

    if ((dspInfo.lastMode & MODE_USING_STEREO) != 0)
    {
        if (inst->usingStereo == 0)
        {
            /* stereo mode changed; reset automode instance to re-synchronize statistics */
            WebRtcNetEQ_ResetAutomode(&(inst->BufferStat_inst.Automode_inst),
                inst->PacketBuffer_inst.maxInsertPositions);
        }
        inst->usingStereo = 1;
        dspInfo.lastMode = (dspInfo.lastMode ^ MODE_USING_STEREO);
    }
    else
    {
        inst->usingStereo = 0;
    }
#endif

    /* detect if BGN_ONLY flag is set in lastMode */
    if ((dspInfo.lastMode & MODE_BGN_ONLY) != 0)
    {
        lastModeBGNonly = 1; /* remember flag */
        dspInfo.lastMode ^= MODE_BGN_ONLY; /* clear the flag */
    }

    if ((dspInfo.lastMode == MODE_RFC3389CNG) || (dspInfo.lastMode == MODE_CODEC_INTERNAL_CNG)
        || (dspInfo.lastMode == MODE_EXPAND))
    {
        /*
         * If last mode was CNG (or Expand, since this could be covering up for a lost CNG
         * packet), increase the CNGplayedTS counter.
         */
        inst->BufferStat_inst.uw32_CNGplayedTS += inst->timestampsPerCall;

        if (dspInfo.lastMode == MODE_RFC3389CNG)
        {
            /* remember that RFC3389CNG is on (needed if CNG is interrupted by DTMF) */
            inst->BufferStat_inst.w16_cngOn = CNG_RFC3389_ON;
        }
        else if (dspInfo.lastMode == MODE_CODEC_INTERNAL_CNG)
        {
            /* remember that internal CNG is on (needed if CNG is interrupted by DTMF) */
            inst->BufferStat_inst.w16_cngOn = CNG_INTERNAL_ON;
        }

    }

    /* Update packet size from previously decoded packet */
    if (dspInfo.frameLen > 0)
    {
        inst->PacketBuffer_inst.packSizeSamples = dspInfo.frameLen;
    }

    /* Look for late packet (unless codec has changed) */
    if (inst->new_codec != 1)
    {
        if (WebRtcNetEQ_DbIsMDCodec((enum WebRtcNetEQDecoder) inst->current_Codec))
        {
            WebRtcNetEQ_PacketBufferFindLowestTimestamp(&inst->PacketBuffer_inst,
                inst->timeStamp, &uw32_availableTS, &i_bufferpos, 1, &payloadType);
            if ((inst->new_codec != 1) && (inst->timeStamp == uw32_availableTS)
                && (inst->timeStamp < dspInfo.playedOutTS) && (i_bufferpos != -1)
                && (WebRtcNetEQ_DbGetPayload(&(inst->codec_DB_inst),
                    (enum WebRtcNetEQDecoder) inst->current_Codec) == payloadType))
            {
                int waitingTime;
                temp_pkt.payload = blockPtr + 1;
                i_res = WebRtcNetEQ_PacketBufferExtract(&inst->PacketBuffer_inst, &temp_pkt,
                    i_bufferpos, &waitingTime);
                if (i_res < 0)
                { /* error returned */
                    return i_res;
                }
                WebRtcNetEQ_StoreWaitingTime(inst, waitingTime);
                *blockPtr = temp_pkt.payloadLen;
                /* set the flag if this is a redundant payload */
                if (temp_pkt.rcuPlCntr > 0)
                {
                    *blockPtr = (*blockPtr) | (DSP_CODEC_RED_FLAG);
                }
                blockPtr += ((temp_pkt.payloadLen + 1) >> 1) + 1;

                /*
                 * Close the data with a zero size block, in case we will not write any
                 * more data.
                 */
                *blockPtr = 0;
                inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0xf0ff)
                        | DSP_CODEC_ADD_LATE_PKT;
                latePacketExist = 1;
            }
        }