libstagefright: Add support for muxing Opus files to Ogg format with unified CSD
Now Ogg writer supports muxing opus files sent with either single
unified CSD or 3 CSDs that are returned by Ogg extractor.
Test: Tested using a local native application using AMediaMuxer API
Bug: 115576456
Change-Id: I335b078a4edf059aca6b3fd0f17b6bab3e006615
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index 7a60c65..5c13983 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -114,30 +114,17 @@
}
mSampleRate = sampleRate;
-
- OpusHeader header;
- header.channels = nChannels;
- header.num_streams = nChannels;
- header.num_coupled = 0;
- header.channel_mapping = ((nChannels > 8) ? 255 : (nChannels > 2));
- header.gain_db = 0;
- header.skip_samples = 0;
-
- // headers are 21-bytes + something driven by channel count
- // expect numbers in the low 30's here. WriteOpusHeader() will tell us
- // if things are bad.
- unsigned char header_data[100];
- ogg_packet op;
- ogg_page og;
-
- const int packet_size = WriteOpusHeader(header, mSampleRate, (uint8_t*)header_data,
- sizeof(header_data));
-
- if (packet_size < 0) {
- ALOGE("opus header writing failed");
+ uint32_t type;
+ const void *header_data;
+ size_t packet_size;
+ if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
+ ALOGE("opus header not found");
return UNKNOWN_ERROR;
}
- op.packet = header_data;
+
+ ogg_packet op;
+ ogg_page og;
+ op.packet = (unsigned char *)header_data;
op.bytes = packet_size;
op.b_o_s = 1;
op.e_o_s = 0;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 49e485a..2e7da01 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -37,6 +37,7 @@
#include <media/stagefright/foundation/ALookup.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ByteUtils.h>
+#include <media/stagefright/foundation/OpusHeader.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDefs.h>
#include <media/AudioSystem.h>
@@ -1745,12 +1746,34 @@
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_AUDIO_OPUS) {
- meta->setData(kKeyOpusHeader, 0, csd0->data(), csd0->size());
+ size_t opusHeadSize = csd0->size();
+ size_t codecDelayBufSize = 0;
+ size_t seekPreRollBufSize = 0;
+ void *opusHeadBuf = csd0->data();
+ void *codecDelayBuf = NULL;
+ void *seekPreRollBuf = NULL;
if (msg->findBuffer("csd-1", &csd1)) {
- meta->setData(kKeyOpusCodecDelay, 0, csd1->data(), csd1->size());
+ codecDelayBufSize = csd1->size();
+ codecDelayBuf = csd1->data();
}
if (msg->findBuffer("csd-2", &csd2)) {
- meta->setData(kKeyOpusSeekPreRoll, 0, csd2->data(), csd2->size());
+ seekPreRollBufSize = csd2->size();
+ seekPreRollBuf = csd2->data();
+ }
+ /* Extract codec delay and seek pre roll from csd-0,
+ * if csd-1 and csd-2 are not present */
+ if (!codecDelayBuf && !seekPreRollBuf) {
+ GetOpusHeaderBuffers(csd0->data(), csd0->size(), &opusHeadBuf,
+ &opusHeadSize, &codecDelayBuf,
+ &codecDelayBufSize, &seekPreRollBuf,
+ &seekPreRollBufSize);
+ }
+ meta->setData(kKeyOpusHeader, 0, opusHeadBuf, opusHeadSize);
+ if (codecDelayBuf) {
+ meta->setData(kKeyOpusCodecDelay, 0, codecDelayBuf, codecDelayBufSize);
+ }
+ if (seekPreRollBuf) {
+ meta->setData(kKeyOpusSeekPreRoll, 0, seekPreRollBuf, seekPreRollBufSize);
}
} else if (mime == MEDIA_MIMETYPE_AUDIO_VORBIS) {
meta->setData(kKeyVorbisInfo, 0, csd0->data(), csd0->size());