Commit de43d43a authored by Ripinder Singh's avatar Ripinder Singh
Browse files

Add dumping of PI Data in decoder, more PI support and bugfixes



* API updates for Pack and Unpack APIs
* Do not report NO_PI_DATA in unpack
* Add support for pack/unpack Listner Position, Diegetic
* Fix PI Data structure for LISTERENR POSITION
* Fix shift in acoustic env pi data unpack
* Add a python implementation of PACK API
* Add tests to validate decoded audio and dumped PI data

Signed-off-by: default avatarRipinder Singh <ripinder.singh@dolby.com>
parent 6dca357c
Loading
Loading
Loading
Loading
Loading
+241 −13
Original line number Original line Diff line number Diff line
@@ -130,6 +130,10 @@ typedef struct
    IVAS_DEC_COMPLEXITY_LEVEL complexityLevel;
    IVAS_DEC_COMPLEXITY_LEVEL complexityLevel;
    bool tsmEnabled;
    bool tsmEnabled;
    IVAS_RENDER_FRAMESIZE renderFramesize;
    IVAS_RENDER_FRAMESIZE renderFramesize;
#ifdef IVAS_RTPDUMP
    bool applyPiData;
    char *piOutputFilename;
#endif
#ifdef DEBUGGING
#ifdef DEBUGGING
    IVAS_DEC_FORCED_REND_MODE forcedRendMode;
    IVAS_DEC_FORCED_REND_MODE forcedRendMode;
#ifdef DEBUG_FOA_AGC
#ifdef DEBUG_FOA_AGC
@@ -183,10 +187,11 @@ typedef struct


typedef struct
typedef struct
{
{
    uint8_t packet[IVAS_NOMINAL_RTP_BYTES_PER_FRAME * IVAS_MAX_FRAMES_PER_RTP_PACKET];
    uint8_t packet[NOMINAL_BUFFER_SIZE( IVAS_MAX_FRAMES_PER_RTP_PACKET )];
    PIDATA_TS piData[IVAS_PI_MAX_ID * IVAS_MAX_FRAMES_PER_RTP_PACKET];
    PIDATA_TS piData[IVAS_PI_MAX_ID * IVAS_MAX_FRAMES_PER_RTP_PACKET];


    FILE *f_rtpstream;
    FILE *f_rtpstream;
    FILE *f_piDataOut;
    IVAS_RTP_CODEC codecId;
    IVAS_RTP_CODEC codecId;
    uint32_t nReadPiData;
    uint32_t nReadPiData;
    uint32_t nProcPiData;
    uint32_t nProcPiData;
@@ -207,6 +212,166 @@ typedef struct
#endif
#endif
} IVAS_RTP;
} IVAS_RTP;


static const char *PiDataNames[IVAS_PI_MAX_ID] = {
    "SCENE_ORIENTATION", "DEVICE_ORIENTATION_COMPENSATED", "DEVICE_ORIENTATION_UNCOMPENSATED",
    "ACOUSTIC_ENVIRONMENT", "AUDIO_DESCRIPTION", "ISM_NUM", "ISM_ID", "ISM_GAIN", "ISM_ORIENTATION",
    "ISM_POSITION", "ISM_DISTANCE_ATTENUATION", "ISM_DIRECTIVITY", "DIEGETIC_TYPE", "RESERVED13",
    "RESERVED14", "RESERVED15", "PLAYBACK_DEVICE_ORIENTATION", "HEAD_ORIENTATION", "LISTENER_POSITION",
    "DYNAMIC_AUDIO_SUPPRESSION", "AUDIO_FOCUS_DIRECTION", "PI_LATENCY", "R_ISM_ID", "R_ISM_GAIN",
    "R_ISM_ORIENTATION", "R_ISM_POSITION", "R_ISM_DIRECTION", "RESERVED27", "RESERVED28", "RESERVED29",
    "RESERVED30", "NO_DATA"
};


static void LogPiData( FILE *f_piDataOut, PIDATA_TS *piData, uint32_t nPiDataPresent )
{
    uint32_t timestamp = ~0u;
    if ( f_piDataOut == NULL || piData == NULL || nPiDataPresent == 0 )
    {
        return;
    }

    if ( ftell( f_piDataOut ) > 2 )
    {
        fprintf( f_piDataOut, ",\n" );
    }

    while ( nPiDataPresent-- > 0 )
    {
        PIDATA_TS *cur = piData++;

        if ( timestamp != ( ~0u ) && timestamp != cur->timestamp )
        {
            fprintf( f_piDataOut, "\n\t},\n\t\"%d\": {\n", cur->timestamp );
        }
        else if ( timestamp != cur->timestamp )
        {
            fprintf( f_piDataOut, "\t\"%d\": {\n", cur->timestamp );
        }
        else
        {
            fprintf( f_piDataOut, ",\n" );
        }
        fprintf( f_piDataOut, "\t\t\"%s\" : ", PiDataNames[cur->data.noPiData.piDataType] );
        switch ( cur->data.noPiData.piDataType )
        {
            case IVAS_PI_SCENE_ORIENTATION:
            case IVAS_PI_DEVICE_ORIENTATION_COMPENSATED:
            case IVAS_PI_DEVICE_ORIENTATION_UNCOMPENSATED:
#ifdef RTP_S4_251135_CR26253_0016_REV1
            case IVAS_PI_PLAYBACK_DEVICE_ORIENTATION:
            case IVAS_PI_HEAD_ORIENTATION:
            case IVAS_PI_AUDIO_FOCUS_DIRECTION:
            case IVAS_PI_R_ISM_ORIENTATION:
#endif
            {
                fprintf( f_piDataOut, "{\n\t\t\t\"w\": %f,\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}",
                         cur->data.scene.orientation.w, cur->data.scene.orientation.x, cur->data.scene.orientation.y, cur->data.scene.orientation.z );
            }
            break;

            case IVAS_PI_ACOUSTIC_ENVIRONMENT:
            {
                fprintf( f_piDataOut, "{\n\t\t\t\"aeid\": %d", cur->data.acousticEnv.aeid );
                if ( cur->data.acousticEnv.availLateReverb )
                {
                    fprintf( f_piDataOut, ",\n\t\t\t\"rt60\": [ %f, %f, %f ],\n", cur->data.acousticEnv.rt60[0], cur->data.acousticEnv.rt60[1], cur->data.acousticEnv.rt60[2] );
                    fprintf( f_piDataOut, "\t\t\t\"dsr\": [ %f, %f, %f ]", cur->data.acousticEnv.dsr[0], cur->data.acousticEnv.dsr[1], cur->data.acousticEnv.dsr[2] );
                }
                if ( cur->data.acousticEnv.availEarlyReflections )
                {
                    fprintf( f_piDataOut, ",\n\t\t\t\"dim\": [ %f, %f, %f ],\n", cur->data.acousticEnv.roomDimensions.x, cur->data.acousticEnv.roomDimensions.y, cur->data.acousticEnv.roomDimensions.z );
                    fprintf( f_piDataOut, "\t\t\t\"abscoeff\": [ %f, %f, %f,  %f, %f, %f ]", cur->data.acousticEnv.absorbCoeffs[0], cur->data.acousticEnv.absorbCoeffs[1], cur->data.acousticEnv.absorbCoeffs[2], cur->data.acousticEnv.absorbCoeffs[3], cur->data.acousticEnv.absorbCoeffs[4], cur->data.acousticEnv.absorbCoeffs[5] );
                }
                fprintf( f_piDataOut, "\n\t\t}" );
            }
            break;
#ifdef RTP_S4_251135_CR26253_0016_REV1
            case IVAS_PI_LISTENER_POSITION:
            case IVAS_PI_R_ISM_POSITION:
            {
                fprintf( f_piDataOut, "{\n\t\t\t\"x\": %f,\n\t\t\t\"y\": %f,\n\t\t\t\"z\": %f \n\t\t}",
                         cur->data.listnerPosition.position.x, cur->data.listnerPosition.position.y, cur->data.listnerPosition.position.z );
            }
            break;
            case IVAS_PI_AUDIO_DESCRIPTION:
            {
                uint32_t nEntries = cur->data.audioDesc.nValidEntries;
                IVAS_AUDIO_ID *audioId = cur->data.audioDesc.audioId;

                fprintf( f_piDataOut, "[\n" );
                while ( nEntries-- > 0 )
                {
                    fprintf( f_piDataOut, "\t\t\t{\n" );
                    fprintf( f_piDataOut, "\t\t\t\t\"isSpeech\": %s,\n", audioId->speech ? "true" : "false" );
                    fprintf( f_piDataOut, "\t\t\t\t\"isMusic\": %s,\n", audioId->music ? "true" : "false" );
                    fprintf( f_piDataOut, "\t\t\t\t\"isAmbiance\": %s,\n", audioId->ambiance ? "true" : "false" );
                    fprintf( f_piDataOut, "\t\t\t\t\"isEditable\": %s,\n", audioId->editable ? "true" : "false" );
                    fprintf( f_piDataOut, "\t\t\t\t\"isBinaural\": %s\n", audioId->binaural ? "true" : "false" );
                    fprintf( f_piDataOut, "\t\t\t}%c\n", ( nEntries == 0 ) ? ' ' : ',' );
                    audioId++;
                }
                fprintf( f_piDataOut, "\t\t]" );
            }
            break;
            case IVAS_PI_DIEGETIC_TYPE:
            {
                bool *isDiegetic = cur->data.digeticIndicator.isDiegetic;
                fprintf( f_piDataOut, "{\n" );
                fprintf( f_piDataOut, "\t\t\t\"isDigetic\": [\n" );
                fprintf( f_piDataOut, "\t\t\t\t%s,\n", isDiegetic[0] ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\t%s,\n", isDiegetic[1] ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\t%s,\n", isDiegetic[2] ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\t%s,\n", isDiegetic[3] ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\t%s\n", isDiegetic[4] ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t]\n\t\t}" );
            }
            break;
            case IVAS_PI_DYNAMIC_AUDIO_SUPPRESSION:
            {
                IVAS_PIDATA_DYNAMIC_SUPPRESSION *das = &cur->data.dynSuppression;
                fprintf( f_piDataOut, "{\n" );
                fprintf( f_piDataOut, "\t\t\t\"preferSpeech\": %s,\n", das->speech ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\"preferMusic\": %s,\n", das->music ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\"preferAmbiance\": %s,\n", das->ambiance ? "true" : "false" );
                fprintf( f_piDataOut, "\t\t\t\"level\": %d", das->sli );
                fprintf( f_piDataOut, "\n\t\t}" );
            }
            break;
            case IVAS_PI_RESERVED13:
            case IVAS_PI_RESERVED14:
            case IVAS_PI_RESERVED15:
            case IVAS_PI_RESERVED27:
            case IVAS_PI_RESERVED28:
            case IVAS_PI_RESERVED29:
            case IVAS_PI_RESERVED30:
            {
                fprintf( f_piDataOut, "{}" );
            }
            break;
            case IVAS_PI_ISM_NUM:
            case IVAS_PI_ISM_ID:
            case IVAS_PI_ISM_GAIN:
            case IVAS_PI_ISM_ORIENTATION:
            case IVAS_PI_ISM_POSITION:
            case IVAS_PI_ISM_DISTANCE_ATTENUATION:
            case IVAS_PI_ISM_DIRECTIVITY:
            case IVAS_PI_PI_LATENCY:
            case IVAS_PI_R_ISM_ID:
            case IVAS_PI_R_ISM_GAIN:
            case IVAS_PI_R_ISM_DIRECTION:
#endif /* RTP_S4_251135_CR26253_0016_REV1 */
            case IVAS_PI_NO_DATA:
            {
                fprintf( f_piDataOut, "{}" );
            }
            break;
        }
        timestamp = cur->timestamp;
    }
    fprintf( f_piDataOut, "\n\t}" );
}

static void IVAS_RTP_Term( IVAS_RTP *rtp )
static void IVAS_RTP_Term( IVAS_RTP *rtp )
{
{
    if ( rtp->f_rtpstream )
    if ( rtp->f_rtpstream )
@@ -214,27 +379,34 @@ static void IVAS_RTP_Term( IVAS_RTP *rtp )
        fclose( rtp->f_rtpstream );
        fclose( rtp->f_rtpstream );
        rtp->f_rtpstream = NULL;
        rtp->f_rtpstream = NULL;
    }
    }
    if ( rtp->f_piDataOut )
    {
        fprintf( rtp->f_piDataOut, "\n}\n" );
        fclose( rtp->f_piDataOut );
        rtp->f_piDataOut = NULL;
    }
    IVAS_RTP_UNPACK_Close( &rtp->hUnpack );
    IVAS_RTP_UNPACK_Close( &rtp->hUnpack );
}
}


static ivas_error IVAS_RTP_Init( IVAS_RTP *rtp, FILE *f_rtpstream )
static ivas_error IVAS_RTP_Init( IVAS_RTP *rtp, FILE *f_rtpstream, FILE *f_piDataOut )
{
{
    ivas_error error = IVAS_ERR_OK;
    ivas_error error = IVAS_ERR_OK;


    memset( rtp, 0, sizeof( IVAS_RTP ) );
    memset( rtp, 0, sizeof( IVAS_RTP ) );


    rtp->unpackCfg.jitterMarginMs = JITTER_DURATION_MS;
    rtp->unpackCfg.maxFramesPerPacket = IVAS_MAX_FRAMES_PER_RTP_PACKET;


    error = IVAS_RTP_UNPACK_Open( &rtp->hUnpack, &rtp->unpackCfg );
    error = IVAS_RTP_UNPACK_Open( &rtp->hUnpack, &rtp->unpackCfg );


    rtp->f_rtpstream = f_rtpstream;
    rtp->f_rtpstream = f_rtpstream;
    rtp->f_piDataOut = f_piDataOut;
    rtp->rtpPacket.buffer = rtp->packet;
    rtp->rtpPacket.buffer = rtp->packet;
    rtp->rtpPacket.capacity = sizeof( rtp->packet );
    rtp->rtpPacket.capacity = sizeof( rtp->packet );


    return error;
    return error;
}
}


static ivas_error readNextFrame( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint8_t *au, int16_t *auSizeBits, uint32_t *rtpTimeStamp, uint16_t *rtpSequenceNumber, uint32_t *nextPacketRcvTime_ms, bool *qBit )
static ivas_error readNextFrame( IVAS_RTP *rtp, uint8_t *au, int16_t *auSizeBits, uint32_t *rtpTimeStamp, uint16_t *rtpSequenceNumber, uint32_t *nextPacketRcvTime_ms, bool *qBit )
{
{
    ivas_error error = IVAS_ERR_OK;
    ivas_error error = IVAS_ERR_OK;
    IVAS_DATA_BUFFER packedFrame = { 0, 0, NULL };
    IVAS_DATA_BUFFER packedFrame = { 0, 0, NULL };
@@ -289,6 +461,7 @@ static ivas_error readNextFrame( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint8_
            rtp->nReadPiData++;
            rtp->nReadPiData++;
            rtp->numPiDataInPacket--;
            rtp->numPiDataInPacket--;
        }
        }
        LogPiData( rtp->f_piDataOut, rtp->piData, rtp->nReadPiData );
    }
    }


#ifdef RTP_S4_251135_CR26253_0016_REV1
#ifdef RTP_S4_251135_CR26253_0016_REV1
@@ -329,8 +502,14 @@ static ivas_error readNextFrame( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint8_
    rtp->numFramesProduced++;
    rtp->numFramesProduced++;
    *nextPacketRcvTime_ms += 20;
    *nextPacketRcvTime_ms += 20;


    return IVAS_ERR_OK;
}

static ivas_error applyPiData( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint32_t rtpTimeStamp )
{
    ivas_error error = IVAS_ERR_OK;
    while ( rtp->nProcPiData < rtp->nReadPiData &&
    while ( rtp->nProcPiData < rtp->nReadPiData &&
            rtp->piData[rtp->nProcPiData].timestamp <= *rtpTimeStamp )
            rtp->piData[rtp->nProcPiData].timestamp <= rtpTimeStamp )
    {
    {
        PIDATA_TS *piData = &rtp->piData[rtp->nProcPiData++];
        PIDATA_TS *piData = &rtp->piData[rtp->nProcPiData++];
        if ( hIvasDec )
        if ( hIvasDec )
@@ -356,7 +535,7 @@ static ivas_error readNextFrame( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint8_


                default:
                default:
                {
                {
                    fprintf( stderr, "Unhandled PI data of type : %d\n", piDataType );
                    fprintf( stderr, "Unhandled PI data of type : %s\n", PiDataNames[piDataType] );
                }
                }
                break;
                break;
            }
            }
@@ -366,8 +545,7 @@ static ivas_error readNextFrame( IVAS_RTP *rtp, IVAS_DEC_HANDLE hIvasDec, uint8_
            }
            }
        }
        }
    }
    }

    return error;
    return IVAS_ERR_OK;
}
}
#endif /* IVAS_RTPDUMP */
#endif /* IVAS_RTPDUMP */


@@ -1304,6 +1482,10 @@ static bool parseCmdlIVAS_dec(
    arg->referenceVectorTrajFileName = NULL;
    arg->referenceVectorTrajFileName = NULL;
    arg->enableExternalOrientation = false;
    arg->enableExternalOrientation = false;
    arg->externalOrientationTrajFileName = NULL;
    arg->externalOrientationTrajFileName = NULL;
#ifdef IVAS_RTPDUMP
    arg->applyPiData = false;
    arg->piOutputFilename = NULL;
#endif


#ifdef SUPPORT_JBM_TRACEFILE
#ifdef SUPPORT_JBM_TRACEFILE
    arg->jbmTraceFilename = NULL;
    arg->jbmTraceFilename = NULL;
@@ -1390,6 +1572,25 @@ static bool parseCmdlIVAS_dec(
            arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF;
            arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF;
            i++;
            i++;
        }
        }
#ifdef IVAS_RTPDUMP
        else if ( strcmp( argv_to_upper, "-PIDATAFILE" ) == 0 )
        {
            i++;
            if ( argc - i <= 3 || argv[i][0] == '-' )
            {
                fprintf( stderr, "Error: PI Data Output file name not specified!\n\n" );
                usage_dec();
                return false;
            }

            arg->piOutputFilename = argv[i++];
        }
        else if ( strcmp( argv_to_upper, "-APPLYPIDATA" ) == 0 )
        {
            arg->applyPiData = true;
            i++;
        }
#endif
#ifdef SUPPORT_JBM_TRACEFILE
#ifdef SUPPORT_JBM_TRACEFILE
        else if ( strcmp( argv_to_upper, "-TRACEFILE" ) == 0 )
        else if ( strcmp( argv_to_upper, "-TRACEFILE" ) == 0 )
        {
        {
@@ -1979,6 +2180,8 @@ static void usage_dec( void )
    fprintf( stdout, "                      EVS RTP Payload Format or rtpdump files containing TS26.253 Annex A\n" );
    fprintf( stdout, "                      EVS RTP Payload Format or rtpdump files containing TS26.253 Annex A\n" );
    fprintf( stdout, "                      IVAS RTP Payload Format. The SDP parameter hf_only is required.\n" );
    fprintf( stdout, "                      IVAS RTP Payload Format. The SDP parameter hf_only is required.\n" );
    fprintf( stdout, "                      Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n" );
    fprintf( stdout, "                      Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n" );
    fprintf( stdout, "-PiDataFile PF        Log the timestampped PI data.\n" );
    fprintf( stdout, "-ApplyPiData          Apply the PI data found in the rtp packet.\n" );
#else
#else
    fprintf( stdout, "-VOIP_hf_only=1     : VoIP mode: EVS RTP Payload Format hf_only=1 in rtpdump\n" );
    fprintf( stdout, "-VOIP_hf_only=1     : VoIP mode: EVS RTP Payload Format hf_only=1 in rtpdump\n" );
    fprintf( stdout, "                      The decoder may read rtpdump files containing TS26.445 Annex A.2.2\n" );
    fprintf( stdout, "                      The decoder may read rtpdump files containing TS26.445 Annex A.2.2\n" );
@@ -3270,7 +3473,7 @@ static ivas_error printBitstreamInfoVoip(
        {
        {
            auPtr = au; /* might have been set to RTP packet in prev call */
            auPtr = au; /* might have been set to RTP packet in prev call */
#ifdef IVAS_RTPDUMP
#ifdef IVAS_RTPDUMP
            error = readNextFrame( &ivasRtp, NULL, auPtr, &auSizeBits, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );
            error = readNextFrame( &ivasRtp, auPtr, &auSizeBits, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );
#else
#else
            rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms, &isAMRWB_IOmode, &frameTypeIndex, &qBit, &auPtr, (uint16_t *) &auSizeBits );
            rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms, &isAMRWB_IOmode, &frameTypeIndex, &qBit, &auPtr, (uint16_t *) &auSizeBits );
#endif
#endif
@@ -3375,6 +3578,8 @@ static ivas_error decodeVoIP(
#ifdef IVAS_RTPDUMP
#ifdef IVAS_RTPDUMP
    IVAS_RTP ivasRtp = { 0 };
    IVAS_RTP ivasRtp = { 0 };
    IVAS_DEC_HANDLE hIvasDec = *phIvasDec;
    IVAS_DEC_HANDLE hIvasDec = *phIvasDec;
    FILE *f_piDataOut = NULL;
    int32_t initialTsOffsetSystemAndRTP = 0;
#else
#else
    EVS_RTPDUMP_DEPACKER rtpdumpDepacker;
    EVS_RTPDUMP_DEPACKER rtpdumpDepacker;
    EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR;
    EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR;
@@ -3441,7 +3646,17 @@ static ivas_error decodeVoIP(
            }
            }


#ifdef IVAS_RTPDUMP
#ifdef IVAS_RTPDUMP
            if ( ( error = IVAS_RTP_Init( &ivasRtp, f_rtpstream ) ) != IVAS_ERR_OK )
            if ( arg.piOutputFilename != NULL )
            {
                f_piDataOut = fopen( arg.piOutputFilename, "w" );
                if ( f_piDataOut == NULL )
                {
                    fprintf( stderr, "could not open: %s\n", arg.piOutputFilename );
                    goto cleanup;
                }
                fprintf( f_piDataOut, "{\n" );
            }
            if ( ( error = IVAS_RTP_Init( &ivasRtp, f_rtpstream, f_piDataOut ) ) != IVAS_ERR_OK )
            {
            {
                fprintf( stderr, "error in IVAS_RTP_Init(): %d\n", error );
                fprintf( stderr, "error in IVAS_RTP_Init(): %d\n", error );
                goto cleanup;
                goto cleanup;
@@ -3496,7 +3711,8 @@ static ivas_error decodeVoIP(
    {
    {
        auPtr = au; /* might have been set to RTP packet in prev call */
        auPtr = au; /* might have been set to RTP packet in prev call */
#ifdef IVAS_RTPDUMP
#ifdef IVAS_RTPDUMP
        error = readNextFrame( &ivasRtp, hIvasDec, auPtr, &auSize, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );
        error = readNextFrame( &ivasRtp, auPtr, &auSize, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );
        initialTsOffsetSystemAndRTP = rtpTimeStamp - systemTime_ms * 16; /* For time mapping */
#else
#else
        rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms, &isAMRWB_IOmode, &frameTypeIndex, &qBit, &auPtr, (uint16_t *) &auSize );
        rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame( &rtpdumpDepacker, &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms, &isAMRWB_IOmode, &frameTypeIndex, &qBit, &auPtr, (uint16_t *) &auSize );
#endif
#endif
@@ -3700,7 +3916,7 @@ static ivas_error decodeVoIP(
            {
            {
                auPtr = au; /* might have been set to RTP packet in prev call */
                auPtr = au; /* might have been set to RTP packet in prev call */
#ifdef IVAS_RTPDUMP
#ifdef IVAS_RTPDUMP
                error = readNextFrame( &ivasRtp, hIvasDec, au, &auSize, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );
                error = readNextFrame( &ivasRtp, au, &auSize, &rtpTimeStamp, &rtpSequenceNumber, &nextPacketRcvTime_ms, &qBit );


                /* IVAS RTP payload format has timescale 16000, JBM uses 1000 internally */
                /* IVAS RTP payload format has timescale 16000, JBM uses 1000 internally */
                rtpTimeStamp = rtpTimeStamp / 16;
                rtpTimeStamp = rtpTimeStamp / 16;
@@ -3745,6 +3961,18 @@ static ivas_error decodeVoIP(
        /* decode and get samples */
        /* decode and get samples */
        while ( nSamplesRendered < nOutSamples )
        while ( nSamplesRendered < nOutSamples )
        {
        {
#ifdef IVAS_RTPDUMP
            if ( arg.applyPiData )
            {
                /* Rudimentry Time Mapping to map system time to rtp timestamp */
                uint32_t piTs = systemTime_ms * 16 + initialTsOffsetSystemAndRTP;
                if ( ( error = applyPiData( &ivasRtp, hIvasDec, piTs ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) );
                    goto cleanup;
                }
            }
#endif
#ifdef SUPPORT_JBM_TRACEFILE
#ifdef SUPPORT_JBM_TRACEFILE
            if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, &parametersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK )
            if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, writeJbmTraceFileFrameWrapper, jbmTraceWriter, &bitstreamReadDone, &nSamplesRendered, &parametersAvailableForEditing, systemTime_ms ) ) != IVAS_ERR_OK )
#else
#else
+1 −1
Original line number Original line Diff line number Diff line
@@ -225,7 +225,7 @@ int main(
    IVAS_RTP_PACK_HANDLE hPack = NULL;
    IVAS_RTP_PACK_HANDLE hPack = NULL;


    uint8_t au[IVAS_MAX_BITS_PER_FRAME / 8];
    uint8_t au[IVAS_MAX_BITS_PER_FRAME / 8];
    uint8_t packet[IVAS_NOMINAL_RTP_BYTES_PER_FRAME * IVAS_MAX_FRAMES_PER_RTP_PACKET];
    uint8_t packet[NOMINAL_BUFFER_SIZE(IVAS_MAX_FRAMES_PER_RTP_PACKET)];
    IVAS_DATA_BUFFER packedFrame = { 0, 0, NULL };
    IVAS_DATA_BUFFER packedFrame = { 0, 0, NULL };
    IVAS_DATA_BUFFER rtpPacket = { 0, 0, NULL };
    IVAS_DATA_BUFFER rtpPacket = { 0, 0, NULL };
    uint32_t numFramesInPayload = 0, packetLength = 0;
    uint32_t numFramesInPayload = 0, packetLength = 0;
+14 −4
Original line number Original line Diff line number Diff line
@@ -82,7 +82,9 @@ extern "C"
 * estimate or RTP packet size per frame. The additional PI data is assumed to add upto a 20%
 * estimate or RTP packet size per frame. The additional PI data is assumed to add upto a 20%
 * overhead in bitrate for the computation.
 * overhead in bitrate for the computation.
 */
 */
#define IVAS_NOMINAL_RTP_BYTES_PER_FRAME ( ( IVAS_MAX_BITS_PER_FRAME + ( IVAS_MAX_BITS_PER_FRAME / 5 ) ) / 8 )
#define NOMINAL_BUFFER_SIZE( numFramesPerPacket ) ( ( IVAS_MAX_BITS_PER_FRAME + ( IVAS_MAX_BITS_PER_FRAME / 5 ) ) * ( numFramesPerPacket ) / 8 )

#define DEFAULT_MAX_PACKET_BYTES ( 1400 ) /* Typical MTU size of 4G/5G Cellular Interfaces */


#define NO_BITRATE_REQ ( 0u ) /* If no bitrate is requested from remote */
#define NO_BITRATE_REQ ( 0u ) /* If no bitrate is requested from remote */


@@ -375,8 +377,8 @@ extern "C"


    /* Generate a rtp payload using available pushed frames
    /* Generate a rtp payload using available pushed frames
     *
     *
     * Available remote requests, pi data and frames will be packed into a rtp payload. If no
     * Available remote requests, pi data and frames will be packed into a rtp payload. The
     * frame is pushed before call to this api, NO_DATA_FRAME will be generated
     * capacity field of payload is used to limits the maximum RTP packet size.
     *
     *
     */
     */
    ivas_error IVAS_RTP_PACK_GetPayload(
    ivas_error IVAS_RTP_PACK_GetPayload(
@@ -408,7 +410,7 @@ extern "C"
    /* Initial configuration for rtp unpacker */
    /* Initial configuration for rtp unpacker */
    typedef struct
    typedef struct
    {
    {
        uint32_t jitterMarginMs; /* expected max jitter duration in milliseconds  */
        uint32_t maxFramesPerPacket; /* maximum no of frame per packet expected during the session */
    } IVAS_RTP_UNPACK_CONFIG;
    } IVAS_RTP_UNPACK_CONFIG;


    /* Open an instance of the RTP unpacker and return a handle to rtp unpacker on success
    /* Open an instance of the RTP unpacker and return a handle to rtp unpacker on success
@@ -432,6 +434,10 @@ extern "C"
     * the number of NO_DATA frame received. All PullFrame calls for non NO_DATA frames shall
     * the number of NO_DATA frame received. All PullFrame calls for non NO_DATA frames shall
     * be reported with timestamp jump indicating missing/NO_DATA IVAS frames.
     * be reported with timestamp jump indicating missing/NO_DATA IVAS frames.
     *
     *
     * It is important to ensure IVAS_RTP_UNPACK_PushPayload, IVAS_RTP_UNPACK_PullFrame and
     * IVAS_RTP_UNPACK_PullNextPiData API are invoked in same thread context else a race condition
     * can arise if new packet is pushed while frames/pidata are still being pulled out.
     *
     * Example usage : -
     * Example usage : -
     * ==================
     * ==================
     * err = IVAS_RTP_UNPACK_PushPayload(hIvasUnpack, payload, rtpTs, seqNum,
     * err = IVAS_RTP_UNPACK_PushPayload(hIvasUnpack, payload, rtpTs, seqNum,
@@ -489,6 +495,10 @@ extern "C"
     * the number of NO_DATA frame received. All PullFrame calls for non NO_DATA frames shall
     * the number of NO_DATA frame received. All PullFrame calls for non NO_DATA frames shall
     * be reported with timestamp jump indicating missing/NO_DATA IVAS frames.
     * be reported with timestamp jump indicating missing/NO_DATA IVAS frames.
     *
     *
     * It is important to ensure IVAS_RTP_UNPACK_PushPacket, IVAS_RTP_UNPACK_PullFrame and
     * IVAS_RTP_UNPACK_PullNextPiData API are invoked in same thread context else a race condition
     * can arise if new packet is pushed while frames/pidata are still being pulled out.
     *
     * Example usage : -
     * Example usage : -
     * ==================
     * ==================
     * err = IVAS_RTP_UNPACK_PushPacket(hIvasUnpack, packet, &nFrames, &nPiData, &reqBitmap);
     * err = IVAS_RTP_UNPACK_PushPacket(hIvasUnpack, packet, &nFrames, &nPiData, &reqBitmap);
+20 −5
Original line number Original line Diff line number Diff line
@@ -489,6 +489,7 @@ ivas_error IVAS_RTP_PACK_Open(
{
{
    ivas_error error;
    ivas_error error;
    IVAS_RTP_PACK_HANDLE hPack;
    IVAS_RTP_PACK_HANDLE hPack;
    uint32_t numFramesPerPacket = ( config->maxFramesPerPacket == 0 ) ? 1 : config->maxFramesPerPacket;


    if ( phPack == NULL )
    if ( phPack == NULL )
    {
    {
@@ -501,7 +502,7 @@ ivas_error IVAS_RTP_PACK_Open(
        return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS rtppack handle" );
        return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS rtppack handle" );
    }
    }


    error = BPOOL_Create( &hPack->packNodePool, sizeof( FRAME_NODE ), IVAS_MAX_FRAMES_IN_QUEUE );
    error = BPOOL_Create( &hPack->packNodePool, sizeof( FRAME_NODE ), numFramesPerPacket * 4 );
    ERR_CHECK_RETURN( error );
    ERR_CHECK_RETURN( error );


    error = QUEUE_Create( &hPack->frameQ );
    error = QUEUE_Create( &hPack->frameQ );
@@ -1192,9 +1193,7 @@ ivas_error IVAS_RTP_UNPACK_Open(
        return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS rtp unpack handle" );
        return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS rtp unpack handle" );
    }
    }


    /* maxNumberOfFrames =  Ping Pong RTP Packet with max frames per packet + any jitter adjustment frames */
    hUnpack->maxNumberOfFrames = ( config->maxFramesPerPacket < IVAS_MAX_FRAMES_PER_RTP_PACKET ) ? IVAS_MAX_FRAMES_PER_RTP_PACKET : config->maxFramesPerPacket;
    hUnpack->maxNumberOfFrames += IVAS_MAX_FRAMES_PER_RTP_PACKET * 2;
    hUnpack->maxNumberOfFrames += ( ( config->jitterMarginMs * IVAS_NUM_FRAMES_PER_SEC + 1000 - 1 ) / 1000 ); /* Jitter in Packets + Ping/Pong */
    hUnpack->maxNumberOfPiData = hUnpack->maxNumberOfFrames * IVAS_PI_MAX_ID;
    hUnpack->maxNumberOfPiData = hUnpack->maxNumberOfFrames * IVAS_PI_MAX_ID;


    error = BPOOL_Create( &hUnpack->unpackNodePool, sizeof( UNPACK_NODE ), hUnpack->maxNumberOfFrames );
    error = BPOOL_Create( &hUnpack->unpackNodePool, sizeof( UNPACK_NODE ), hUnpack->maxNumberOfFrames );
@@ -1544,7 +1543,16 @@ static ivas_error parsePIData( IVAS_RTP_UNPACK_HANDLE hUnpack, uint32_t rtpTimes
            }
            }
        } while ( byte == 255 );
        } while ( byte == 255 );


        if ( nBytes + piSize <= payload->length )
        if ( piDataType == IVAS_PI_NO_DATA )
        {
            if ( piSize > 0 )
            {
                return IVAS_ERROR( IVAS_ERR_UNPACK_PI_DATA, "NO_PI_DATA should be 0 sized" );
            }

            /* Do not add a node for NO_DATA */
        }
        else if ( nBytes + piSize <= payload->length )
        {
        {
            PIDATA_NODE *node = NULL;
            PIDATA_NODE *node = NULL;
            ivas_error error = BPOOL_GetBuffer( hUnpack->piDataPool, (void **) &node );
            ivas_error error = BPOOL_GetBuffer( hUnpack->piDataPool, (void **) &node );
@@ -1614,6 +1622,13 @@ ivas_error IVAS_RTP_UNPACK_PushPayload(
        *numPiDataInPacket = 0;
        *numPiDataInPacket = 0;
    }
    }


    /* Sanity check if any frame or PI data from last packet is still not pulled */
    if ( QUEUE_Size( hUnpack->frameQ ) > 0 || QUEUE_Size( hUnpack->piDataQ ) > 0 )
    {
        assert( 0 );
        return IVAS_ERROR( IVAS_ERR_INTERNAL, "Previous packet data should be consumed before next packet is pushed" );
    }

    memcpy( oldRequests, hUnpack->requests, sizeof( oldRequests ) );
    memcpy( oldRequests, hUnpack->requests, sizeof( oldRequests ) );


    /* Unpack IVAS Payload, starting with the E-Bytes */
    /* Unpack IVAS Payload, starting with the E-Bytes */
Loading