am 9bc4dc11: am 53d4e0d5: Allows the authoring engine to skip frame.

Merge commit '9bc4dc114fce58606a81d65d4cb31348cc7c1bae'

* commit '9bc4dc114fce58606a81d65d4cb31348cc7c1bae':
  Allows the authoring engine to skip frame.
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index a31395e..dafc621 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -78,18 +78,31 @@
         void clearSeekTo();
         bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
 
+        // Option allows encoder to skip some frames until the specified
+        // time stamp.
+        // To prevent from being abused, when the skipFrame timestamp is
+        // found to be more than 1 second later than the current timestamp,
+        // an error will be returned from read().
+        void clearSkipFrame();
+        bool getSkipFrame(int64_t *timeUs) const;
+        void setSkipFrame(int64_t timeUs);
+
         void setLateBy(int64_t lateness_us);
         int64_t getLateBy() const;
 
     private:
         enum Options {
+            // Bit map
             kSeekTo_Option      = 1,
+            kSkipFrame_Option   = 2,
         };
 
         uint32_t mOptions;
         int64_t mSeekTimeUs;
         SeekMode mSeekMode;
         int64_t mLatenessUs;
+
+        int64_t mSkipFrameUntilTimeUs;
     };
 
     // Causes this source to suspend pulling data from its upstream source
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 79e7a2f..6c6949b 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -143,6 +143,7 @@
     int64_t mSeekTimeUs;
     ReadOptions::SeekMode mSeekMode;
     int64_t mTargetTimeUs;
+    int64_t mSkipTimeUs;
 
     MediaBuffer *mLeftOverBuffer;
 
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 6031797..50c0edc 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -137,53 +137,76 @@
     MediaBuffer *buffer;
     CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
 
-    uint32_t numFramesRecorded;
-    mRecord->getPosition(&numFramesRecorded);
-    int64_t latency = mRecord->latency() * 1000;
+    while (mStarted) {
+        uint32_t numFramesRecorded;
+        mRecord->getPosition(&numFramesRecorded);
+        int64_t latency = mRecord->latency() * 1000;
 
-    int64_t readTime = systemTime() / 1000;
-    if (numFramesRecorded == 0) {
-        // Initial delay
-        if (mStartTimeUs > 0) {
-            mStartTimeUs = readTime - mStartTimeUs;
+        int64_t readTime = systemTime() / 1000;
+
+        if (numFramesRecorded == 0) {
+            // Initial delay
+            if (mStartTimeUs > 0) {
+                mStartTimeUs = readTime - mStartTimeUs;
+            } else {
+                mStartTimeUs += latency;
+            }
+        }
+
+        ssize_t n = 0;
+        if (mCollectStats) {
+            n = mRecord->read(buffer->data(), buffer->size());
+            int64_t endTime = systemTime() / 1000;
+            mTotalReadTimeUs += (endTime - readTime);
+            if (n >= 0) {
+                mTotalReadBytes += n;
+            }
         } else {
-            mStartTimeUs += latency;
+            n = mRecord->read(buffer->data(), buffer->size());
         }
-    }
 
-    ssize_t n = 0;
-    if (mCollectStats) {
-        n = mRecord->read(buffer->data(), buffer->size());
-        int64_t endTime = systemTime() / 1000;
-        mTotalReadTimeUs += (endTime - readTime);
-        if (n >= 0) {
-            mTotalReadBytes += n;
+        if (n < 0) {
+            buffer->release();
+            buffer = NULL;
+
+            return (status_t)n;
         }
-    } else {
-        n = mRecord->read(buffer->data(), buffer->size());
+
+        uint32_t sampleRate = mRecord->getSampleRate();
+        int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate +
+                                 mStartTimeUs;
+        int64_t skipFrameUs;
+        if (!options || !options->getSkipFrame(&skipFrameUs)) {
+            skipFrameUs = timestampUs;  // Don't skip frame
+        }
+
+        if (skipFrameUs > timestampUs) {
+            // Safe guard against the abuse of the kSkipFrame_Option.
+            if (skipFrameUs - timestampUs >= 1E6) {
+                LOGE("Frame skipping requested is way too long: %lld us",
+                    skipFrameUs - timestampUs);
+                buffer->release();
+                return UNKNOWN_ERROR;
+            }
+            LOGV("skipFrame: %lld us > timestamp: %lld us, samples %d",
+                skipFrameUs, timestampUs, numFramesRecorded);
+            continue;
+        }
+
+        if (mTrackMaxAmplitude) {
+            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
+        }
+
+        buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
+                mStartTimeUs, sampleRate, timestampUs);
+
+        buffer->set_range(0, n);
+
+        *out = buffer;
+        return OK;
     }
 
-    if (n < 0) {
-        buffer->release();
-        buffer = NULL;
-
-        return (status_t)n;
-    }
-
-    if (mTrackMaxAmplitude) {
-        trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
-    }
-
-    uint32_t sampleRate = mRecord->getSampleRate();
-    int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate + mStartTimeUs;
-    buffer->meta_data()->setInt64(kKeyTime, timestampUs);
-    LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
-            mStartTimeUs, sampleRate, timestampUs);
-
-    buffer->set_range(0, n);
-
-    *out = buffer;
-
     return OK;
 }
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index f4d269f..5e7dd5c 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -292,23 +292,44 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        while (mStarted && mFramesReceived.empty()) {
-            mFrameAvailableCondition.wait(mLock);
-        }
-        if (!mStarted) {
-            return OK;
-        }
-        frame = *mFramesReceived.begin();
-        mFramesReceived.erase(mFramesReceived.begin());
+        while (mStarted) {
+            while(mFramesReceived.empty()) {
+                mFrameAvailableCondition.wait(mLock);
+            }
 
-        frameTime = *mFrameTimes.begin();
-        mFrameTimes.erase(mFrameTimes.begin());
+            if (!mStarted) {
+                return OK;
+            }
 
-        mFramesBeingEncoded.push_back(frame);
-        *buffer = new MediaBuffer(frame->pointer(), frame->size());
-        (*buffer)->setObserver(this);
-        (*buffer)->add_ref();
-        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+            frame = *mFramesReceived.begin();
+            mFramesReceived.erase(mFramesReceived.begin());
+
+            frameTime = *mFrameTimes.begin();
+            mFrameTimes.erase(mFrameTimes.begin());
+            int64_t skipTimeUs;
+            if (!options || !options->getSkipFrame(&skipTimeUs)) {
+                skipTimeUs = frameTime;
+            }
+            if (skipTimeUs > frameTime) {
+                LOGV("skipTimeUs: %lld us > frameTime: %lld us",
+                    skipTimeUs, frameTime);
+                releaseOneRecordingFrame(frame);
+                ++mNumFramesDropped;
+                // Safeguard against the abuse of the kSkipFrame_Option.
+                if (skipTimeUs - frameTime >= 1E6) {
+                    LOGE("Frame skipping requested is way too long: %lld us",
+                        skipTimeUs - frameTime);
+                    return UNKNOWN_ERROR;
+                }
+            } else {
+                mFramesBeingEncoded.push_back(frame);
+                *buffer = new MediaBuffer(frame->pointer(), frame->size());
+                (*buffer)->setObserver(this);
+                (*buffer)->add_ref();
+                (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+                return OK;
+            }
+        }
     }
     return OK;
 }
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index fd0e79c3..b4ef338 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -32,6 +32,7 @@
     mOptions = 0;
     mSeekTimeUs = 0;
     mLatenessUs = 0;
+    mSkipFrameUntilTimeUs = 0;
 }
 
 void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
@@ -53,6 +54,21 @@
     return (mOptions & kSeekTo_Option) != 0;
 }
 
+void MediaSource::ReadOptions::clearSkipFrame() {
+    mOptions &= ~kSkipFrame_Option;
+    mSkipFrameUntilTimeUs = 0;
+}
+
+void MediaSource::ReadOptions::setSkipFrame(int64_t timeUs) {
+    mOptions |= kSkipFrame_Option;
+    mSkipFrameUntilTimeUs = timeUs;
+}
+
+bool MediaSource::ReadOptions::getSkipFrame(int64_t *timeUs) const {
+    *timeUs = mSkipFrameUntilTimeUs;
+    return (mOptions & kSkipFrame_Option) != 0;
+}
+
 void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
     mLatenessUs = lateness_us;
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1b63083..3fba2d9 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1274,6 +1274,7 @@
       mSeekTimeUs(-1),
       mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
       mTargetTimeUs(-1),
+      mSkipTimeUs(-1),
       mLeftOverBuffer(NULL),
       mPaused(false) {
     mPortStatus[kPortIndexInput] = ENABLED;
@@ -2200,13 +2201,15 @@
     int32_t n = 0;
     for (;;) {
         MediaBuffer *srcBuffer;
+        MediaSource::ReadOptions options;
+        if (mSkipTimeUs >= 0) {
+            options.setSkipFrame(mSkipTimeUs);
+        }
         if (mSeekTimeUs >= 0) {
             if (mLeftOverBuffer) {
                 mLeftOverBuffer->release();
                 mLeftOverBuffer = NULL;
             }
-
-            MediaSource::ReadOptions options;
             options.setSeekTo(mSeekTimeUs, mSeekMode);
 
             mSeekTimeUs = -1;
@@ -2231,7 +2234,7 @@
 
             err = OK;
         } else {
-            err = mSource->read(&srcBuffer);
+            err = mSource->read(&srcBuffer, &options);
         }
 
         if (err != OK) {
@@ -2830,6 +2833,12 @@
     if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
         seeking = true;
     }
+    int64_t skipTimeUs;
+    if (options && options->getSkipFrame(&skipTimeUs)) {
+        mSkipTimeUs = skipTimeUs;
+    } else {
+        mSkipTimeUs = -1;
+    }
 
     if (mInitialBufferSubmit) {
         mInitialBufferSubmit = false;
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index e8235c2..052c354 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -224,6 +224,7 @@
         if (mInputBuffer == NULL) {
             if (mSource->read(&mInputBuffer, options) != OK) {
                 if (mNumInputSamples == 0) {
+                    buffer->release();
                     return ERROR_END_OF_STREAM;
                 }
                 memset(&mInputFrame[mNumInputSamples],