Merge "Fix warning: Potential leak of memory pointed to by 'device'"
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 91f9fc7..6ed9a43 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -604,7 +604,7 @@
                 *replySize < (sizeof(int32_t) * MEASUREMENT_COUNT)) {
             ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32
                     " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, *replySize,
-                    sizeof(int32_t) * MEASUREMENT_COUNT);
+                    uint32_t(sizeof(int32_t)) * MEASUREMENT_COUNT);
             android_errorWriteLog(0x534e4554, "30229821");
             return -EINVAL;
         }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index cdb0a7b..a748b46 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -884,7 +884,10 @@
         case OUTPUT_FORMAT_RTP_AVP:
         case OUTPUT_FORMAT_MPEG2TS:
         {
-            status = mWriter->start();
+            sp<MetaData> meta = new MetaData;
+            int64_t startTimeUs = systemTime() / 1000;
+            meta->setInt64(kKeyTime, startTimeUs);
+            status = mWriter->start(meta.get());
             break;
         }
 
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 931b280..b83b0a0 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -37,7 +37,7 @@
 struct MPEG2TSWriter::SourceInfo : public AHandler {
     explicit SourceInfo(const sp<IMediaSource> &source);
 
-    void start(const sp<AMessage> &notify);
+    void start(const sp<AMessage> &notify, const sp<MetaData> &params);
     void stop();
 
     unsigned streamType() const;
@@ -75,7 +75,7 @@
 
     sp<ABuffer> mAACCodecSpecificData;
 
-    sp<ABuffer> mAACBuffer;
+    sp<ABuffer> mBuffer;
 
     sp<ABuffer> mLastAccessUnit;
     bool mEOSReceived;
@@ -85,10 +85,8 @@
 
     void extractCodecSpecificData();
 
-    bool appendAACFrames(MediaBuffer *buffer);
-    bool flushAACFrames();
-
-    void postAVCFrame(MediaBuffer *buffer);
+    void appendAACFrames(MediaBuffer *buffer);
+    void appendAVCFrame(MediaBuffer *buffer);
 
     DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
 };
@@ -129,13 +127,14 @@
     return mContinuityCounter;
 }
 
-void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify) {
+void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify, const sp<MetaData> &params) {
     mLooper->registerHandler(this);
     mLooper->start();
-
     mNotify = notify;
 
-    (new AMessage(kWhatStart, this))->post();
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
+    msg->setObject("meta", params);
+    msg->post();
 }
 
 void MPEG2TSWriter::SourceInfo::stop() {
@@ -250,56 +249,51 @@
     notify->post();
 }
 
-void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
+void MPEG2TSWriter::SourceInfo::appendAVCFrame(MediaBuffer *buffer) {
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", kNotifyBuffer);
 
-    sp<ABuffer> copy =
-        new ABuffer(buffer->range_length());
-    memcpy(copy->data(),
+    if (mBuffer == NULL || buffer->range_length() > mBuffer->capacity()) {
+        mBuffer = new ABuffer(buffer->range_length());
+    }
+    mBuffer->setRange(0, 0);
+
+    memcpy(mBuffer->data(),
            (const uint8_t *)buffer->data()
             + buffer->range_offset(),
            buffer->range_length());
 
     int64_t timeUs;
     CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
-    copy->meta()->setInt64("timeUs", timeUs);
+    mBuffer->meta()->setInt64("timeUs", timeUs);
 
     int32_t isSync;
     if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
             && isSync != 0) {
-        copy->meta()->setInt32("isSync", true);
+        mBuffer->meta()->setInt32("isSync", true);
     }
 
-    notify->setBuffer("buffer", copy);
+    mBuffer->setRange(0, buffer->range_length());
+
+    notify->setBuffer("buffer", mBuffer);
     notify->post();
 }
 
-bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
-    bool accessUnitPosted = false;
+void MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kNotifyBuffer);
 
-    if (mAACBuffer != NULL
-            && mAACBuffer->size() + 7 + buffer->range_length()
-                    > mAACBuffer->capacity()) {
-        accessUnitPosted = flushAACFrames();
+    if (mBuffer == NULL || 7 + buffer->range_length() > mBuffer->capacity()) {
+        mBuffer = new ABuffer(7 + buffer->range_length());
     }
 
-    if (mAACBuffer == NULL) {
-        size_t alloc = 4096;
-        if (buffer->range_length() + 7 > alloc) {
-            alloc = 7 + buffer->range_length();
-        }
+    int64_t timeUs;
+    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
 
-        mAACBuffer = new ABuffer(alloc);
+    mBuffer->meta()->setInt64("timeUs", timeUs);
+    mBuffer->meta()->setInt32("isSync", true);
 
-        int64_t timeUs;
-        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
-        mAACBuffer->meta()->setInt64("timeUs", timeUs);
-        mAACBuffer->meta()->setInt32("isSync", true);
-
-        mAACBuffer->setRange(0, 0);
-    }
+    mBuffer->setRange(0, 0);
 
     const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
 
@@ -312,7 +306,7 @@
     unsigned channel_configuration =
         (codec_specific_data[1] >> 3) & 0x0f;
 
-    uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
+    uint8_t *ptr = mBuffer->data() + mBuffer->size();
 
     const uint32_t aac_frame_length = buffer->range_length() + 7;
 
@@ -340,24 +334,10 @@
 
     ptr += buffer->range_length();
 
-    mAACBuffer->setRange(0, ptr - mAACBuffer->data());
+    mBuffer->setRange(0, ptr - mBuffer->data());
 
-    return accessUnitPosted;
-}
-
-bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
-    if (mAACBuffer == NULL) {
-        return false;
-    }
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kNotifyBuffer);
-    notify->setBuffer("buffer", mAACBuffer);
+    notify->setBuffer("buffer", mBuffer);
     notify->post();
-
-    mAACBuffer.clear();
-
-    return true;
 }
 
 void MPEG2TSWriter::SourceInfo::readMore() {
@@ -368,7 +348,10 @@
     switch (msg->what()) {
         case kWhatStart:
         {
-            status_t err = mSource->start();
+            sp<RefBase> obj;
+            CHECK(msg->findObject("meta", &obj));
+            MetaData *params = static_cast<MetaData *>(obj.get());
+            status_t err = mSource->start(params);
             if (err != OK) {
                 sp<AMessage> notify = mNotify->dup();
                 notify->setInt32("what", kNotifyStartFailed);
@@ -376,6 +359,7 @@
                 break;
             }
 
+            // Extract CSD from config format.
             extractCodecSpecificData();
 
             readMore();
@@ -388,10 +372,6 @@
             status_t err = mSource->read(&buffer);
 
             if (err != OK && err != INFO_FORMAT_CHANGED) {
-                if (mStreamType == 0x0f) {
-                    flushAACFrames();
-                }
-
                 sp<AMessage> notify = mNotify->dup();
                 notify->setInt32("what", kNotifyReachedEOS);
                 notify->setInt32("status", err);
@@ -401,23 +381,20 @@
 
             if (err == OK) {
                 if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
-                    // The first buffer contains codec specific data.
-
+                    // The first audio buffer must contain CSD if not received yet.
                     CHECK_GE(buffer->range_length(), 2u);
-
                     mAACCodecSpecificData = new ABuffer(buffer->range_length());
 
                     memcpy(mAACCodecSpecificData->data(),
                            (const uint8_t *)buffer->data()
                             + buffer->range_offset(),
                            buffer->range_length());
+                    readMore();
                 } else if (buffer->range_length() > 0) {
                     if (mStreamType == 0x0f) {
-                        if (!appendAACFrames(buffer)) {
-                            msg->post();
-                        }
+                        appendAACFrames(buffer);
                     } else {
-                        postAVCFrame(buffer);
+                        appendAVCFrame(buffer);
                     }
                 } else {
                     readMore();
@@ -452,7 +429,6 @@
 
     int64_t timeUs;
     CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
-
     return timeUs;
 }
 
@@ -542,7 +518,7 @@
     return OK;
 }
 
-status_t MPEG2TSWriter::start(MetaData * /* param */) {
+status_t MPEG2TSWriter::start(MetaData *param ) {
     CHECK(!mStarted);
 
     mStarted = true;
@@ -556,7 +532,7 @@
 
         notify->setInt32("source-index", i);
 
-        mSources.editItemAt(i)->start(notify);
+        mSources.editItemAt(i)->start(notify, param);
     }
 
     return OK;
@@ -594,13 +570,13 @@
         {
             int32_t sourceIndex;
             CHECK(msg->findInt32("source-index", &sourceIndex));
+            sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
 
             int32_t what;
             CHECK(msg->findInt32("what", &what));
 
             if (what == SourceInfo::kNotifyReachedEOS
                     || what == SourceInfo::kNotifyStartFailed) {
-                sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
                 source->setEOSReceived();
 
                 sp<ABuffer> buffer = source->lastAccessUnit();
@@ -615,6 +591,7 @@
             } else if (what == SourceInfo::kNotifyBuffer) {
                 sp<ABuffer> buffer;
                 CHECK(msg->findBuffer("buffer", &buffer));
+                CHECK(source->lastAccessUnit() == NULL);
 
                 int32_t oob;
                 if (msg->findInt32("oob", &oob) && oob) {
@@ -635,15 +612,10 @@
                 // Rinse, repeat.
                 // If we don't have data on any track we don't write
                 // anything just yet.
-
-                sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
-
-                CHECK(source->lastAccessUnit() == NULL);
                 source->setLastAccessUnit(buffer);
 
                 ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
-                     sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
-
+                    sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
                 int64_t minTimeUs = -1;
                 size_t minIndex = 0;
 
@@ -665,15 +637,14 @@
                 }
 
                 if (minTimeUs < 0) {
-                    ALOGV("not a all tracks have valid data.");
+                    ALOGV("not all tracks have valid data.");
                     break;
                 }
 
                 ALOGV("writing access unit at time %.2f secs (index %zu)",
-                     minTimeUs / 1E6, minIndex);
+                    minTimeUs / 1E6, minIndex);
 
                 source = mSources.editItemAt(minIndex);
-
                 buffer = source->lastAccessUnit();
                 source->setLastAccessUnit(NULL);
 
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 030c505..137a924 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -906,6 +906,7 @@
                 }
                 mbuf->meta_data()->setInt64(kKeyTime, timeUs);
             } else {
+                mbuf->meta_data()->setInt64(kKeyTime, 0ll);
                 mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
             }
             if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index b863d67..844479e 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -701,6 +701,10 @@
         }
 
         mPayloadStarted = true;
+        // There should be at most 2 elements in |mPesStartOffsets|.
+        while (mPesStartOffsets.size() >= 2) {
+            mPesStartOffsets.erase(mPesStartOffsets.begin());
+        }
         mPesStartOffsets.push_back(offset);
     }
 
@@ -1104,15 +1108,20 @@
             mSource->queueAccessUnit(accessUnit);
         }
 
-        if ((event != NULL) && !found && mQueue->getFormat() != NULL) {
+        // Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
+        off64_t pesStartOffset = -1;
+        if (!mPesStartOffsets.empty()) {
+            pesStartOffset = *mPesStartOffsets.begin();
+            mPesStartOffsets.erase(mPesStartOffsets.begin());
+        }
+
+        if (pesStartOffset >= 0 && (event != NULL) && !found && mQueue->getFormat() != NULL) {
             int32_t sync = 0;
             if (accessUnit->meta()->findInt32("isSync", &sync) && sync) {
                 int64_t timeUs;
                 if (accessUnit->meta()->findInt64("timeUs", &timeUs)) {
                     found = true;
-                    off64_t pesStartOffset = *mPesStartOffsets.begin();
                     event->init(pesStartOffset, mSource, timeUs);
-                    mPesStartOffsets.erase(mPesStartOffsets.begin());
                 }
             }
         }
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index bd89a51..7301193 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -220,7 +220,9 @@
         mTransactionID(0),
         mReceivedResponse(false),
         mProcessingEvent(false),
-        mCurrentEventHandle(0)
+        mCurrentEventHandle(0),
+        mLastSendObjectInfoTransactionID(0),
+        mLastSendObjectInfoObjectHandle(0)
 {
     mRequestIn1 = usb_request_new(device, ep_in);
     mRequestIn2 = usb_request_new(device, ep_in);
@@ -490,6 +492,8 @@
    if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
         MtpResponseCode ret = readResponse();
         if (ret == MTP_RESPONSE_OK) {
+            mLastSendObjectInfoTransactionID = mRequest.getTransactionID();
+            mLastSendObjectInfoObjectHandle = mResponse.getParameter(3);
             info->mStorageID = mResponse.getParameter(1);
             info->mParent = mResponse.getParameter(2);
             info->mHandle = mResponse.getParameter(3);
@@ -502,9 +506,14 @@
 bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
     Mutex::Autolock autoLock(mMutex);
 
+    if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
+            mLastSendObjectInfoObjectHandle != handle) {
+        ALOGE("A sendObject request must follow the sendObjectInfo request.");
+        return false;
+    }
+
     int remaining = size;
     mRequest.reset();
-    mRequest.setParameter(1, handle);
     bool error = false;
     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
         // send data header
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index c034c13..88f245f 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -62,6 +62,10 @@
     bool                    mProcessingEvent;
     int                     mCurrentEventHandle;
 
+    // to check if a sendObject request follows the last sendObjectInfo request.
+    MtpTransactionID        mLastSendObjectInfoTransactionID;
+    MtpObjectHandle         mLastSendObjectInfoObjectHandle;
+
     // to ensure only one MTP transaction at a time
     Mutex                   mMutex;
     Mutex                   mEventMutex;