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());