diff --git a/apps/decoder.c b/apps/decoder.c index 4996122e70dbee11b42bd2994887a4965d5f5606..411bf0a218a1227aae6b850ba03ed93a47449996 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -135,6 +135,7 @@ typedef struct #ifdef IVAS_RTPDUMP bool applyPiData; char *piOutputFilename; + bool rtpOutSR; #endif #ifdef DEBUGGING #ifdef DEBUG_FOA_AGC @@ -448,6 +449,9 @@ int main( asked_frame_size = arg.renderFramesize; uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : 65535; +#ifdef IVAS_RTPDUMP + arg.enableHeadRotation = arg.enableHeadRotation || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; +#endif if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputConfig, arg.renderFramesize, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.non_diegetic_pan_enabled, arg.non_diegetic_pan_gain, arg.dpidEnabled, aeID, arg.objEditEnabled, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK ) @@ -486,7 +490,9 @@ int main( goto cleanup; } +#ifndef IVAS_RTPDUMP arg.enableHeadRotation = true; +#endif } /*------------------------------------------------------------------------------------------* @@ -979,6 +985,7 @@ static bool parseCmdlIVAS_dec( #ifdef IVAS_RTPDUMP arg->applyPiData = false; arg->piOutputFilename = NULL; + arg->rtpOutSR = false; #endif #ifdef SUPPORT_JBM_TRACEFILE @@ -1084,6 +1091,11 @@ static bool parseCmdlIVAS_dec( arg->applyPiData = true; i++; } + else if ( strcmp( argv_to_upper, "-RTPOUTSR" ) == 0 ) + { + arg->rtpOutSR = true; + i++; + } #endif #ifdef SUPPORT_JBM_TRACEFILE else if ( strcmp( argv_to_upper, "-TRACEFILE" ) == 0 ) @@ -1677,6 +1689,7 @@ static void usage_dec( void ) 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" ); + fprintf( stdout, "-rtpOutSR : Split Rendering bitstream RTPDump output \n" ); #else 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" ); @@ -1785,6 +1798,9 @@ static ivas_error initOnFirstGoodFrame( IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS], /* o : */ int16_t *pNumOutChannels, /* o : */ uint16_t *pNumObj, /* o : */ +#ifdef IVAS_RTPDUMP + IVAS_RTP *srRtp, /* o : */ +#endif SplitFileReadWrite **splitRendWriter ) { int16_t isSplitRend, isSplitCoded; @@ -1849,7 +1865,20 @@ static ivas_error initOnFirstGoodFrame( return error; } +#ifdef IVAS_RTPDUMP + if ( arg.rtpOutSR && srRtp != NULL ) + { + /* Split Rendering RTPDump Output file */ + if ( ( error = IVAS_RTP_WRITER_Init( srRtp, arg.outputWavFilename, 1000 / ( IVAS_NUM_FRAMES_PER_SEC * splitRendCodecFrameSizeMs ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: Can't open SR output bitstream file for RTP output %s \n\n", arg.outputWavFilename ); + return error; + } + } + else if ( isSplitCoded ) +#else if ( isSplitCoded ) +#endif { if ( ( error = split_rend_writer_open( splitRendWriter, arg.outputWavFilename, delayNumSamples_temp[0], delayTimeScale_temp, splitRendCodec, poseCorrection, splitRendCodecFrameSizeMs, splitRendIsarFrameSizeMs, arg.output_Fs, lc3plusHighRes ) ) != IVAS_ERR_OK ) { @@ -1883,6 +1912,74 @@ static ivas_error initOnFirstGoodFrame( } } +#ifdef IVAS_RTPDUMP + if ( !arg.rtpOutSR ) + { + int16_t pcmFrameSize; + if ( ( error = IVAS_DEC_GetOutputBufferSize( hIvasDec, &pcmFrameSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetOutputBufferSize, error code: %d\n", error ); + return error; + } + + /* Write zeros to the output audio buffer */ + int16_t *zeroBuf = calloc( pcmFrameSize, sizeof( int16_t ) ); + if ( zeroBuf == NULL ) + { + fprintf( stdout, "Error: Unable to allocate memory for output buffer.\n" ); + return IVAS_ERR_FAILED_ALLOC; + } + + for ( int16_t i = 0; i < numInitialBadFrames; ++i ) + { +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( isSplitRend ) +#else + if ( *splitRendWriter != NULL ) +#endif + { + ISAR_SPLIT_REND_BITS_DATA splitRendBitsZero; + splitRendBitsZero.bits_buf = NULL; + splitRendBitsZero.bits_read = 0; + splitRendBitsZero.bits_written = 0; + splitRendBitsZero.buf_len = 0; + splitRendBitsZero.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + splitRendBitsZero.pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + splitRendBitsZero.codec_frame_size_ms = 0; + splitRendBitsZero.isar_frame_size_ms = 20; + + if ( split_rend_write_bitstream_to_file( *splitRendWriter, splitRendBitsZero.bits_buf, &splitRendBitsZero.bits_read, &splitRendBitsZero.bits_written ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to write to bitstream file!\n" ); + return error; + } + } + +#ifdef FIX_1119_SPLIT_RENDERING_VOIP + if ( !isSplitCoded ) +#else + else +#endif + { + if ( *pRemainingDelayNumSamples < *numOutSamples ) + { + if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, *numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + return error; + } + *pRemainingDelayNumSamples = 0; + } + else + { + *pRemainingDelayNumSamples -= *numOutSamples; + } + } + } + + free( zeroBuf ); + } +#else int16_t pcmFrameSize; if ( ( error = IVAS_DEC_GetOutputBufferSize( hIvasDec, &pcmFrameSize ) ) != IVAS_ERR_OK ) { @@ -1947,6 +2044,8 @@ static ivas_error initOnFirstGoodFrame( free( zeroBuf ); +#endif + /* Open other output files if EXT output config - now details about ISM or MASA are known */ if ( arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -2039,7 +2138,11 @@ static ivas_error initOnFirstGoodFrame( } } +#ifdef IVAS_RTPDUMP + if ( arg.rtpOutSR || *splitRendWriter != NULL ) +#else if ( *splitRendWriter != NULL ) +#endif { if ( numOutSamples == NULL || vec_pos_len == NULL ) { @@ -2583,7 +2686,11 @@ static ivas_error decodeG192( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { +#ifdef IVAS_RTPDUMP + if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, &vec_pos_len, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, NULL, &splitRendWriter ) ) != IVAS_ERR_OK ) +#else if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, &vec_pos_len, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) +#endif { goto cleanup; } @@ -3098,6 +3205,8 @@ static ivas_error decodeVoIP( int16_t i; #ifdef IVAS_RTPDUMP IVAS_RTP ivasRtp = { 0 }; + IVAS_RTP srRtp = { 0 }; + IVAS_RTP_SR_INFO srInfo = { true, false, 0, IVAS_SR_TRANSPORT_LCLD }; int32_t initialTsOffsetSystemAndRTP = 0; #else FILE *f_rtpstream = NULL; @@ -3607,7 +3716,11 @@ static ivas_error decodeVoIP( #else if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, NULL, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, #endif +#ifdef IVAS_RTPDUMP + &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &srRtp, &splitRendWriter ) ) != IVAS_ERR_OK ) +#else &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "Error in initOnFirstGoodFrame(): %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -3620,7 +3733,11 @@ static ivas_error decodeVoIP( } /* Write current frame */ +#ifdef IVAS_RTPDUMP + if ( !srRtp.hPack && decodedGoodFrame ) +#else if ( decodedGoodFrame ) +#endif { #ifdef FIX_1119_SPLIT_RENDERING_VOIP if ( isSplitRend ) @@ -3709,6 +3826,19 @@ static ivas_error decodeVoIP( IVAS_RTP_WriteExtPiData( ivasRtp.f_piExtOut, ivasRtp.piData, ivasRtp.nReadPiData, numObj ); } } +#ifdef IVAS_RTPDUMP + else if ( decodedGoodFrame ) + { + srInfo.bitrateKbps = splitRendBits->bits_written * 1000 / splitRendBits->codec_frame_size_ms; + srInfo.codec = ( splitRendBits->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) ? IVAS_SR_TRANSPORT_LC3PLUS : IVAS_SR_TRANSPORT_LCLD; + if ( ( error = IVAS_RTP_WriteNextFrame( &srRtp, splitRendBits->bits_buf, &srInfo, (int16_t) splitRendBits->bits_written, false, false ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while pushing SR audio bitstream to RTP pack\n", ivas_error_to_string( error ) ); + goto cleanup; + } + } +#endif + vec_pos_update = ( vec_pos_update + 1 ) % vec_pos_len; if ( vec_pos_update == 0 ) @@ -3875,6 +4005,7 @@ static ivas_error decodeVoIP( cleanup: #ifdef IVAS_RTPDUMP + IVAS_RTP_Term( &srRtp ); IVAS_RTP_Term( &ivasRtp ); #else EVS_RTPDUMP_DEPACKER_close( &rtpdumpDepacker ); diff --git a/apps/encoder.c b/apps/encoder.c index 44fda79373b257c91adccbe9d0e54191c78e7383..2bbd131a6160f220829975fad78bcd7f85eb93a5 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -874,7 +874,11 @@ int main( goto cleanup; } +#ifdef RTP_S4_251135_CR26253_0016_REV1 + if ( ( error = IVAS_RTP_WriteNextFrame( &ivasRtp, au, NULL, numBits, isMono, forcePacket ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_RTP_WriteNextFrame( &ivasRtp, au, numBits, isMono, forcePacket ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError %s while pushing audio frame to RTP pack\n", IVAS_ENC_GetErrorMessage( error ) ); goto cleanup; diff --git a/lib_util/ivas_rtp_api.h b/lib_util/ivas_rtp_api.h index d2b2f5fbc87af4e6c489b93b941c093fecdbea6a..06f50ef9e375571774423de333fb953e9f71e8b8 100644 --- a/lib_util/ivas_rtp_api.h +++ b/lib_util/ivas_rtp_api.h @@ -274,6 +274,7 @@ typedef struct { bool valid; /* Valid Split Rendering Info for/in the ToC */ bool diegetic; /* SR content digetic */ + uint32_t bitrateKbps; /* SR bitrate in kbps */ IVAS_RTP_SR_TRANSPORT codec; /* SR Transport Codec used*/ } IVAS_RTP_SR_INFO; #endif /* RTP_S4_251135_CR26253_0016_REV1 */ @@ -344,7 +345,7 @@ ivas_error IVAS_RTP_PACK_PushFrame( IVAS_RTP_PACK_HANDLE hIvasPack, /* i/o : IVAS rtp packer handle */ IVAS_RTP_CODEC codecId, /* i : Codec type (IVAS/EVS) */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info (NULL if absent) */ + const IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info (NULL if absent) */ #endif /* RTP_S4_251135_CR26253_0016_REV1 */ const IVAS_DATA_BUFFER *frameBuffer /* i : packed frame bitstream for IVAS/EVS */ ); diff --git a/lib_util/ivas_rtp_file.c b/lib_util/ivas_rtp_file.c index a0c0193f1015fa072872452bde2bcbc8e7754102..3df5c27d79a41823f6b1a8c262d7a756e676d3e3 100644 --- a/lib_util/ivas_rtp_file.c +++ b/lib_util/ivas_rtp_file.c @@ -754,8 +754,11 @@ ivas_error IVAS_RTP_READER_Init( } ivas_error IVAS_RTP_WriteNextFrame( - IVAS_RTP *rtp, /* i/o : IVAS RTP File writer handle */ - uint8_t *au, /* i : IVAS Compressed AU (Packed frame) */ + IVAS_RTP *rtp, /* i/o : IVAS RTP File writer handle */ + uint8_t *au, /* i : IVAS Compressed AU (Packed frame) */ +#ifdef RTP_S4_251135_CR26253_0016_REV1 + const IVAS_RTP_SR_INFO *srInfo, /* i : Split rendering info in present, else NULL */ +#endif int16_t auSizeBits, /* i : Frame size in bits */ bool isMono, /* i : input was evs(true) or ivas(false) */ bool forcePacket /* i : force packets with whatever frames pushed so far */ @@ -774,7 +777,7 @@ ivas_error IVAS_RTP_WriteNextFrame( error = IVAS_RTP_PACK_PushFrame( rtp->hPack, isMono ? IVAS_RTP_EVS : IVAS_RTP_IVAS, #ifdef RTP_S4_251135_CR26253_0016_REV1 - NULL, + srInfo, #endif /* RTP_S4_251135_CR26253_0016_REV1 */ &packedFrame ); if ( error != IVAS_ERR_OK ) diff --git a/lib_util/ivas_rtp_file.h b/lib_util/ivas_rtp_file.h index 062b29c5c449996719fd9151386fc373277859c2..bd8d2658731f60ab97006ff56c0dcae35b082d81 100644 --- a/lib_util/ivas_rtp_file.h +++ b/lib_util/ivas_rtp_file.h @@ -73,7 +73,11 @@ typedef struct ivas_error IVAS_RTP_WRITER_Init( IVAS_RTP *rtp, const char *outputBitstreamFilename, uint32_t numFramesPerPacket ); ivas_error IVAS_RTP_READER_Init( IVAS_RTP *rtp, const char *inputBitstreamFilename, const char *piOutputFilename, bool isExtOutput, const char *outputWavFilename ); void IVAS_RTP_Term( IVAS_RTP *rtp ); +#ifdef RTP_S4_251135_CR26253_0016_REV1 +ivas_error IVAS_RTP_WriteNextFrame( IVAS_RTP *rtp, uint8_t *au, const IVAS_RTP_SR_INFO *srInfo, int16_t auSizeBits, bool isMono, bool forcePacket ); +#else ivas_error IVAS_RTP_WriteNextFrame( IVAS_RTP *rtp, uint8_t *au, int16_t auSizeBits, bool isMono, bool forcePacket ); +#endif ivas_error IVAS_RTP_ReadNextFrame( IVAS_RTP *rtp, uint8_t *au, int16_t *auSizeBits, uint32_t *rtpTimeStamp, uint16_t *rtpSequenceNumber, uint32_t *nextPacketRcvTime_ms, bool *qBit ); void IVAS_RTP_LogPiData( FILE *f_piDataOut, const PIDATA_TS *piData, uint32_t nPiDataPresent ); void IVAS_RTP_WriteExtPiData( FILE *f_piDataOut, const PIDATA_TS *piData, uint32_t nPiDataPresent, uint16_t numObj ); diff --git a/lib_util/ivas_rtp_payload.c b/lib_util/ivas_rtp_payload.c index c9d26f20eef3f9e8f91c8bb916161f501b08dbc9..97a532022e10b9f9340a8e045dc11f9c8b90c64d 100644 --- a/lib_util/ivas_rtp_payload.c +++ b/lib_util/ivas_rtp_payload.c @@ -835,18 +835,17 @@ static void packEBytes( #ifdef RTP_S4_251135_CR26253_0016_REV1 static ivas_error getSRToCByte( - IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info */ - uint32_t bitrateKbps, /* i : Bitrate in kbps */ - uint8_t *tocByte /* o : toc byte 2 */ + const IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info */ + uint8_t *tocByte /* o : toc byte 2 */ ) { uint8_t bitIdx, codecId, digetic; - if ( bitrateKbps < 256000 || bitrateKbps > 512000 ) + if ( srInfo->bitrateKbps < 256000 || srInfo->bitrateKbps > 512000 ) { return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Unsupported bitrate for SR" ); } - bitIdx = ( ( bitrateKbps / 128000u ) - 1 ) & MASK_2BIT; + bitIdx = ( ( srInfo->bitrateKbps / 128000u ) - 1 ) & MASK_2BIT; codecId = (uint8_t) srInfo->codec; digetic = srInfo->diegetic ? 1 : 0; @@ -882,7 +881,7 @@ ivas_error IVAS_RTP_PACK_PushFrame( IVAS_RTP_PACK_HANDLE hPack, /* i/o : IVAS rtp packer handle */ IVAS_RTP_CODEC codecId, /* i : Codec type (IVAS/EVS) */ #ifdef RTP_S4_251135_CR26253_0016_REV1 - IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info */ + const IVAS_RTP_SR_INFO *srInfo, /* i : Split Rendering Info */ #endif /* RTP_S4_251135_CR26253_0016_REV1 */ const IVAS_DATA_BUFFER *frameBuffer /* i : packed frame bitstream for IVAS/EVS */ ) @@ -907,7 +906,8 @@ ivas_error IVAS_RTP_PACK_PushFrame( else if ( srInfo != NULL && srInfo->valid ) { tocByte = TOC_INDICATE_SR; - error = getSRToCByte( srInfo, bitrate, &tocByte1 ); + frameLengthInBits = frameBuffer->length * 8; + error = getSRToCByte( srInfo, &tocByte1 ); ERR_CHECK_RETURN( error ); } #endif