Merge "OggWriter: Support format without CSD for opus" into qt-dev
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index cb87b55..b738fef 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -52,6 +52,7 @@
 
 OggWriter::OggWriter(int fd)
       : mFd(dup(fd)),
+        mHaveAllCodecSpecificData(false),
         mInitCheck(mFd < 0 ? NO_INIT : OK) {
     // empty
 }
@@ -115,17 +116,26 @@
 
     mSampleRate = sampleRate;
     uint32_t type;
-    const void *header_data;
-    size_t packet_size;
+    const void *header_data = NULL;
+    size_t packet_size = 0;
+
     if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
-        ALOGE("opus header not found");
-        return UNKNOWN_ERROR;
+        ALOGV("opus header not found in format");
+    } else if (header_data && packet_size) {
+        writeOggHeaderPackets((unsigned char *)header_data, packet_size);
+    } else {
+        ALOGD("ignoring incomplete opus header data in format");
     }
 
+    mSource = source;
+    return OK;
+}
+
+status_t OggWriter::writeOggHeaderPackets(unsigned char *buf, size_t size) {
     ogg_packet op;
     ogg_page og;
-    op.packet = (unsigned char *)header_data;
-    op.bytes = packet_size;
+    op.packet = buf;
+    op.bytes = size;
     op.b_o_s = 1;
     op.e_o_s = 0;
     op.granulepos = 0;
@@ -169,8 +179,8 @@
         write(mFd, og.body, og.body_len);
     }
 
-    mSource = source;
     free(comments);
+    mHaveAllCodecSpecificData = true;
     return OK;
 }
 
@@ -301,12 +311,35 @@
              && isCodecSpecific)
             || IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
                          buffer->range_length())) {
-            ALOGV("Drop codec specific info buffer");
+            if (mHaveAllCodecSpecificData == false) {
+                size_t opusHeadSize = 0;
+                size_t codecDelayBufSize = 0;
+                size_t seekPreRollBufSize = 0;
+                void *opusHeadBuf = NULL;
+                void *codecDelayBuf = NULL;
+                void *seekPreRollBuf = NULL;
+                GetOpusHeaderBuffers((uint8_t*)buffer->data() + buffer->range_offset(),
+                                    buffer->range_length(), &opusHeadBuf,
+                                    &opusHeadSize, &codecDelayBuf,
+                                    &codecDelayBufSize, &seekPreRollBuf,
+                                    &seekPreRollBufSize);
+                writeOggHeaderPackets((unsigned char *)opusHeadBuf, opusHeadSize);
+            } else {
+                ALOGV("ignoring later copy of CSD contained in info buffer");
+            }
             buffer->release();
             buffer = nullptr;
             continue;
         }
 
+        if (mHaveAllCodecSpecificData == false) {
+            ALOGE("Did not get valid opus header before first sample data");
+            buffer->release();
+            buffer = nullptr;
+            err = ERROR_MALFORMED;
+            break;
+        }
+
         int64_t timestampUs;
         CHECK(buffer->meta_data().findInt64(kKeyTime, &timestampUs));
         if (timestampUs > mEstimatedDurationUs) {
diff --git a/media/libstagefright/include/media/stagefright/OggWriter.h b/media/libstagefright/include/media/stagefright/OggWriter.h
index e3837cd..1a0a1d2 100644
--- a/media/libstagefright/include/media/stagefright/OggWriter.h
+++ b/media/libstagefright/include/media/stagefright/OggWriter.h
@@ -43,6 +43,7 @@
 
 private:
     int mFd;
+    bool mHaveAllCodecSpecificData;
     status_t mInitCheck;
     sp<MediaSource> mSource;
     bool mStarted = false;
@@ -66,6 +67,8 @@
 
     OggWriter(const OggWriter&);
     OggWriter& operator=(const OggWriter&);
+
+    status_t writeOggHeaderPackets(unsigned char *buf, size_t size);
 };
 
 }  // namespace android