The PV AVC software decoder expects each fragment of a NAL unit to be handed to the decoder unframed.
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 56f6338..185e6ac 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -70,6 +70,7 @@
 
     long numIterationsLeft = gNumRepetitions;
     MediaSource::ReadOptions options;
+
     while (numIterationsLeft-- > 0) {
         MediaBuffer *buffer;
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 2d5b8d8..6ce2581 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -28,23 +28,23 @@
 namespace android {
 
 enum {
-    kKeyMIMEType         = 'mime',
-    kKeyWidth            = 'widt',
-    kKeyHeight           = 'heig',
-    kKeyChannelCount     = '#chn',
-    kKeySampleRate       = 'srte',
-    kKeyBitRate          = 'brte',
-    kKeyESDS             = 'esds',
-    kKeyAVCC             = 'avcc',
-    kKeyTimeUnits        = '#tim',
-    kKeyTimeScale        = 'scal',
-    kKeyNeedsNALFraming  = 'NALf',
-    kKeyIsSyncFrame      = 'sync',
-    kKeyDuration         = 'dura',
-    kKeyColorFormat      = 'colf',
-    kKeyPlatformPrivate  = 'priv',
-    kKeyDecoderComponent = 'decC',
-    kKeyBufferID         = 'bfID',
+    kKeyMIMEType          = 'mime',
+    kKeyWidth             = 'widt',
+    kKeyHeight            = 'heig',
+    kKeyChannelCount      = '#chn',
+    kKeySampleRate        = 'srte',
+    kKeyBitRate           = 'brte',
+    kKeyESDS              = 'esds',
+    kKeyAVCC              = 'avcc',
+    kKeyTimeUnits         = '#tim',
+    kKeyTimeScale         = 'scal',
+    kKeyWantsNALFragments = 'NALf',
+    kKeyIsSyncFrame       = 'sync',
+    kKeyDuration          = 'dura',
+    kKeyColorFormat       = 'colf',
+    kKeyPlatformPrivate   = 'priv',
+    kKeyDecoderComponent  = 'decC',
+    kKeyBufferID          = 'bfID',
 };
 
 enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index d4ae349..c8ee255 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -79,7 +79,7 @@
 
     enum Quirks {
         kNeedsFlushBeforeDisable             = 1,
-        kWantsRawNALFrames                   = 2,
+        kWantsNALFragments                   = 2,
         kRequiresLoadedToIdleAfterAllocation = 4,
         kRequiresAllocateBufferOnInputPorts  = 8,
     };
diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h
index 0abc5a6..99d803a 100644
--- a/include/media/stagefright/OMXDecoder.h
+++ b/include/media/stagefright/OMXDecoder.h
@@ -76,7 +76,7 @@
     };
 
     enum Quirks {
-        kWantsRawNALFrames                   = 1,
+        kWantsNALFragments                   = 1,
         kDoesntReturnBuffersOnDisable        = 2,
         kDoesntFlushOnExecutingToIdle        = 4,
         kDoesntProperlyFlushAllPortsAtOnce   = 8,
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 662d5fb..894d46c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -19,9 +19,6 @@
 
 #include <arpa/inet.h>
 
-#undef NDEBUG
-#include <assert.h>
-
 #include <ctype.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -31,6 +28,7 @@
 #include <media/stagefright/MPEG4Extractor.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/SampleTable.h>
@@ -70,10 +68,8 @@
     MediaBufferGroup *mGroup;
 
     MediaBuffer *mBuffer;
-    size_t mBufferOffset;
-    size_t mBufferSizeRemaining;
 
-    bool mNeedsNALFraming;
+    bool mWantsNALFragments;
 
     uint8_t *mSrcBuffer;
 
@@ -138,7 +134,7 @@
             return "video/avc";
 
         default:
-            assert(!"should not be here.");
+            CHECK(!"should not be here.");
             return NULL;
     }
 }
@@ -279,7 +275,7 @@
                     return err;
                 }
             }
-            assert(*offset == stop_offset);
+            CHECK_EQ(*offset, stop_offset);
 
             if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
                 mHaveMetadata = true;
@@ -291,7 +287,7 @@
 
         case FOURCC('t', 'k', 'h', 'd'):
         {
-            assert(chunk_data_size >= 4);
+            CHECK(chunk_data_size >= 4);
 
             uint8_t version;
             if (mDataSource->read_at(data_offset, &version, 1) < 1) {
@@ -444,7 +440,7 @@
             }
 
             uint8_t buffer[8];
-            assert(chunk_data_size >= (off_t)sizeof(buffer));
+            CHECK(chunk_data_size >= (off_t)sizeof(buffer));
             if (mDataSource->read_at(
                         data_offset, buffer, 8) < 8) {
                 return ERROR_IO;
@@ -470,7 +466,7 @@
                     return err;
                 }
             }
-            assert(*offset == stop_offset);
+            CHECK_EQ(*offset, stop_offset);
             break;
         }
 
@@ -518,7 +514,7 @@
                     return err;
                 }
             }
-            assert(*offset == stop_offset);
+            CHECK_EQ(*offset, stop_offset);
             break;
         }
 
@@ -560,7 +556,7 @@
                     return err;
                 }
             }
-            assert(*offset == stop_offset);
+            CHECK_EQ(*offset, stop_offset);
             break;
         }
 
@@ -728,16 +724,14 @@
       mStarted(false),
       mGroup(NULL),
       mBuffer(NULL),
-      mBufferOffset(0),
-      mBufferSizeRemaining(0),
-      mNeedsNALFraming(false),
+      mWantsNALFragments(false),
       mSrcBuffer(NULL) {
     const char *mime;
     bool success = mFormat->findCString(kKeyMIMEType, &mime);
-    assert(success);
+    CHECK(success);
 
     success = mFormat->findInt32(kKeyTimeScale, &mTimescale);
-    assert(success);
+    CHECK(success);
 
     mIsAVC = !strcasecmp(mime, "video/avc");
 }
@@ -749,21 +743,21 @@
 }
 
 status_t MPEG4Source::start(MetaData *params) {
-    assert(!mStarted);
+    CHECK(!mStarted);
 
     int32_t val;
-    if (mIsAVC && params && params->findInt32(kKeyNeedsNALFraming, &val)
+    if (params && params->findInt32(kKeyWantsNALFragments, &val)
         && val != 0) {
-        mNeedsNALFraming = true;
+        mWantsNALFragments = true;
     } else {
-        mNeedsNALFraming = false;
+        mWantsNALFragments = false;
     }
 
     mGroup = new MediaBufferGroup;
 
     size_t max_size;
     status_t err = mSampleTable->getMaxSampleSize(&max_size);
-    assert(err == OK);
+    CHECK_EQ(err, OK);
 
     // Assume that a given buffer only contains at most 10 fragments,
     // each fragment originally prefixed with a 2 byte length will
@@ -779,7 +773,7 @@
 }
 
 status_t MPEG4Source::stop() {
-    assert(mStarted);
+    CHECK(mStarted);
 
     if (mBuffer != NULL) {
         mBuffer->release();
@@ -804,7 +798,7 @@
 
 status_t MPEG4Source::read(
         MediaBuffer **out, const ReadOptions *options) {
-    assert(mStarted);
+    CHECK(mStarted);
 
     *out = NULL;
 
@@ -830,38 +824,124 @@
 
     off_t offset;
     size_t size;
-    status_t err = mSampleTable->getSampleOffsetAndSize(
-            mCurrentSampleIndex, &offset, &size);
-
-    if (err != OK) {
-        return err;
-    }
-
     uint32_t dts;
-    err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
+    bool newBuffer = false;
+    if (mBuffer == NULL) {
+        newBuffer = true;
 
-    if (err != OK) {
-        return err;
+        status_t err = mSampleTable->getSampleOffsetAndSize(
+                mCurrentSampleIndex, &offset, &size);
+
+        if (err != OK) {
+            return err;
+        }
+
+        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
+
+        if (err != OK) {
+            return err;
+        }
+
+        err = mGroup->acquire_buffer(&mBuffer);
+        if (err != OK) {
+            CHECK_EQ(mBuffer, NULL);
+            return err;
+        }
     }
 
-    err = mGroup->acquire_buffer(&mBuffer);
-    if (err != OK) {
-        assert(mBuffer == NULL);
-        return err;
-    }
+    if (!mIsAVC || mWantsNALFragments) {
+        if (newBuffer) {
+            ssize_t num_bytes_read =
+                mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
 
-    if (!mIsAVC || !mNeedsNALFraming) {
+            if (num_bytes_read < (ssize_t)size) {
+                mBuffer->release();
+                mBuffer = NULL;
+
+                return ERROR_IO;
+            }
+
+            mBuffer->set_range(0, size);
+            mBuffer->meta_data()->clear();
+            mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
+            mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
+            ++mCurrentSampleIndex;
+        }
+
+        if (!mIsAVC) {
+            *out = mBuffer;
+            mBuffer = NULL;
+
+            return OK;
+        }
+
+        // Each NAL unit is split up into its constituent fragments and
+        // each one of them returned in its own buffer.
+
+        CHECK(mBuffer->range_length() >= 2);
+
+        const uint8_t *src =
+            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
+
+        size_t nal_size = U16_AT(src);
+
+        CHECK(mBuffer->range_length() >= 2 + nal_size);
+
+        MediaBuffer *clone = mBuffer->clone();
+        clone->set_range(mBuffer->range_offset() + 2, nal_size);
+
+        mBuffer->set_range(
+                mBuffer->range_offset() + 2 + nal_size,
+                mBuffer->range_length() - 2 - nal_size);
+
+        if (mBuffer->range_length() == 0) {
+            mBuffer->release();
+            mBuffer = NULL;
+        }
+
+        *out = clone;
+
+        return OK;
+    } else {
+        // Whole NAL units are returned but each fragment is prefixed by
+        // the start code (0x00 00 00 01).
+
         ssize_t num_bytes_read =
-            mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
+            mDataSource->read_at(offset, mSrcBuffer, size);
 
         if (num_bytes_read < (ssize_t)size) {
             mBuffer->release();
             mBuffer = NULL;
 
-            return err;
+            return ERROR_IO;
         }
 
-        mBuffer->set_range(0, size);
+        uint8_t *dstData = (uint8_t *)mBuffer->data();
+        size_t srcOffset = 0;
+        size_t dstOffset = 0;
+        while (srcOffset < size) {
+            CHECK(srcOffset + 1 < size);
+            size_t nalLength =
+                (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
+            CHECK(srcOffset + 1 + nalLength < size);
+            srcOffset += 2;
+
+            if (nalLength == 0) {
+                continue;
+            }
+
+            CHECK(dstOffset + 4 <= mBuffer->size());
+
+            dstData[dstOffset++] = 0;
+            dstData[dstOffset++] = 0;
+            dstData[dstOffset++] = 0;
+            dstData[dstOffset++] = 1;
+            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+            srcOffset += nalLength;
+            dstOffset += nalLength;
+        }
+
+        mBuffer->set_range(0, dstOffset);
         mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
         mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
@@ -872,52 +952,6 @@
 
         return OK;
     }
-
-    ssize_t num_bytes_read =
-        mDataSource->read_at(offset, mSrcBuffer, size);
-
-    if (num_bytes_read < (ssize_t)size) {
-        mBuffer->release();
-        mBuffer = NULL;
-
-        return err;
-    }
-
-    uint8_t *dstData = (uint8_t *)mBuffer->data();
-    size_t srcOffset = 0;
-    size_t dstOffset = 0;
-    while (srcOffset < size) {
-        assert(srcOffset + 1 < size);
-        size_t nalLength =
-            (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
-        assert(srcOffset + 1 + nalLength < size);
-        srcOffset += 2;
-
-        if (nalLength == 0) {
-            continue;
-        }
-
-        assert(dstOffset + 4 <= mBuffer->size());
-
-        dstData[dstOffset++] = 0;
-        dstData[dstOffset++] = 0;
-        dstData[dstOffset++] = 0;
-        dstData[dstOffset++] = 1;
-        memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
-        srcOffset += nalLength;
-        dstOffset += nalLength;
-    }
-
-    mBuffer->set_range(0, dstOffset);
-    mBuffer->meta_data()->clear();
-    mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
-    mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
-    ++mCurrentSampleIndex;
-
-    *out = mBuffer;
-    mBuffer = NULL;
-
-    return OK;
 }
 
 bool SniffMPEG4(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 35d599c..70ab0b5 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -152,7 +152,7 @@
 
     uint32_t quirks = 0;
     if (!strcmp(componentName, "OMX.PV.avcdec")) {
-        quirks |= kWantsRawNALFrames;
+        quirks |= kWantsNALFragments;
     }
     if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
         quirks |= kNeedsFlushBeforeDisable;
@@ -554,7 +554,7 @@
 }
 
 OMXCodec::~OMXCodec() {
-    CHECK_EQ(mState, LOADED);
+    CHECK(mState == LOADED || mState == ERROR);
 
     status_t err = mOMX->observe_node(mNode, NULL);
     CHECK_EQ(err, OK);
@@ -1149,8 +1149,8 @@
 
         size_t size = specific->mSize;
 
-        if (!strcasecmp(mMIME, "video/avc")
-            && !(mQuirks & kWantsRawNALFrames)) {
+        if (!strcasecmp("video/avc", mMIME)
+                && !(mQuirks & kWantsNALFragments)) {
             static const uint8_t kNALStartCode[4] =
                     { 0x00, 0x00, 0x00, 0x01 };
 
@@ -1462,8 +1462,8 @@
     }
     
     sp<MetaData> params = new MetaData;
-    if (!strcasecmp(mMIME, "video/avc") && !(mQuirks & kWantsRawNALFrames)) {
-        params->setInt32(kKeyNeedsNALFraming, true);
+    if (mQuirks & kWantsNALFragments) {
+        params->setInt32(kKeyWantsNALFragments, true);
     }
     status_t err = mSource->start(params.get());
 
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index 94cca43..cf08fa5 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -139,7 +139,7 @@
 
     uint32_t quirks = 0;
     if (!strcmp(codec, "OMX.PV.avcdec")) {
-        quirks |= kWantsRawNALFrames;
+        quirks |= kWantsNALFragments;
     }
     if (!strcmp(codec, "OMX.TI.AAC.decode")
         || !strcmp(codec, "OMX.TI.MP3.decode")) {
@@ -274,8 +274,8 @@
     // mDealer->dump("Decoder Dealer");
 
     sp<MetaData> params = new MetaData;
-    if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
-        params->setInt32(kKeyNeedsNALFraming, true);
+    if (mQuirks & kWantsNALFragments) {
+        params->setInt32(kKeyWantsNALFragments, true);
     }
 
     status_t err = mSource->start(params.get());
@@ -1331,7 +1331,7 @@
 
         size_t range_length = 0;
 
-        if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
+        if (mIsAVC && !(mQuirks & kWantsNALFragments)) {
             assert((*mCodecSpecificDataIterator).size + 4 <= mem->size());
 
             memcpy(mem->pointer(), kNALStartCode, 4);