Commit e0a12076 authored by Lauros Pajunen's avatar Lauros Pajunen
Browse files

Merge branch '1154-add-rtpdump-support-format-pi-latency' into 'main'

Resolve "Add rtpdump support" - add PI latency

See merge request !2343
parents 7475c404 78b1f30f
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@
#define IVAS_RTPDUMP                                   /* RTPDUMP writing and reading for IVAS payloads */
#define IVAS_RTPDUMP_ACOUSTIC_ENVIRONMENT              /* RTPDUMP acoustic environment */
#define FIXED_RTP_SEQUENCE_NUM                         /* Remove random sequence number initialization */
#define PI_LATENCY                                     /* Pi latency PI frame */
#define ISM_PI_DATA                                    /* Add reading and packing/unpacking of ISM PI data */
#define REVERSE_ISM_PI_DATA                            /* Add reading and packing/unpacking of reverse ISM PI data */

+12 −1
Original line number Diff line number Diff line
@@ -444,8 +444,19 @@ void IVAS_RTP_LogPiData(
            case IVAS_PI_ISM_POSITION:
            case IVAS_PI_ISM_DISTANCE_ATTENUATION:
            case IVAS_PI_ISM_DIRECTIVITY:
            {
                fprintf( f_piDataOut, "{}" );
            }
            break;
#endif
            case IVAS_PI_PI_LATENCY:
            {
                fprintf( f_piDataOut, "{" );
                fprintf( f_piDataOut, "\n\t\t\t\"reverseType\": \"%s\",", PiDataNames[cur->data.piLatency.type] );
                fprintf( f_piDataOut, "\n\t\t\t\"latency\": %d", cur->data.piLatency.latency );
                fprintf( f_piDataOut, "\n\t\t}" );
            }
            break;
            case IVAS_PI_R_ISM_ID:
#ifdef REVERSE_ISM_PI_DATA
            {
@@ -707,7 +718,7 @@ void IVAS_RTP_WriteExtPiData(
            break;
            case IVAS_PI_PI_LATENCY:
            {
                fprintf( f_piDataOut, "%d", cur->data.piLatency.latency );
                fprintf( f_piDataOut, "%s,%d", PiDataNames[cur->data.piLatency.type], cur->data.piLatency.latency );
            }
            break;
            case IVAS_PI_R_ISM_ID:
+80 −2
Original line number Diff line number Diff line
@@ -938,7 +938,75 @@ static ivas_error unpackISMID( const uint8_t *buffer, uint32_t numDataBytes, IVA

    return IVAS_ERR_OK;
}
#endif
#ifdef PI_LATENCY
static ivas_error packPiLatency( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten )
{
    uint32_t typeBits;
    uint32_t latencyBits;
    uint32_t word;
    uint32_t nBytes = 0;
    const IVAS_PIDATA_REVERSE_PI_LATENCY *p = (const IVAS_PIDATA_REVERSE_PI_LATENCY *) piData;

    *nBytesWritten = 0;
    if ( piData->size != sizeof( IVAS_PIDATA_REVERSE_PI_LATENCY ) )
    {
        return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect size for PI_LATENCY data" );
    }
    if ( piData->piDataType != IVAS_PI_PI_LATENCY )
    {
        return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Incorrect PI ID for PI_LATENCY data" );
    }
    if ( maxDataBytes < 2 + 4 )
    {
        return IVAS_ERROR( IVAS_ERR_RTP_INSUFFICIENT_OUTPUT_SIZE, "Insufficient space to pack PI_LATENCY data" );
    }

    buffer[nBytes++] = ( p->piDataType & MASK_5BIT );
    buffer[nBytes++] = 4;

    typeBits = (uint32_t) ( p->type & MASK_5BIT );
    latencyBits = (uint32_t) ( p->latency & 0x07FFFFFF );
    word = ( typeBits << 27 ) | latencyBits;

    buffer[nBytes++] = (uint8_t) ( word >> 24 );
    buffer[nBytes++] = (uint8_t) ( word >> 16 );
    buffer[nBytes++] = (uint8_t) ( word >> 8 );
    buffer[nBytes++] = (uint8_t) ( word );
    *nBytesWritten = nBytes;

    return IVAS_ERR_OK;
}

static ivas_error unpackPiLatency( const uint8_t *buffer, uint32_t numDataBytes, IVAS_PIDATA_GENERIC *piData )
{
    uint32_t word;
    uint32_t lat;
    IVAS_PIDATA_REVERSE_PI_LATENCY *p = (IVAS_PIDATA_REVERSE_PI_LATENCY *) piData;

    if ( numDataBytes != 4 )
    {
        return IVAS_ERROR( IVAS_ERR_RTP_UNPACK_PI_DATA, "Incorrect size to unpack PI_LATENCY data" );
    }

    p->size = sizeof( IVAS_PIDATA_REVERSE_PI_LATENCY );
    p->piDataType = IVAS_PI_PI_LATENCY;

    word = ( (uint32_t) buffer[0] << 24 ) | ( (uint32_t) buffer[1] << 16 ) |
           ( (uint32_t) buffer[2] << 8 ) | (uint32_t) buffer[3];
    p->type = (IVAS_PI_TYPE) ( ( word >> 27 ) & MASK_5BIT );
    lat = word & 0x07FFFFFF;

    /* Sign-extend 27-bit value */
    if ( lat & ( 1u << 26 ) )
        p->latency = (int32_t) ( lat | ~0x07FFFFFF );
    else
        p->latency = (int32_t) lat;

    return IVAS_ERR_OK;
}
#endif
#ifdef ISM_PI_DATA
static ivas_error packISMGain( const IVAS_PIDATA_GENERIC *piData, uint8_t *buffer, uint32_t maxDataBytes, uint32_t *nBytesWritten )
{
    uint32_t nBytes = 0, n, idx;
@@ -1432,14 +1500,19 @@ static const PACK_PI_FN packPiDataFuntions[IVAS_PI_MAX_ID] = {
#endif
    packDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION        */
    packAudioFocusCommon,   /* AUDIO_FOCUS_REQUEST              */
#ifdef PI_LATENCY
    packPiLatency, /* PI_LATENCY                       */
#else
    packUnsupportedData,    /* PI_LATENCY                       */
#endif
#else
    packUnsupportedData,   /* PLAYBACK_DEVICE_ORIENTATION      */
    packUnsupportedData,   /* HEAD_ORIENTATION                 */
    packUnsupportedData,   /* LISTENER_POSITION                */
    packUnsupportedData,   /* DYNAMIC_AUDIO_SUPPRESSION        */
    packUnsupportedData,   /* AUDIO_FOCUS_DIRECTION            */
#endif
    packUnsupportedData,   /* PI_LATENCY                       */
#endif
#ifdef REVERSE_ISM_PI_DATA
    packReverseISMID,   /* R_ISM_ID                         */
    packReverseISMGain, /* R_ISM_GAIN                       */
@@ -1515,14 +1588,19 @@ static const UNPACK_PI_FN unpackPiDataFuntions[IVAS_PI_MAX_ID] = {
#endif
    unpackDynamicSuppression, /* DYNAMIC_AUDIO_SUPPRESSION        */
    unpackAudioFocusCommon,   /* AUDIO_FOCUS_REQUEST              */
#ifdef PI_LATENCY
    unpackPiLatency, /* PI_LATENCY                       */
#else
    unpackUnsupportedData,  /* PI_LATENCY                       */
#endif
#else
    unpackUnsupportedData, /* PLAYBACK_DEVICE_ORIENTATION      */
    unpackUnsupportedData, /* HEAD_ORIENTATION                 */
    unpackUnsupportedData, /* LISTENER_POSITION                */
    unpackUnsupportedData, /* DYNAMIC_AUDIO_SUPPRESSION        */
    unpackUnsupportedData, /* PI_LATENCY                       */
    unpackUnsupportedData, /* AUDIO_FOCUS_DIRECTION            */
#endif
    unpackUnsupportedData, /* PI_LATENCY                       */
#ifdef REVERSE_ISM_PI_DATA
    unpackReverseISMID,   /* R_ISM_ID                         */
    unpackReverseISMGain, /* R_ISM_GAIN                       */
+25 −2
Original line number Diff line number Diff line
@@ -447,6 +447,11 @@ class AUDIO_FOCUS:
    direction: Optional[ORIENTATION] = None
    level: Optional[AUDIO_FOCUS_LEVEL] = None

@dataclass
class PI_LATENCY:
    reverseType: PIDATAS
    latency: int


@dataclass
class PIDATA:
@@ -998,6 +1003,24 @@ def packAudioFocus(bitstrm: BitStream, data: any):
        bitstrm.append(f"uint:4={level}")
        bitstrm.append(f"uint:4=0")

def unpackPiLatency(bitstrm: ConstBitStream, piSize: int) -> PI_LATENCY:
    assert piSize == 4, "PI_LATENCY must be 4 bytes"
    word = bitstrm.read(32).uint
    typeBits = (word >> 27) & 0x1F
    reverseType = PiTypeNames[typeBits]
    raw = word & 0x07FFFFFF
    # Sign-extend 27-bit
    if raw & (1 << 26):
        raw = raw | ~0x07FFFFFF
    return PI_LATENCY(reverseType, int(raw))

def packPiLatency(bitstrm: BitStream, data: any) -> None:
    assert type(data) == PI_LATENCY, "PI_LATENCY pack expects PI_LATENCY data"
    idx = PiTypeNames.index(data.reverseType)
    latency = data.latency & 0x07FFFFFF
    word = (idx << 27) | latency
    bitstrm.append(f"uint:32={word}")

def unpackISMNum(bitstrm: ConstBitStream, piSize: int) -> ISM_NUM:
    assert piSize == 1, "Incorrect PI Data Size for ISM_NUM"
    numISM = bitstrm.read(2).uint + 1
@@ -1154,7 +1177,7 @@ PIDataUnpacker = [
    unpackPosition,  # LISTENER_POSITION
    unpackDAS,  # DYNAMIC_AUDIO_SUPPRESSION_REQUEST
    unpackAudioFocus,  # AUDIO_FOCUS_REQUEST
    unpackUnsupported,  # PI_LATENCY
    unpackPiLatency,    # PI_LATENCY
    unpackReverseISMID,  # R_ISM_ID
    unpackReverseISMGain,  # R_ISM_GAIN
    unpackOrientation,  # R_ISM_ORIENTATION
@@ -1189,7 +1212,7 @@ PIDataPacker = [
    packPosition,  # LISTENER_POSITION
    packDAS,  # DYNAMIC_AUDIO_SUPPRESSION_REQUEST
    packAudioFocus,  # AUDIO_FOCUS_DIRECTION
    packUnsupported,  # PI_LATENCY
    packPiLatency,    # PI_LATENCY
    packReverseISMID,  # R_ISM_ID
    packReverseISMGain,  # R_ISM_GAIN
    packOrientation,  # R_ISM_ORIENTATION
+19 −1
Original line number Diff line number Diff line
@@ -228,7 +228,16 @@ def generatePiData(startTs: int, endTs: int) -> dict:
    )
    someAuFocusLvl = lambda: AUDIO_FOCUS(level=AUDIO_FOCUS_LEVEL(random.randint(0, 15)))
    someAuFocusList = [someAuFocusDirLvl, someAuFocusDir, someAuFocusLvl]

    someLatency = lambda: PI_LATENCY(
        reverseType=random.choice([
            "PLAYBACK_DEVICE_ORIENTATION",
            "HEAD_ORIENTATION",
            "LISTENER_POSITION",
            "DYNAMIC_AUDIO_SUPPRESSION_REQUEST",
            "AUDIO_FOCUS_REQUEST"
        ]),
        latency=random.randint(- (1 << 26), (1 << 26) - 1)
    )
    someAcousticEnvAEID = lambda: ACOUSTIC_ENVIRONMENT(
        aeid=random.randint(0, 127)
    )
@@ -286,6 +295,7 @@ def generatePiData(startTs: int, endTs: int) -> dict:
        pidata["AUDIO_DESCRIPTION"] = [someDesc() for n in range(random.randint(1, 5))]
        pidata["DIEGETIC_TYPE"] = someDIG()
        pidata["ACOUSTIC_ENVIRONMENT"] = random.choice(someAcousticEnvList)()
        pidata["PI_LATENCY"] = someLatency()
        pidata["ISM_NUM"] = someNumISM()
        pidata["ISM_ID"] = someISMIds(pidata["ISM_NUM"].num)
        pidata["ISM_GAIN"] = someISMGains(pidata["ISM_NUM"].num)
@@ -395,6 +405,12 @@ def isEqualAudioFocus(ref: AUDIO_FOCUS, dut: AUDIO_FOCUS):
        ), "Audio Focus PI Data mismatch in direction z"
    assert ref.level == dut.level, "Audio Focus PI Data mismatch in level"

def isEqualPILatency(ref: PI_LATENCY, dut: PI_LATENCY):
    assert ref.reverseType == dut.reverseType, \
        f"PI_LATENCY type mismatch: {dut.reverseType} != {ref.reverseType}"
    assert ref.latency == dut.latency, \
        f"PI_LATENCY latency mismatch: {dut.latency} != {ref.latency}"

def isEqualISMNum(ref: ISM_NUM, dut: ISM_NUM):
    assert ref.num == dut.num, "ISM NUM PI Data mismatch"

@@ -725,6 +741,8 @@ def run_rtp_bitstream_tests(
                        isEqualAcousticEnv(ACOUSTIC_ENVIRONMENT(**decoded), data)
                    elif type(generatedPIData[ts][pitype]) == AUDIO_FOCUS:
                        isEqualAudioFocus(AUDIO_FOCUS(**decoded), data)
                    elif type(generatedPIData[ts][pitype]) == PI_LATENCY:
                        isEqualPILatency(PI_LATENCY(**decoded), data)
                    elif type(generatedPIData[ts][pitype]) == list:
                        if pitype == "AUDIO_DESCRIPTION":
                            for r, d in zip(generatedPIData[ts][pitype], decodedPiData[ts][pitype]):