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
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/libstagefright/foundation/OpusHeader.cpp
index d2c8e29..9faede1 100644
--- a/media/libstagefright/foundation/OpusHeader.cpp
+++ b/media/libstagefright/foundation/OpusHeader.cpp
@@ -16,7 +16,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "SoftOpus"
-
+#include <algorithm>
#include <cstring>
#include <stdint.h>
@@ -176,4 +176,88 @@
}
}
+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
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
index f9f79cd..9bffccb 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
@@ -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 @@
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_