Propagate duration from input to output only if available, support multiple full frames of audio per input buffer in AMR/AAC decoders.
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fc3c05b..9c9787f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -293,17 +293,19 @@
     CHECK(success);
 
 #if BUILD_WITH_FULL_STAGEFRIGHT
-    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
-        return new AACDecoder(source);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
-        return new AMRNBDecoder(source);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
-        return new AMRWBDecoder(source);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
-        return new MP3Decoder(source);
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
-                && (flags & kPreferSoftwareCodecs)) {
-        return new AVCDecoder(source);
+    if (!createEncoder) {
+        if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+            return new AACDecoder(source);
+        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+            return new AMRNBDecoder(source);
+        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+            return new AMRWBDecoder(source);
+        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+            return new MP3Decoder(source);
+        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
+                    && (flags & kPreferSoftwareCodecs)) {
+            return new AVCDecoder(source);
+        }
     }
 #endif
 
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index 77bbe89..92059c5 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -128,16 +128,18 @@
 
     int32_t numChannels;
     int32_t sampleRate;
-    int64_t durationUs;
     CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
     CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-    CHECK(srcFormat->findInt64(kKeyDuration, &durationUs));
 
     sp<MetaData> meta = new MetaData;
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeyChannelCount, numChannels);
     meta->setInt32(kKeySampleRate, sampleRate);
-    meta->setInt64(kKeyDuration, durationUs);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        meta->setInt64(kKeyDuration, durationUs);
+    }
 
     return meta;
 }
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index 856e29c..fbb6598 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -87,7 +87,6 @@
 
     int32_t numChannels;
     int32_t sampleRate;
-    int64_t durationUs;
 
     CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
     CHECK_EQ(numChannels, 1);
@@ -95,13 +94,15 @@
     CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
     CHECK_EQ(sampleRate, kSampleRate);
 
-    CHECK(srcFormat->findInt64(kKeyDuration, &durationUs));
-
     sp<MetaData> meta = new MetaData;
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeyChannelCount, numChannels);
     meta->setInt32(kKeySampleRate, sampleRate);
-    meta->setInt64(kKeyDuration, durationUs);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        meta->setInt64(kKeyDuration, durationUs);
+    }
 
     return meta;
 }
@@ -160,10 +161,16 @@
 
     buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
 
-    CHECK_EQ(numBytesRead, mInputBuffer->range_length());
+    CHECK(numBytesRead <= mInputBuffer->range_length());
 
-    mInputBuffer->release();
-    mInputBuffer = NULL;
+    mInputBuffer->set_range(
+            mInputBuffer->range_offset() + numBytesRead,
+            mInputBuffer->range_length() - numBytesRead);
+
+    if (mInputBuffer->range_length() == 0) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
 
     buffer->meta_data()->setInt64(
             kKeyTime,
diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
index 2f45514..c9d38c0 100644
--- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
+++ b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
@@ -93,7 +93,6 @@
 
     int32_t numChannels;
     int32_t sampleRate;
-    int64_t durationUs;
 
     CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
     CHECK_EQ(numChannels, 1);
@@ -101,13 +100,15 @@
     CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
     CHECK_EQ(sampleRate, kSampleRate);
 
-    CHECK(srcFormat->findInt64(kKeyDuration, &durationUs));
-
     sp<MetaData> meta = new MetaData;
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeyChannelCount, numChannels);
     meta->setInt32(kKeySampleRate, sampleRate);
-    meta->setInt64(kKeyDuration, durationUs);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        meta->setInt64(kKeyDuration, durationUs);
+    }
 
     return meta;
 }
@@ -170,7 +171,7 @@
 
     int16 mode = ((inputPtr[0] >> 3) & 0x0f);
     size_t frameSize = getFrameSize(mode);
-    CHECK_EQ(mInputBuffer->range_length(), frameSize);
+    CHECK(mInputBuffer->range_length() >= frameSize);
 
     int16 frameType;
     RX_State rx_state;
@@ -197,8 +198,14 @@
 
     buffer->set_range(0, numSamplesOutput * sizeof(int16_t));
 
-    mInputBuffer->release();
-    mInputBuffer = NULL;
+    mInputBuffer->set_range(
+            mInputBuffer->range_offset() + frameSize,
+            mInputBuffer->range_length() - frameSize);
+
+    if (mInputBuffer->range_length() == 0) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
 
     buffer->meta_data()->setInt64(
             kKeyTime,
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 00e0046..7e18c1f 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -63,6 +63,11 @@
     mFormat->setInt32(kKeyHeight, height);
     mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
     mFormat->setCString(kKeyDecoderComponent, "AVCDecoder");
+
+    int64_t durationUs;
+    if (mSource->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+        mFormat->setInt64(kKeyDuration, durationUs);
+    }
 }
 
 AVCDecoder::~AVCDecoder() {
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index 54061ed..2f919c2 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -94,16 +94,18 @@
 
     int32_t numChannels;
     int32_t sampleRate;
-    int64_t durationUs;
     CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
     CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-    CHECK(srcFormat->findInt64(kKeyDuration, &durationUs));
 
     sp<MetaData> meta = new MetaData;
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
     meta->setInt32(kKeyChannelCount, numChannels);
     meta->setInt32(kKeySampleRate, sampleRate);
-    meta->setInt64(kKeyDuration, durationUs);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        meta->setInt64(kKeyDuration, durationUs);
+    }
 
     return meta;
 }