Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad69acb2 authored by Harish Mahendrakar's avatar Harish Mahendrakar Committed by Ray Essick
Browse files

OpusHeader: Add support for unified CSD

Added few macros and functions to handle unified CSD for opus
These functions are used to write/read codec delay and seek pre-roll data
to/from CSD buffer

Bug: 115576456
Test: vendor
Change-Id: Iace44d7dea860c9fcf27492fcd9666b99a4c1e73
parent 187dcc50
Loading
Loading
Loading
Loading
+85 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "SoftOpus"

#include <algorithm>
#include <cstring>
#include <stdint.h>

@@ -176,4 +176,88 @@ int WriteOpusHeader(const OpusHeader &header, int input_sample_rate,
    }
}

int WriteOpusHeaders(const OpusHeader &header, int inputSampleRate,
                     uint8_t* output, size_t outputSize, uint64_t codecDelay,
                     uint64_t seekPreRoll) {
    if (outputSize < AOPUS_UNIFIED_CSD_MINSIZE) {
        ALOGD("Buffer not large enough to hold unified OPUS CSD");
        return -1;
    }

    int headerLen = WriteOpusHeader(header, inputSampleRate, output,
        outputSize);
    if (headerLen < 0) {
        ALOGD("WriteOpusHeader failed");
        return -1;
    }
    if (headerLen >= (outputSize - 2 * AOPUS_TOTAL_CSD_SIZE)) {
        ALOGD("Buffer not large enough to hold codec delay and seek pre roll");
        return -1;
    }

    uint64_t length = AOPUS_LENGTH;

    /*
      Following is the CSD syntax for signalling codec delay and
      seek pre-roll which is to be appended after OpusHeader

      Marker (8 bytes) | Length (8 bytes) | Samples (8 bytes)

      Markers supported:
      AOPUSDLY - Signals Codec Delay
      AOPUSPRL - Signals seek pre roll

      Length should be 8.
    */

    // Add codec delay
    memcpy(output + headerLen, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE);
    headerLen += AOPUS_MARKER_SIZE;
    memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
    headerLen += AOPUS_LENGTH_SIZE;
    memcpy(output + headerLen, &codecDelay, AOPUS_CSD_SIZE);
    headerLen += AOPUS_CSD_SIZE;

    // Add skip pre roll
    memcpy(output + headerLen, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE);
    headerLen += AOPUS_MARKER_SIZE;
    memcpy(output + headerLen, &length, AOPUS_LENGTH_SIZE);
    headerLen += AOPUS_LENGTH_SIZE;
    memcpy(output + headerLen, &seekPreRoll, AOPUS_CSD_SIZE);
    headerLen += AOPUS_CSD_SIZE;

    return headerLen;
}

void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
                          void **opusHeadBuf, size_t *opusHeadSize,
                          void **codecDelayBuf, size_t *codecDelaySize,
                          void **seekPreRollBuf, size_t *seekPreRollSize) {
    *codecDelayBuf = NULL;
    *codecDelaySize = 0;
    *seekPreRollBuf = NULL;
    *seekPreRollSize = 0;
    *opusHeadBuf = (void *)data;
    *opusHeadSize = data_size;
    if (data_size >= AOPUS_UNIFIED_CSD_MINSIZE) {
        size_t i = 0;
        while (i < data_size - AOPUS_TOTAL_CSD_SIZE) {
            uint8_t *csdBuf = (uint8_t *)data + i;
            if (!memcmp(csdBuf, AOPUS_CSD_CODEC_DELAY_MARKER, AOPUS_MARKER_SIZE)) {
                *opusHeadSize = std::min(*opusHeadSize, i);
                *codecDelayBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
                *codecDelaySize = AOPUS_CSD_SIZE;
                i += AOPUS_TOTAL_CSD_SIZE;
            } else if (!memcmp(csdBuf, AOPUS_CSD_SEEK_PREROLL_MARKER, AOPUS_MARKER_SIZE)) {
                *opusHeadSize = std::min(*opusHeadSize, i);
                *seekPreRollBuf = csdBuf + AOPUS_MARKER_SIZE + AOPUS_LENGTH_SIZE;
                *seekPreRollSize = AOPUS_CSD_SIZE;
                i += AOPUS_TOTAL_CSD_SIZE;
            } else {
                i++;
            }
        }
    }
}

}  // namespace android
+25 −0
Original line number Diff line number Diff line
@@ -24,6 +24,24 @@

namespace android {

/* Constants used for delimiting Opus CSD */
#define AOPUS_CSD_CODEC_DELAY_MARKER "AOPUSDLY"
#define AOPUS_CSD_SEEK_PREROLL_MARKER "AOPUSPRL"
#define AOPUS_CSD_SIZE 8
#define AOPUS_LENGTH 8
#define AOPUS_MARKER_SIZE 8
#define AOPUS_LENGTH_SIZE 8
#define AOPUS_TOTAL_CSD_SIZE \
    ((AOPUS_MARKER_SIZE) + (AOPUS_LENGTH_SIZE) + (AOPUS_CSD_SIZE))
#define AOPUS_CSD0_MINSIZE 19
#define AOPUS_UNIFIED_CSD_MINSIZE \
    ((AOPUS_CSD0_MINSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))

/* CSD0 at max can be 22 bytes + max number of channels (255) */
#define AOPUS_CSD0_MAXSIZE 277
#define AOPUS_UNIFIED_CSD_MAXSIZE \
    ((AOPUS_CSD0_MAXSIZE) + 2 * (AOPUS_TOTAL_CSD_SIZE))

struct OpusHeader {
    int channels;
    int channel_mapping;
@@ -36,6 +54,13 @@ struct OpusHeader {

bool ParseOpusHeader(const uint8_t* data, size_t data_size, OpusHeader* header);
int WriteOpusHeader(const OpusHeader &header, int input_sample_rate, uint8_t* output, size_t output_size);
void GetOpusHeaderBuffers(const uint8_t *data, size_t data_size,
                          void **opusHeadBuf, size_t *opusHeadSize,
                          void **codecDelayBuf, size_t *codecDelaySize,
                          void **seekPreRollBuf, size_t *seekPreRollSize);
int WriteOpusHeaders(const OpusHeader &header, int inputSampleRate,
                     uint8_t* output, size_t outputSize, uint64_t codecDelay,
                     uint64_t seekPreRoll);
}  // namespace android

#endif  // OPUS_HEADER_H_