Audio/video initial recording time synchronization

Change-Id: Iac58b63d474fe09c1d36ba6ecde91dafbb7fef9a
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 60f30f5..3c85eca 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -68,12 +68,16 @@
     bool mStreamableFile;
     off_t mEstimatedMoovBoxSize;
     uint32_t mInterleaveDurationUs;
+    int64_t mStartTimestampUs;
     Mutex mLock;
 
     List<Track *> mTracks;
 
     List<off_t> mBoxes;
 
+    void setStartTimestamp(int64_t timeUs);
+    int64_t getStartTimestamp();  // Not const
+
     void lock();
     void unlock();
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 044460c..788534d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -98,6 +98,7 @@
     bool mGotAllCodecSpecificData;
 
     bool mReachedEOS;
+    int64_t mStartTimestampUs;
 
     static void *ThreadWrapper(void *me);
     void threadEntry();
@@ -152,6 +153,7 @@
         return UNKNOWN_ERROR;
     }
 
+    mStartTimestampUs = 0;
     mStreamableFile = true;
     mWriteMoovBoxToMemory = false;
     mMoovBoxBuffer = NULL;
@@ -500,6 +502,21 @@
     return allDone;
 }
 
+void MPEG4Writer::setStartTimestamp(int64_t timeUs) {
+    LOGI("setStartTimestamp: %lld", timeUs);
+    Mutex::Autolock autoLock(mLock);
+    if (mStartTimestampUs != 0) {
+        return;  // Sorry, too late
+    }
+    mStartTimestampUs = timeUs;
+}
+
+int64_t MPEG4Writer::getStartTimestamp() {
+    LOGI("getStartTimestamp: %lld", mStartTimestampUs);
+    Mutex::Autolock autoLock(mLock);
+    return mStartTimestampUs;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
@@ -836,6 +853,10 @@
 
         int64_t timestampUs;
         CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        if (mSampleInfos.empty()) {
+            mOwner->setStartTimestamp(timestampUs);
+            mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp());
+        }
 
         if (timestampUs > mMaxTimeStampUs) {
             mMaxTimeStampUs = timestampUs;
@@ -1005,6 +1026,19 @@
         }
       mOwner->endBox();  // tkhd
 
+      if (mStartTimestampUs != 0) {
+        mOwner->beginBox("edts");
+          mOwner->writeInt32(0);             // version=0, flags=0
+          mOwner->beginBox("elst");
+            mOwner->writeInt32(0);           // version=0, flags=0
+            mOwner->writeInt32(1);           // a single entry
+            mOwner->writeInt32(mStartTimestampUs / 1000);  // edit duration
+            mOwner->writeInt32(0);           // edit media starting time
+            mOwner->writeInt32(1);           // x1 rate
+          mOwner->endBox();
+        mOwner->endBox();
+      }
+
       mOwner->beginBox("mdia");
 
         mOwner->beginBox("mdhd");