Commit 2e4d9fc8 authored by Stefan Doehla's avatar Stefan Doehla
Browse files

Merge branch '1154-add-rtpdump-support_api' into '1154-add-rtpdump-support'

Introduce an ivas rtp api for pack/unpack

See merge request !2174

This merge was agreed in the RTP payload format TF on 2025-08-28. Pending matters will be addressed on !1809.
parents ba624cf8 e3fa8dc5
Loading
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -111,6 +111,11 @@
    <ClCompile Include="..\lib_util\evs_rtp_payload.c" />
    <ClCompile Include="..\lib_util\g192.c" />
    <ClCompile Include="..\lib_util\ivas_rtp_payload.c" />
    <ClCompile Include="..\lib_util\ivas_rtp_pi_data.c" />
    <ClCompile Include="..\lib_util\ivas_rtp_rom.c" />
    <ClCompile Include="..\lib_util\ivas_bpool.c" />
    <ClCompile Include="..\lib_util\ivas_queue.c" />
    <ClCompile Include="..\lib_util\ivas_rtp_file.c" />
    <ClCompile Include="..\lib_util\vector3_pair_file_reader.c" />
    <ClCompile Include="..\lib_util\hrtf_file_reader.c" />
    <ClCompile Include="..\lib_util\ism_file_reader.c" />
+15 −0
Original line number Diff line number Diff line
@@ -85,6 +85,21 @@
    <ClCompile Include="..\lib_util\ivas_rtp_payload.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\ivas_rtp_pi_data.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\ivas_rtp_rom.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\ivas_bpool.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\ivas_queue.c">
      <Filter>util_c</Filter>
    </ClCompile>
    <ClCompile Include="..\lib_util\ivas_rtp_file.c">
      <Filter>util_c</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\lib_util\aeid_file_reader.h">
+601 −84

File changed.

Preview size limit exceeded, changes collapsed.

+150 −40
Original line number Diff line number Diff line
@@ -39,16 +39,16 @@
#include "jbm_file_reader.h"
#include "masa_file_reader.h"
#ifdef IVAS_RTPDUMP
#include "evs_rtp_payload.h"
#include "ivas_rtp_payload.h"
#include "ivas_rtp_api.h"
#include "ivas_rtp_pi_data.h"
#include "rotation_file_reader.h"
#include "ivas_rtp_file.h"
#endif
#ifdef DEBUGGING
#include "debug.h"
#endif
#include "wmc_auto.h"


#define WMC_TOOL_SKIP

/*------------------------------------------------------------------------------------------*
@@ -153,6 +153,7 @@ typedef struct
    bool ism_extended_metadata;
#ifdef IVAS_RTPDUMP
    bool rtpdumpOutput;
    uint32_t numFramesPerPacket;
    char *sceneOrientationTrajFileName;
    char *deviceOrientationTrajFileName;
#endif
@@ -221,9 +222,19 @@ int main(
#endif

#ifdef IVAS_RTPDUMP
    FILE *f_rtpstream = NULL;
    IVAS_RTPDUMP_PACKER *rtpdumpPacker = NULL;
    IVAS_RTPDUMP_PACKER_ERROR rtpdumpPackerError = IVAS_RTPDUMP_PACKER_NO_ERROR;
    IVAS_RTP_FILE_HANDLE hWriter = NULL;
    IVAS_RTP_PACK_HANDLE hPack = NULL;

    uint8_t au[IVAS_MAX_BITS_PER_FRAME / 8];
    uint8_t packet[NOMINAL_BUFFER_SIZE( IVAS_MAX_FRAMES_PER_RTP_PACKET )];
    IVAS_DATA_BUFFER packedFrame = { 0, 0, NULL };
    IVAS_DATA_BUFFER rtpPacket = { 0, 0, NULL };
    uint32_t numFramesInPayload = 0;

    packedFrame.capacity = sizeof( au );
    packedFrame.buffer = au;
    rtpPacket.capacity = sizeof( packet );
    rtpPacket.buffer = packet;
#endif

    /*------------------------------------------------------------------------------------------*
@@ -623,19 +634,38 @@ int main(

    if ( arg.rtpdumpOutput )
    {
        /* Open the output file for RTPDump writing */
        f_rtpstream = fopen( arg.outputBitstreamFilename, "wb" );
        IVAS_RTP_PACK_CONFIG packCfg;
        uint32_t SSRC = ( rand() & 0xFFFF ) | ( (uint32_t) rand() << 16 );

        if ( f_rtpstream == NULL )
        packCfg.maxFramesPerPacket = arg.numFramesPerPacket;

        /* Open the output file for RTPDump writing */
        error = IvasRtpFile_Open ( arg.outputBitstreamFilename, true, &hWriter );
        if ( error != IVAS_ERR_OK )
        {
            fprintf( stderr, "could not open: %s\n", arg.outputBitstreamFilename );
            goto cleanup;
        }

        rtpdumpPackerError = IVAS_RTPDUMP_PACKER_open( &rtpdumpPacker, f_rtpstream );
        if ( rtpdumpPackerError != IVAS_RTPDUMP_PACKER_NO_ERROR )
        error = IVAS_RTP_PACK_Open( &hPack, &packCfg );
        if ( error != IVAS_ERR_OK )
        {
            fprintf( stderr, "error in IVAS_RTP_PACK_Open(): %d\n", error );
            goto cleanup;
        }


        error = IVAS_RTP_PACK_UpdateHeader(
            hPack,
            SSRC,
            0,
            NULL,
            0,
            0,
            NULL );
        if ( error != IVAS_ERR_OK )
        {
            fprintf( stderr, "error in IVAS_RTPDUMP_PACKER_open(): %d\n", rtpdumpPackerError );
            fprintf( stderr, "error in IVAS_RTP_PACK_UpdateHeader(): %d\n", error );
            goto cleanup;
        }
    }
@@ -669,6 +699,7 @@ int main(

    int16_t numSamplesRead = 0;
    uint16_t bitStream[IVAS_MAX_BITS_PER_FRAME];

    uint16_t numBits = 0;
#ifdef DEBUG_SBA
#ifdef DEBUG_AGC
@@ -831,54 +862,99 @@ int main(
        }

        /* *** Encode one frame *** */
        if ( ( error = IVAS_ENC_EncodeFrameToSerial( hIvasEnc, pcmBuf, pcmBufSize, bitStream, &numBits ) ) != IVAS_ERR_OK )
#ifdef IVAS_RTPDUMP
        if ( hPack )
        {
            if ( ( error = IVAS_ENC_EncodeFrameToCompact( hIvasEnc, pcmBuf, pcmBufSize, packedFrame.buffer, &numBits ) ) != IVAS_ERR_OK )
            {
                fprintf( stderr, "\nencodeFrame failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) );
                goto cleanup;
            }

#ifdef IVAS_RTPDUMP
        if ( rtpdumpPacker && rtpdumpPacker->rtpdump )
            packedFrame.length = ( numBits + 7 ) / 8;
            rtpPacket.length = 0;

            /* Push Encoded Stream to */
            if ( ( error = IVAS_RTP_PACK_PushFrame( hPack,
                                                    IVAS_isImmersiveFormat( hIvasEnc ) ? IVAS_RTP_IVAS : IVAS_RTP_EVS,
#ifdef RTP_S4_251135_CR26253_0016_REV1
                                                    NULL,
#endif /* RTP_S4_251135_CR26253_0016_REV1 */
                                                    &packedFrame ) ) != IVAS_ERR_OK )
            {
                fprintf( stderr, "\nError %s while pushing audio frame to RTP pack\n", IVAS_ENC_GetErrorMessage( error ) );
                goto cleanup;
            }

            /* scene orientation */
            if ( sceneOrientationFileReader )
            {
                if ( ( error = HeadRotationFileReading( sceneOrientationFileReader, &rtpdumpPacker->piDataPacker.sceneOrientationQuat, NULL ) ) != IVAS_ERR_OK )
                IVAS_PIDATA_ORIENTATION sceneOrientation = {
                    .size = sizeof( IVAS_PIDATA_ORIENTATION ),
                    .piDataType = IVAS_PI_SCENE_ORIENTATION,
                    .orientation = { 0.0f, 0.0f, 0.0f, 0.0f }
                };

                if ( ( error = HeadRotationFileReading( sceneOrientationFileReader, &sceneOrientation.orientation, NULL ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError %s while reading scene orientation from %s\n", IVAS_ENC_GetErrorMessage( error ), RotationFileReader_getFilePath( sceneOrientationFileReader ) );
                    goto cleanup;
                }
                rtpdumpPacker->piDataPacker.sceneOrientationPresent = true;

                if ( ( error = IVAS_RTP_PACK_PushPiData( hPack, (const IVAS_PIDATA_GENERIC *) &sceneOrientation ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError %s while pushing scene orientation\n", IVAS_ENC_GetErrorMessage( error ) );
                    goto cleanup;
                }
            }

            /* device orientation */
            if ( deviceOrientationFileReader )
            {
                if ( ( error = HeadRotationFileReading( deviceOrientationFileReader, &rtpdumpPacker->piDataPacker.deviceOrientationQuat, NULL ) ) != IVAS_ERR_OK )
                IVAS_PIDATA_ORIENTATION deviceOrientation = {
                    .size = sizeof( IVAS_PIDATA_ORIENTATION ),
                    .piDataType = IVAS_PI_DEVICE_ORIENTATION_COMPENSATED,
                    .orientation = { 0.0f, 0.0f, 0.0f, 0.0f }
                };

                if ( ( error = HeadRotationFileReading( deviceOrientationFileReader, &deviceOrientation.orientation, NULL ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError %s while reading device orientation from %s\n", IVAS_ENC_GetErrorMessage( error ), RotationFileReader_getFilePath( deviceOrientationFileReader ) );
                    goto cleanup;
                }
                rtpdumpPacker->piDataPacker.deviceOrientationPresent = true;
            }

            /* PI presence */
            IVAS_RTPDUMP_PACKER_determinePIpresence( rtpdumpPacker );
                if ( ( error = IVAS_RTP_PACK_PushPiData( hPack, (const IVAS_PIDATA_GENERIC *) &deviceOrientation ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError %s while pushing scene orientation\n", IVAS_ENC_GetErrorMessage( error ) );
                    goto cleanup;
                }
            }

            /* write rtpdump */
            rtpdumpPackerError = IVAS_RTPDUMP_PACKER_writeNextFrame( rtpdumpPacker, bitStream, numBits,
                                                                     IVAS_isImmersiveFormat( hIvasEnc ), 0, false, NO_BANDWIDTH_REQUEST, NO_FORMAT_REQUEST );
            if ( rtpdumpPackerError != IVAS_RTPDUMP_PACKER_NO_ERROR )
            if ( ( numSamplesRead < pcmBufSize ) || IVAS_RTP_PACK_GetNumFrames( hPack ) == arg.numFramesPerPacket )
            {
                /* Generate RTP Packet */
                if ( ( error = IVAS_RTP_PACK_GetPacket( hPack, &rtpPacket, &numFramesInPayload ) ) != IVAS_ERR_OK )
                {
                fprintf( stderr, "IVAS_RTPDUMP_PACKER_writeNextFrame() failed, error code: %d\n", rtpdumpPackerError );
                    fprintf( stderr, "\nError %s while packing RTP Header\n", IVAS_ENC_GetErrorMessage( error ) );
                    goto cleanup;
                }

            IVAS_RTPDUMP_PACKER_resetPIdata( rtpdumpPacker );
                if ( ( error = IvasRtpFile_Write ( hWriter, rtpPacket.buffer, rtpPacket.length ) ) != IVAS_ERR_OK )
                {
                    fprintf( stderr, "\nError %s while writing RTP packet\n", IVAS_ENC_GetErrorMessage( error ) );
                    goto cleanup;
                }
            }
        }
        else
        {
#endif
            if ( ( error = IVAS_ENC_EncodeFrameToSerial( hIvasEnc, pcmBuf, pcmBufSize, bitStream, &numBits ) ) != IVAS_ERR_OK )
            {
                fprintf( stderr, "\nencodeFrame failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) );
                goto cleanup;
            }

            /* write bitstream */
            if ( ( error = BS_Writer_WriteFrame_short( hBsWriter, bitStream, numBits, totalBitrate ) ) != IVAS_ERR_OK )
            {
@@ -966,9 +1042,25 @@ cleanup:
    }

#ifdef IVAS_RTPDUMP
    if ( rtpdumpPacker )
    if ( hPack )
    {
        IVAS_RTPDUMP_PACKER_close( &rtpdumpPacker );
        /* Complete the last packet */
        if ( IVAS_RTP_PACK_GetNumFrames( hPack ) != 0 )
        {
            if ( ( error = IVAS_RTP_PACK_GetPacket( hPack, &rtpPacket, &numFramesInPayload ) ) != IVAS_ERR_OK )
            {
                fprintf( stderr, "\nError %s while packing RTP Packet\n", IVAS_ENC_GetErrorMessage( error ) );
                goto cleanup;
            }

            if ( ( error = IvasRtpFile_Write ( hWriter, rtpPacket.buffer, rtpPacket.length ) ) != IVAS_ERR_OK )
            {
                fprintf( stderr, "\nError %s while writing RTP packet\n", IVAS_ENC_GetErrorMessage( error ) );
                goto cleanup;
            }
        }

        IVAS_RTP_PACK_Close( &hPack );
    }

    if ( sceneOrientationFileReader )
@@ -980,6 +1072,8 @@ cleanup:
    {
        RotationFileReader_close( &deviceOrientationFileReader );
    }

    IvasRtpFile_Close( &hWriter );
#endif

    IVAS_ENC_Close( &hIvasEnc );
@@ -1858,9 +1952,25 @@ static bool parseCmdlIVAS_enc(

        else if ( strcmp( argv_to_upper, "-RTPDUMP" ) == 0 )
        {
            i++;
            arg->rtpdumpOutput = true;
            fprintf( stdout, "Output format: RTPDump\n" );
            ++i;
            if ( i < argc - 4 )
            {
                if ( !is_digits_only( argv[i] ) )
                {
                    arg->numFramesPerPacket = 1; /* Default to 1 frame per packet */
                }
                else
                {
                    arg->numFramesPerPacket = atoi( argv[i++] );
                    if ( arg->numFramesPerPacket > IVAS_MAX_FRAMES_PER_RTP_PACKET )
                    {
                        fprintf( stderr, "numFramesPerPacket(%d) exceeds max frames per packet (%d) \n", arg->numFramesPerPacket, IVAS_MAX_FRAMES_PER_RTP_PACKET );
                        arg->numFramesPerPacket = 1;
                    }
                }
            }
            fprintf( stdout, "Output format: RTPDump using %d frames/packet \n", arg->numFramesPerPacket );
        }

        /*-----------------------------------------------------------------*
@@ -2133,10 +2243,10 @@ static void usage_enc( void )
    fprintf( stdout, "-q                  : Quiet mode, no frame counters\n" );
    fprintf( stdout, "                      default is deactivated\n" );
#ifdef IVAS_RTPDUMP
    fprintf( stdout, "-rtpdump            : RTPDump output, hf_only=1 by default. The encoder will packetize the \n" );
    fprintf( stdout, "-rtpdump <N>        : RTPDump output, hf_only=1 by default. The encoder will packetize the \n" );
    fprintf( stdout, "                      bitstream frames into TS26.253 Annex A IVAS RTP Payload Format packets and \n" );
    fprintf( stdout, "                      writes those to the output file. In EVS mono operating mode, TS26.445 Annex A.2.2 \n" );
    fprintf( stdout, "                      EVS RTP Payload Format is used. \n" );
    fprintf( stdout, "                      EVS RTP Payload Format is used. Optional N represents number of frames per RTP packet\n" );
    fprintf( stdout, "-scene_orientation  : Scene orientation trajectory file. Only used with rtpdump output.\n" );
    fprintf( stdout, "-device_orientation : Device orientation trajectory file. Only used with rtpdump output.\n" );
#endif
+9 −0
Original line number Diff line number Diff line
@@ -150,6 +150,15 @@ typedef enum
    IVAS_ERR_LC3PLUS_INVALID_BITRATE,
    IVAS_ERR_INVALID_SPLIT_REND_CONFIG,

    /*----------------------------------------*
     *               rtp errors               *
     *----------------------------------------*/
    IVAS_ERR_UNDERFLOW = 0x7000,
    IVAS_ERR_PI_DATA_WITH_NO_INPUT_FRAME,
    IVAS_ERR_INSUFFICIENT_OUTPUT_SIZE,
    IVAS_ERR_UNPACK_PI_DATA,
    IVAS_ERR_RTP_UNSUPPORTED_FRAME,

    /*----------------------------------------*
     *              unknown error             *
     *----------------------------------------*/
Loading