Merge "Fix the h.263 assembler to properly subset a buffer's range if it already has a range applied." into gingerbread
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index f1d45d2..2597e9e 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -60,7 +60,8 @@
     int64_t mStartTimeUs;
     int16_t mMaxAmplitude;
     int64_t mPrevSampleTimeUs;
-    int64_t mNumLostFrames;
+    int64_t mTotalLostFrames;
+    int64_t mPrevLostBytes;
 
     MediaBufferGroup *mGroup;
 
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 4eb63e8..947ff34 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -23,6 +23,7 @@
 #include <camera/ICamera.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
+#include <unistd.h>
 
 namespace android {
 
@@ -373,6 +374,7 @@
             int64_t offset = data.readInt64();
             int64_t length = data.readInt64();
             reply->writeInt32(setOutputFile(fd, offset, length));
+            ::close(fd);
             return NO_ERROR;
         } break;
         case SET_VIDEO_SIZE: {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index f6f89c7..8481d493 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -55,11 +55,6 @@
 StagefrightRecorder::~StagefrightRecorder() {
     LOGV("Destructor");
     stop();
-
-    if (mOutputFd >= 0) {
-        ::close(mOutputFd);
-        mOutputFd = -1;
-    }
 }
 
 status_t StagefrightRecorder::init() {
@@ -1084,6 +1079,11 @@
         mFlags = 0;
     }
 
+    if (mOutputFd >= 0) {
+        ::close(mOutputFd);
+        mOutputFd = -1;
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 99978e8..c8dfede 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -35,7 +35,8 @@
     : mStarted(false),
       mCollectStats(false),
       mPrevSampleTimeUs(0),
-      mNumLostFrames(0),
+      mTotalLostFrames(0),
+      mPrevLostBytes(0),
       mGroup(NULL) {
 
     LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
@@ -108,7 +109,8 @@
     mStarted = false;
 
     if (mCollectStats) {
-        LOGI("Total lost audio frames: %lld", mNumLostFrames);
+        LOGI("Total lost audio frames: %lld",
+            mTotalLostFrames + (mPrevLostBytes >> 1));
     }
 
     return OK;
@@ -186,10 +188,11 @@
         // Insert null frames when lost frames are detected.
         int64_t timestampUs = mPrevSampleTimeUs;
         uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
+        numLostBytes += mPrevLostBytes;
 #if 0
         // Simulate lost frames
-        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * kMaxBufferSize;
-        numLostBytes &= 0xFFFFFFFE; // Alignment request
+        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
+        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
 
         // Reduce the chance to lose
         if (rand() * 1.0 / RAND_MAX >= 0.05) {
@@ -197,13 +200,18 @@
         }
 #endif
         if (numLostBytes > 0) {
-            // Not expect too many lost frames!
-            CHECK(numLostBytes <= kMaxBufferSize);
+            if (numLostBytes > kMaxBufferSize) {
+                mPrevLostBytes = numLostBytes - kMaxBufferSize;
+                numLostBytes = kMaxBufferSize;
+            }
 
-            timestampUs += (1000000LL * numLostBytes >> 1) / sampleRate;
+            CHECK_EQ(numLostBytes & 1, 0);
+            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
+                    (sampleRate >> 1)) / sampleRate;
+
             CHECK(timestampUs > mPrevSampleTimeUs);
             if (mCollectStats) {
-                mNumLostFrames += (numLostBytes >> 1);
+                mTotalLostFrames += (numLostBytes >> 1);
             }
             if ((err = skipFrame(timestampUs, options)) == -1) {
                 buffer->release();
@@ -240,7 +248,7 @@
 
         buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
         CHECK(timestampUs > mPrevSampleTimeUs);
-        if (mNumLostFrames == 0) {
+        if (mTotalLostFrames == 0) {
             CHECK_EQ(mPrevSampleTimeUs,
                 mStartTimeUs + (1000000LL * numFramesRecorded) / sampleRate);
         }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index c860c5c..1460f37 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1956,11 +1956,11 @@
                   mOwner->writeInt16(0x18);        // depth
                   mOwner->writeInt16(-1);          // predefined
 
-                  CHECK(mCodecSpecificData);
-                  CHECK(mCodecSpecificDataSize > 0);
                   CHECK(23 + mCodecSpecificDataSize < 128);
 
                   if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+                      CHECK(mCodecSpecificData);
+                      CHECK(mCodecSpecificDataSize > 0);
                       mOwner->beginBox("esds");
 
                         mOwner->writeInt32(0);           // version=0, flags=0
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index 6e74279..0d89e02 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -407,6 +407,22 @@
         CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
         outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
 
+        // When the timestamp of the current sample is the same as
+        // that of the previous sample, the encoding of the sample
+        // is bypassed, and the output length is set to 0.
+        if (mNumInputFrames >= 1 && mPrevTimestampUs == timeUs) {
+            // Frame arrives too late
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+            outputBuffer->set_range(0, 0);
+            *out = outputBuffer;
+            return OK;
+        }
+
+        // Don't accept out-of-order samples
+        CHECK(mPrevTimestampUs < timeUs);
+        mPrevTimestampUs = timeUs;
+
         AVCFrameIO videoInput;
         memset(&videoInput, 0, sizeof(videoInput));
         videoInput.height = ((mVideoHeight  + 15) >> 4) << 4;
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
index 1bef0e9..5ea5859 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -306,8 +306,13 @@
 
     int64_t timeUs;
     CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-    if (mNextModTimeUs > timeUs) {
-        LOGV("mNextModTimeUs %lld > timeUs %lld", mNextModTimeUs, timeUs);
+
+    // When the timestamp of the current sample is the same as that
+    // of the previous sample, encoding of the current sample is
+    // bypassed, and the output length of the sample is set to 0
+    if (mNumInputFrames >= 1 &&
+        (mNextModTimeUs > timeUs || mPrevTimestampUs == timeUs)) {
+        // Frame arrives too late
         outputBuffer->set_range(0, 0);
         *out = outputBuffer;
         mInputBuffer->release();
@@ -315,6 +320,10 @@
         return OK;
     }
 
+    // Don't accept out-of-order samples
+    CHECK(mPrevTimestampUs < timeUs);
+    mPrevTimestampUs = timeUs;
+
     // Color convert to OMX_COLOR_FormatYUV420Planar if necessary
     outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
     uint8_t *inPtr = (uint8_t *) mInputBuffer->data();
diff --git a/media/libstagefright/include/AVCEncoder.h b/media/libstagefright/include/AVCEncoder.h
index 4fe2e30..83e1f97 100644
--- a/media/libstagefright/include/AVCEncoder.h
+++ b/media/libstagefright/include/AVCEncoder.h
@@ -64,6 +64,7 @@
     int32_t  mVideoBitRate;
     int32_t  mVideoColorFormat;
     int64_t  mNumInputFrames;
+    int64_t  mPrevTimestampUs;
     status_t mInitCheck;
     bool     mStarted;
     bool     mSpsPpsHeaderReceived;
diff --git a/media/libstagefright/include/M4vH263Encoder.h b/media/libstagefright/include/M4vH263Encoder.h
index dd146f4..dbe9fd0 100644
--- a/media/libstagefright/include/M4vH263Encoder.h
+++ b/media/libstagefright/include/M4vH263Encoder.h
@@ -59,6 +59,7 @@
     int32_t  mVideoColorFormat;
     int64_t  mNumInputFrames;
     int64_t  mNextModTimeUs;
+    int64_t  mPrevTimestampUs;
     status_t mInitCheck;
     bool     mStarted;