Commit 290e40ea authored by Lauros Pajunen's avatar Lauros Pajunen
Browse files

Restructure code, move PI data parsing to utils from lib_dec

parent d8f66c1b
Loading
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -3384,14 +3384,13 @@ static ivas_error decodeVoIP(
                /* IVAS RTP payload format has timescale 16000, JBM uses 1000 internally */
                rtpTimeStamp = rtpTimeStamp / 16;

                /* parse PI data */
                error = IVAS_DEC_parsePIdata( hIvasDec, &rtpdumpDepacker.PIdataCurrentFrame, &rtpdumpDepacker.PIdataDepackerState );
                /* feed PI data to decoder handle */
                error = IVAS_DEC_feedPIdata( hIvasDec, &rtpdumpDepacker.PIdataDepackerState );
                if ( error != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError in IVAS_DEC_parsePIdata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
                    fprintf( stderr, "\nError in IVAS_DEC_feedPIdata: %s\n", IVAS_DEC_GetErrorMessage( error ) );
                    goto cleanup;
                }
                IVAS_DEC_resetPIdataCurrentFrame( &rtpdumpDepacker.PIdataCurrentFrame );
#else
                rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp,
                                                                           &nextPacketRcvTime_ms,
+0 −9
Original line number Diff line number Diff line
@@ -821,15 +821,6 @@ void QuaternionInverse(
    IVAS_QUATERNION *const r
);

void resetPIdataCurrentFrame(
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame                   /* o  : PI data handle for the current audio frame                  */
);

bool ivasPayload_parseOrientationPIdata(
    char *PIorientationData,                                    /* i/o: Pointer to the PI data frame containing a single quaternion orientation */
    IVAS_QUATERNION *q                                          /* o  : Parsed quaternion value                                                 */
);

#endif
/*----------------------------------------------------------------------------------*
 * JBM prototypes
+15 −43
Original line number Diff line number Diff line
@@ -3723,24 +3723,23 @@ ivas_error IVAS_DEC_Flush(

#ifdef IVAS_RTPDUMP
/*---------------------------------------------------------------------*
 * IVAS_DEC_parseSinglePIorientation( )
 * IVAS_DEC_feedSinglePIorientation( )
 *
 * Parse a single orientation from PI data and feed to external orientation handle.
 * Save the parsed (inverted) orientation value and use in processing in future frames, if no new PI orientation is received.
 * Feed a single orientation PI data to external orientation handle.
 *---------------------------------------------------------------------*/

ivas_error IVAS_DEC_parseSinglePIorientation(
ivas_error IVAS_DEC_feedSinglePIorientation(
    IVAS_DEC_HANDLE hIvasDec,            /* i/o: IVAS decoder handle                                                     */
    char *orientation,                   /* i  : input PI orientation                                                    */
    bool *isOrientationSaved,            /* i  : flag to indicate if an orientation for this PI type was previously saved  */
    IVAS_QUATERNION *savedInvOrientation /* i  : previously saved (inverted) orientation for this PI type                */
    const bool *isOrientationSaved,      /* i  : flag to indicate if an orientation for this PI type was previously saved  */
    IVAS_QUATERNION *savedOrientation    /* i  : previously saved orientation for this PI type                           */
)
{
    int16_t i;
    ivas_error error = IVAS_ERR_OK;
    if ( orientation )
    IVAS_QUATERNION savedInvOrientation;

    if ( *isOrientationSaved )
    {
        IVAS_QUATERNION orientationQuat, orientationQuatInv;
        if ( !hIvasDec->st_ivas->hExtOrientationData )
        {
            if ( ( error = ivas_external_orientation_open( &( hIvasDec->st_ivas->hExtOrientationData ), hIvasDec->st_ivas->hDecoderConfig->render_framesize ) ) != IVAS_ERR_OK )
@@ -3757,24 +3756,12 @@ ivas_error IVAS_DEC_parseSinglePIorientation(
            }
        }

        /* read the orientation PI value */
        if ( !ivasPayload_parseOrientationPIdata( orientation, &orientationQuat ) )
        {
            return IVAS_ERROR( IVAS_ERR_INTERNAL, "Parsing PI orientation failed" );
        }
        QuaternionInverse( orientationQuat, &orientationQuatInv );
        QuaternionInverse( *savedOrientation, &savedInvOrientation );

        /* update the saved orientation value */
        *isOrientationSaved = true;
        *savedInvOrientation = orientationQuatInv;
    }

    if ( *isOrientationSaved )
    {
        /* use the new PI orientation or the previously saved orientation in processing */
        for ( i = 0; i < hIvasDec->st_ivas->hExtOrientationData->num_subframes; i++ )
        {
            QuaternionProduct( hIvasDec->st_ivas->hExtOrientationData->Quaternions[i], *savedInvOrientation,
            QuaternionProduct( hIvasDec->st_ivas->hExtOrientationData->Quaternions[i], savedInvOrientation,
                               &hIvasDec->st_ivas->hExtOrientationData->Quaternions[i] );
            hIvasDec->st_ivas->hExtOrientationData->enableExternalOrientation[i] = true;
        }
@@ -3785,27 +3772,26 @@ ivas_error IVAS_DEC_parseSinglePIorientation(


/*---------------------------------------------------------------------*
 * IVAS_DEC_parsePIdata( )
 * IVAS_DEC_feedPIdata( )
 *
 * Parse PI data for a single frame
 * Feed PI data to the decoder handle
 *---------------------------------------------------------------------*/

ivas_error IVAS_DEC_parsePIdata(
ivas_error IVAS_DEC_feedPIdata(
    IVAS_DEC_HANDLE hIvasDec,                   /* i/o: IVAS decoder handle                                                     */
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame,  /* i  : PI data handle for the current frame                                    */
    PI_DATA_DEPACKER_STATE *PIdataDepackerState /* i/o: data handle for the PI depacker state                                   */
)
{
    ivas_error error = IVAS_ERR_OK;

    /* scene orientation */
    if ( ( error = IVAS_DEC_parseSinglePIorientation( hIvasDec, PIdataCurrentFrame->sceneOrientation, &PIdataDepackerState->sceneOrientationSaved, &PIdataDepackerState->sceneOrientationQuat ) ) != IVAS_ERR_OK )
    if ( ( error = IVAS_DEC_feedSinglePIorientation( hIvasDec, &PIdataDepackerState->sceneOrientationSaved, &PIdataDepackerState->sceneOrientationQuat ) ) != IVAS_ERR_OK )
    {
        return error;
    }

    /* device orientation */
    if ( ( error = IVAS_DEC_parseSinglePIorientation( hIvasDec, PIdataCurrentFrame->deviceOrientationUncompensated, &PIdataDepackerState->deviceOrientationSaved, &PIdataDepackerState->deviceOrientationQuat ) ) != IVAS_ERR_OK )
    if ( ( error = IVAS_DEC_feedSinglePIorientation( hIvasDec, &PIdataDepackerState->deviceOrientationSaved, &PIdataDepackerState->deviceOrientationQuat ) ) != IVAS_ERR_OK )
    {
        return error;
    }
@@ -3828,20 +3814,6 @@ void IVAS_DEC_resetExternalOrientations(
}


/*---------------------------------------------------------------------*
 * IVAS_DEC_resetPIdataCurrentFrame( )
 *
 * Reset current PI frame struct
 *---------------------------------------------------------------------*/

void IVAS_DEC_resetPIdataCurrentFrame(
    PI_DATA_CURRENT_FRAME *piDataCurrentFrame /* i/o: PI data handle for the current frame                                    */
)
{
    resetPIdataCurrentFrame( piDataCurrentFrame );
}


#endif
/*---------------------------------------------------------------------*
 * IVAS_DEC_VoIP_IsEmpty( )
+4 −10
Original line number Diff line number Diff line
@@ -330,16 +330,14 @@ ivas_error IVAS_DEC_Flush(
);

#ifdef IVAS_RTPDUMP
ivas_error IVAS_DEC_parseSinglePIorientation(
ivas_error IVAS_DEC_feedSinglePIorientation(
    IVAS_DEC_HANDLE hIvasDec,                   /* i/o: IVAS decoder handle                                                     */
    char *orientation,                          /* i  : input PI orientation                                                    */
    bool *isOrientationSaved,                   /* i  : flag to indicate if an orientation for this PI type was previously saved  */
    IVAS_QUATERNION *savedInvOrientation        /* i  : previously saved (inverted) orientation for this PI type                */
    const bool *isOrientationSaved,             /* i  : flag to indicate if an orientation for this PI type was previously saved  */
    IVAS_QUATERNION *savedOrientation           /* i  : previously saved orientation for this PI type                           */
);

ivas_error IVAS_DEC_parsePIdata(
ivas_error IVAS_DEC_feedPIdata(
    IVAS_DEC_HANDLE hIvasDec,                   /* i/o: IVAS decoder handle                                                     */
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame,  /* i  : PI data handle for the current frame                                    */
    PI_DATA_DEPACKER_STATE *PIdataDepackerState /* i/o: data handle for the PI depacker state                                   */
);

@@ -347,10 +345,6 @@ void IVAS_DEC_resetExternalOrientations(
    IVAS_DEC_HANDLE hIvasDec                    /* i/o: IVAS decoder handle                                                     */
);

void IVAS_DEC_resetPIdataCurrentFrame(
    PI_DATA_CURRENT_FRAME *piDataCurrentFrame   /* i/o: PI data handle for the current frame                                    */
);

#endif
/* Setter functions - apply changes to decoder configuration */

+148 −104
Original line number Diff line number Diff line
@@ -196,6 +196,133 @@ static void ivasPayload_PIaddHeaderBytes(
}


/*-----------------------------------------------------------------------*
 * ivasPayload_convertFromQ15()
 *
 * Convert a Q15 encoded value to a float value.
 *-----------------------------------------------------------------------*/

static float ivasPayload_convertFromQ15( uint16_t Q15Value )
{
    float temp;
    temp = (float) ( Q15Value & 0x7FFF ) / 0x7FFF;
    return ( Q15Value & 0x8000 ) ? -temp : temp;
}


/*-----------------------------------------------------------------------*
 * ivasPayload_convertToQ15()
 *
 * Convert a float value into a Q15 encoded value.
 *-----------------------------------------------------------------------*/

static uint16_t ivasPayload_convertToQ15( float value )
{
    uint16_t temp;
    temp = (uint16_t) ( fabsf( value ) * 0x7FFF );
    if ( value >= 0.0f )
    {
        temp = temp & 0x7FFF;
    }
    else
    {
        temp = temp | 0x8000;
    }
    return temp;
}


/*-----------------------------------------------------------------------*
 * ivasPayload_convertOrientationToQ15()
 *
 * Convert a float quaternion into a Q15 encoded quaternion.
 *-----------------------------------------------------------------------*/

static void ivasPayload_convertOrientationToQ15(
    IVAS_QUATERNION orientation,        /* i  : Input orientation in quaternion to be converted to Q15      */
    IVAS_QUATERNION_Q15 *orientationQ15 /* o  : Ouput orientation in Q15 quaternion                         */
)
{
    orientationQ15->w = ivasPayload_convertToQ15( orientation.w );
    orientationQ15->x = ivasPayload_convertToQ15( orientation.x );
    orientationQ15->y = ivasPayload_convertToQ15( orientation.y );
    orientationQ15->z = ivasPayload_convertToQ15( orientation.z );
}


/*-----------------------------------------------------------------------*
 * ivasPayload_parseQuaternionValue()
 *
 * Parse a single Q15 encoded quaternion component from the RTP packet and convert it to float.
 *-----------------------------------------------------------------------*/

static float ivasPayload_parseQuaternionComponent(
    char **PIorientationData /* i/o: Pointer to the PI data frame containing a single quaternion component */
)
{
    uint16_t tempQ15value;
    tempQ15value = ( uint16_t ) * *PIorientationData;
    tempQ15value = (uint16_t) ( ( tempQ15value << 8 ) | ( uint16_t ) * ( *PIorientationData + 1 ) );
    *PIorientationData += 2;
    return ivasPayload_convertFromQ15( tempQ15value );
}


/*-----------------------------------------------------------------------*
 * ivasPayload_parseOrientationPIdata()
 *
 * Parse a single orientation in quaternions from the PI data.
 *-----------------------------------------------------------------------*/

static bool ivasPayload_parseOrientationPIdata(
    char *PIorientationData, /* i/o: Pointer to the PI data frame containing a single quaternion orientation */
    IVAS_QUATERNION *q       /* o  : Parsed quaternion value                                                 */
)
{
    q->w = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->x = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->y = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->z = ivasPayload_parseQuaternionComponent( &PIorientationData );

    if ( q->w > 1.0f || q->w < -1.0f ||
         q->x > 1.0f || q->x < -1.0f ||
         q->y > 1.0f || q->y < -1.0f ||
         q->z > 1.0f || q->z < -1.0f )
    {
        fprintf( stderr, "Error: invalid orientation PI data\n" );
        return false;
    }
    return true;
}


/*---------------------------------------------------------------------*
 * ivasPayload_parseSinglePIorientation( )
 *
 * Parse a single orientation from PI data.
 * Save the parsed orientation value and use in processing in future frames, if no new PI orientation is received.
 *---------------------------------------------------------------------*/

static bool ivasPayload_parseSinglePIorientation(
    char *orientation,                   /* i  : input PI orientation                                                    */
    bool *isOrientationSaved,            /* o  : flag to indicate if an orientation for this PI type was previously saved  */
    IVAS_QUATERNION *savedOrientation    /* o  : saved orientation value for this PI type                                */
)
{
    if ( orientation )
    {
        /* read the orientation PI value */
        if ( !ivasPayload_parseOrientationPIdata( orientation, savedOrientation ) )
        {
            fprintf( stderr, "Error: parsing PI orientation failed\n" );
            return false;
        }
        *isOrientationSaved = true;
    }
    return true;
}


/*-----------------------------------------------------------------------*
 * ivasPayload_parsePIdata()
 *
@@ -206,7 +333,8 @@ static bool ivasPayload_parsePIdata(
    char *PIdataPayload,                      /* i  : Pointer to the beginning of the PI data section in the RTP packet */
    uint16_t PIdataPayloadSizeBytes,          /* i  : Size of the PI data section in bytes                              */
    uint16_t frameIndex,                      /* i  : Index to the current audio frame in the RTP packet                */
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame /* o  : PI data handle for the current audio frame                        */
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame,/* o  : PI data handle for the current audio frame                        */
    PI_DATA_DEPACKER_STATE *PIdataDepackerState /* i/o: data handle for the PI depacker state                           */
)
{
    // TODO(pajunen): can this accidentally include zero padding bits?
@@ -273,79 +401,21 @@ static bool ivasPayload_parsePIdata(
    }
    ivasPayload_PIaddHeaderBytes( totalPIheaderSizeBytes, PIdataCurrentFrame );

    return true;
}


/*-----------------------------------------------------------------------*
 * ivasPayload_convertFromQ15()
 *
 * Convert a Q15 encoded value to a float value.
 *-----------------------------------------------------------------------*/

static float ivasPayload_convertFromQ15( uint16_t Q15Value )
{
    float temp;
    temp = (float) ( Q15Value & 0x7FFF ) / 0x7FFF;
    return ( Q15Value & 0x8000 ) ? -temp : temp;
}


/*-----------------------------------------------------------------------*
 * ivasPayload_convertToQ15()
 *
 * Convert a float value into a Q15 encoded value.
 *-----------------------------------------------------------------------*/

static uint16_t ivasPayload_convertToQ15( float value )
{
    uint16_t temp;
    temp = (uint16_t) ( fabsf( value ) * 0x7FFF );
    if ( value >= 0.0f )
    {
        temp = temp & 0x7FFF;
    }
    else
    /* scene orientation */
    if ( !ivasPayload_parseSinglePIorientation( PIdataCurrentFrame->sceneOrientation, &PIdataDepackerState->sceneOrientationSaved, &PIdataDepackerState->sceneOrientationQuat ) )
    {
        temp = temp | 0x8000;
    }
    return temp;
        fprintf( stderr, "Error: parsing scene orientation PI data failed.\n" );
        return false;
    }


/*-----------------------------------------------------------------------*
 * ivasPayload_convertOrientationToQ15()
 *
 * Convert a float quaternion into a Q15 encoded quaternion.
 *-----------------------------------------------------------------------*/

static void ivasPayload_convertOrientationToQ15(
    IVAS_QUATERNION orientation,        /* i  : Input orientation in quaternion to be converted to Q15      */
    IVAS_QUATERNION_Q15 *orientationQ15 /* o  : Ouput orientation in Q15 quaternion                         */
)
    /* device orientation */
    if ( !ivasPayload_parseSinglePIorientation( PIdataCurrentFrame->deviceOrientationUncompensated, &PIdataDepackerState->deviceOrientationSaved, &PIdataDepackerState->deviceOrientationQuat ) )
    {
    orientationQ15->w = ivasPayload_convertToQ15( orientation.w );
    orientationQ15->x = ivasPayload_convertToQ15( orientation.x );
    orientationQ15->y = ivasPayload_convertToQ15( orientation.y );
    orientationQ15->z = ivasPayload_convertToQ15( orientation.z );
        fprintf( stderr, "Error: parsing device orientation PI data failed.\n" );
        return false;
    }


/*-----------------------------------------------------------------------*
 * ivasPayload_parseQuaternionValue()
 *
 * Parse a single Q15 encoded quaternion component from the RTP packet and convert it to float.
 *-----------------------------------------------------------------------*/

static float ivasPayload_parseQuaternionComponent(
    char **PIorientationData /* i/o: Pointer to the PI data frame containing a single quaternion component */
)
{
    uint16_t tempQ15value;
    tempQ15value = ( uint16_t ) * *PIorientationData;
    tempQ15value = (uint16_t) ( ( tempQ15value << 8 ) | ( uint16_t ) * ( *PIorientationData + 1 ) );
    *PIorientationData += 2;
    return ivasPayload_convertFromQ15( tempQ15value );
    return true;
}


@@ -355,7 +425,7 @@ static float ivasPayload_parseQuaternionComponent(
 * Reset the PI data handle for the current audio frame.
 *-----------------------------------------------------------------------*/

void resetPIdataCurrentFrame( PI_DATA_CURRENT_FRAME *PIdataCurrentFrame )
static void resetPIdataCurrentFrame( PI_DATA_CURRENT_FRAME *PIdataCurrentFrame )
{
    PIdataCurrentFrame->PIdataPresent = false;
    PIdataCurrentFrame->sceneOrientation = NULL;
@@ -367,33 +437,6 @@ void resetPIdataCurrentFrame( PI_DATA_CURRENT_FRAME *PIdataCurrentFrame )
}


/*-----------------------------------------------------------------------*
 * ivasPayload_parseOrientationPIdata()
 *
 * Parse a single orientation in quaternions from the PI data.
 *-----------------------------------------------------------------------*/

bool ivasPayload_parseOrientationPIdata(
    char *PIorientationData, /* i/o: Pointer to the PI data frame containing a single quaternion orientation */
    IVAS_QUATERNION *q       /* o  : Parsed quaternion value                                                 */
)
{
    q->w = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->x = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->y = ivasPayload_parseQuaternionComponent( &PIorientationData );
    q->z = ivasPayload_parseQuaternionComponent( &PIorientationData );

    if ( q->w > 1.0f || q->w < -1.0f ||
         q->x > 1.0f || q->x < -1.0f ||
         q->y > 1.0f || q->y < -1.0f ||
         q->z > 1.0f || q->z < -1.0f )
    {
        fprintf( stderr, "Error: invalid orientation PI data\n" );
        return false;
    }
    return true;
}

bool ivasPayload_unpackFrame(
    char *payload,                            /* i  : RTP payload data                                                */
    uint16_t payloadSizeBytes,                /* i  : RTP payload size in bytes                                       */
@@ -406,7 +449,7 @@ bool ivasPayload_unpackFrame(
                                               *       In EVS mode, this is the Q-bit (see A.2.2.1.2 in TS26.445)     */
    unsigned char **frame,                    /* o  : Data frame indicated by frameIndex                              */
    uint16_t *frameSizeInBits,                /* o  : Data frame size in bits                                         */
    PI_DATA_CURRENT_FRAME *PIdataCurrentFrame /* o  : PI data for frame indicated by frameIndex                       */
    PI_DATA_DEPACKER_STATE *PIdataDepackerState /* i/o: data handle for the PI depacker state                         */
)
{
    bool someEvsIvasModeBit, someFrameFollowing, someIvasIndicatorBit;
@@ -417,6 +460,8 @@ bool ivasPayload_unpackFrame(
    fullPayloadSizeBytes = payloadSizeBytes;
    PIdataPayload = payload;
    someFrameFollowing = true;
    PI_DATA_CURRENT_FRAME PIdataCurrentFrame;
    resetPIdataCurrentFrame( &PIdataCurrentFrame );
    if ( payloadSizeBytes < 1 )
    {
        fprintf( stderr, "Error: payload too small to parse ToC\n" );
@@ -425,7 +470,7 @@ bool ivasPayload_unpackFrame(
    /* parse CMR/E-bytes */
    if ( *payload & E_BYTE ) // 1xxx xxxx
    {
        PIdataCurrentFrame->PIdataPresent = false;
        PIdataCurrentFrame.PIdataPresent = false;
        while ( 1 )
        {
            if ( ( *payload & 0xF0 ) == IVAS_E_CMR ) // 1111 xxxx
@@ -487,7 +532,7 @@ bool ivasPayload_unpackFrame(
                    else if ( ( *payload & 0xE0 ) == IVAS_E_PI_INDICATION ) // 110x xxxx
                    {
                        /* IVAS PI presence */
                        PIdataCurrentFrame->PIdataPresent = true;
                        PIdataCurrentFrame.PIdataPresent = true;
                    }
                    else if ( ( *payload & 0xE0 ) == IVAS_E_RESERVED ) // 111x xxxx
                    {
@@ -574,11 +619,11 @@ bool ivasPayload_unpackFrame(
    }

    /* parse PI data */
    if ( PIdataCurrentFrame->PIdataPresent )
    if ( PIdataCurrentFrame.PIdataPresent )
    {
        PIdataPayloadSizeBytes = payloadSizeBytes;
        PIdataPayload += ( fullPayloadSizeBytes - PIdataPayloadSizeBytes );
        if ( !ivasPayload_parsePIdata( PIdataPayload, PIdataPayloadSizeBytes, frameIndex, PIdataCurrentFrame ) )
        if ( !ivasPayload_parsePIdata( PIdataPayload, PIdataPayloadSizeBytes, frameIndex, &PIdataCurrentFrame, PIdataDepackerState ) )
        {
            fprintf( stderr, "Error while parsing PI data\n" );
            return false;
@@ -600,7 +645,6 @@ IVAS_RTPDUMP_DEPACKER_ERROR IVAS_RTPDUMP_DEPACKER_open(
    {
        return IVAS_RTPDUMP_DEPACKER_RTPDUMP_ERROR;
    }
    resetPIdataCurrentFrame( &self->PIdataCurrentFrame );
    self->PIdataDepackerState.sceneOrientationSaved = false;
    self->PIdataDepackerState.deviceOrientationSaved = false;
    return IVAS_RTPDUMP_DEPACKER_NO_ERROR;
@@ -638,7 +682,7 @@ IVAS_RTPDUMP_DEPACKER_ERROR IVAS_RTPDUMP_DEPACKER_readNextFrame(
    if ( !ivasPayload_unpackFrame( self->rtpPacket.data + self->rtpPacket.headerSize,
                                   self->rtpPacket.payloadSize, self->frameIndex,
                                   evsIvasModeBit, &self->frameFollowing, bitrateIndex, ivasIndicatorBit,
                                   frame, frameSizeBits, &self->PIdataCurrentFrame ) )
                                   frame, frameSizeBits, &self->PIdataDepackerState ) )
    {
        return IVAS_RTPDUMP_DEPACKER_PAYLOAD_ERROR;
    }
Loading