Merge "Use default values when MPEG4 audio config parsing fails."
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index cacfa54..b1e57cf 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -113,6 +113,8 @@
     // pending, an error is pending.
     void requestActivityNotification(const sp<AMessage> &notify);
 
+    status_t getName(AString *componentName) const;
+
 protected:
     virtual ~MediaCodec();
     virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -154,6 +156,7 @@
         kWhatCodecNotify                    = 'codc',
         kWhatRequestIDRFrame                = 'ridr',
         kWhatRequestActivityNotification    = 'racN',
+        kWhatGetName                        = 'getN',
     };
 
     enum {
@@ -178,6 +181,7 @@
     sp<ALooper> mLooper;
     sp<ALooper> mCodecLooper;
     sp<ACodec> mCodec;
+    AString mComponentName;
     uint32_t mReplyID;
     uint32_t mFlags;
     sp<SurfaceTextureClient> mNativeWindow;
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 94090ee..3076a96 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -67,7 +67,7 @@
     }
 
 protected:
-    MediaExtractor() {}
+    MediaExtractor() : mIsDrm(false) {}
     virtual ~MediaExtractor() {}
 
 private:
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 0ecc348..a211ed9 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -88,7 +88,8 @@
 class VideoFrame
 {
 public:
-    VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0) {}
+    VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0),
+            mRotationAngle(0) {}
 
     VideoFrame(const VideoFrame& copy) {
         mWidth = copy.mWidth;
@@ -105,6 +106,7 @@
                 mSize = 0;
             }
         }
+        mRotationAngle = copy.mRotationAngle;
     }
 
     ~VideoFrame() {
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
index 21d3c30..de91731 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp
@@ -1149,6 +1149,12 @@
     pDecShellContext->mLastOutputCts     = -1;
     pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
 
+    // Calculate the interval between two video frames.
+    if(pDecShellContext->m_pVideoStreamhandler->m_averageFrameRate > 0){
+        pDecShellContext->mFrameIntervalMs =
+            1000.0 / pDecShellContext->m_pVideoStreamhandler->m_averageFrameRate;
+    }
+
     /**
      * StageFright graph building
      */
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 362d022..aec8c4a 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1441,7 +1441,7 @@
     result.append(" AudioTrack::dump\n");
     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]);
     result.append(buffer);
-    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mCblk->frameCount);
+    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, (mCblk == 0) ? 0 : mCblk->frameCount);
     result.append(buffer);
     snprintf(buffer, 255, "  sample rate(%d), status(%d), muted(%d)\n", (mCblk == 0) ? 0 : mCblk->sampleRate, mStatus, mMuted);
     result.append(buffer);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index faa0f31..cc0581e 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -95,6 +95,7 @@
         libstagefright_matroska \
         libstagefright_timedtext \
         libvpx \
+        libwebm \
         libstagefright_mpeg2ts \
         libstagefright_httplive \
         libstagefright_id3 \
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
index 29bb056..098fcf9 100644
--- a/media/libstagefright/FLACExtractor.cpp
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -122,7 +122,7 @@
     // media buffers
     size_t mMaxBufferSize;
     MediaBufferGroup *mGroup;
-    void (*mCopy)(short *dst, const int *const *src, unsigned nSamples);
+    void (*mCopy)(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels);
 
     // handle to underlying libFLAC parser
     FLAC__StreamDecoder *mDecoder;
@@ -380,14 +380,14 @@
 // Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
 // These are candidates for optimization if needed.
 
-static void copyMono8(short *dst, const int *const *src, unsigned nSamples)
+static void copyMono8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i] << 8;
     }
 }
 
-static void copyStereo8(short *dst, const int *const *src, unsigned nSamples)
+static void copyStereo8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i] << 8;
@@ -395,14 +395,23 @@
     }
 }
 
-static void copyMono16(short *dst, const int *const *src, unsigned nSamples)
+static void copyMultiCh8(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
+{
+    for (unsigned i = 0; i < nSamples; ++i) {
+        for (unsigned c = 0; c < nChannels; ++c) {
+            *dst++ = src[c][i] << 8;
+        }
+    }
+}
+
+static void copyMono16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i];
     }
 }
 
-static void copyStereo16(short *dst, const int *const *src, unsigned nSamples)
+static void copyStereo16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i];
@@ -410,16 +419,25 @@
     }
 }
 
+static void copyMultiCh16(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
+{
+    for (unsigned i = 0; i < nSamples; ++i) {
+        for (unsigned c = 0; c < nChannels; ++c) {
+            *dst++ = src[c][i];
+        }
+    }
+}
+
 // 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
 
-static void copyMono24(short *dst, const int *const *src, unsigned nSamples)
+static void copyMono24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i] >> 8;
     }
 }
 
-static void copyStereo24(short *dst, const int *const *src, unsigned nSamples)
+static void copyStereo24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         *dst++ = src[0][i] >> 8;
@@ -427,7 +445,16 @@
     }
 }
 
-static void copyTrespass(short *dst, const int *const *src, unsigned nSamples)
+static void copyMultiCh24(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
+{
+    for (unsigned i = 0; i < nSamples; ++i) {
+        for (unsigned c = 0; c < nChannels; ++c) {
+            *dst++ = src[c][i] >> 8;
+        }
+    }
+}
+
+static void copyTrespass(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels)
 {
     TRESPASS();
 }
@@ -507,11 +534,7 @@
     }
     if (mStreamInfoValid) {
         // check channel count
-        switch (getChannels()) {
-        case 1:
-        case 2:
-            break;
-        default:
+        if (getChannels() == 0 || getChannels() > 8) {
             ALOGE("unsupported channel count %u", getChannels());
             return NO_INIT;
         }
@@ -536,9 +559,10 @@
         case 32000:
         case 44100:
         case 48000:
+        case 88200:
+        case 96000:
             break;
         default:
-            // 96000 would require a proper downsampler in AudioFlinger
             ALOGE("unsupported sample rate %u", getSampleRate());
             return NO_INIT;
         }
@@ -546,17 +570,20 @@
         static const struct {
             unsigned mChannels;
             unsigned mBitsPerSample;
-            void (*mCopy)(short *dst, const int *const *src, unsigned nSamples);
+            void (*mCopy)(short *dst, const int *const *src, unsigned nSamples, unsigned nChannels);
         } table[] = {
             { 1,  8, copyMono8    },
             { 2,  8, copyStereo8  },
+            { 8,  8, copyMultiCh8  },
             { 1, 16, copyMono16   },
             { 2, 16, copyStereo16 },
+            { 8, 16, copyMultiCh16 },
             { 1, 24, copyMono24   },
             { 2, 24, copyStereo24 },
+            { 8, 24, copyMultiCh24 },
         };
         for (unsigned i = 0; i < sizeof(table)/sizeof(table[0]); ++i) {
-            if (table[i].mChannels == getChannels() &&
+            if (table[i].mChannels >= getChannels() &&
                     table[i].mBitsPerSample == getBitsPerSample()) {
                 mCopy = table[i].mCopy;
                 break;
@@ -640,7 +667,7 @@
     short *data = (short *) buffer->data();
     buffer->set_range(0, bufferSize);
     // copy PCM from FLAC write buffer to our media buffer, with interleaving
-    (*mCopy)(data, mWriteBuffer, blocksize);
+    (*mCopy)(data, mWriteBuffer, blocksize, getChannels());
     // fill in buffer metadata
     CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
     FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number;
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index d94054b..380dab4 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -350,8 +350,10 @@
 
     mInitCheck = OK;
 
-    // get iTunes-style gapless info if present
-    ID3 id3(mDataSource);
+    // Get iTunes-style gapless info if present.
+    // When getting the id3 tag, skip the V1 tags to prevent the source cache
+    // from being iterated to the end of the file.
+    ID3 id3(mDataSource, true);
     if (id3.isValid()) {
         ID3::Iterator *com = new ID3::Iterator(id3, "COM");
         if (com->done()) {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index dc8e4a3..1a62f9d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/DataSource.h>
@@ -1221,18 +1222,15 @@
 
         case FOURCC('a', 'v', 'c', 'C'):
         {
-            char buffer[256];
-            if (chunk_data_size > (off64_t)sizeof(buffer)) {
-                return ERROR_BUFFER_TOO_SMALL;
-            }
+            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
 
             if (mDataSource->readAt(
-                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
+                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
                 return ERROR_IO;
             }
 
             mLastTrack->meta->setData(
-                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
+                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
 
             *offset += chunk_size;
             break;
@@ -1426,18 +1424,15 @@
             if (mFileMetaData != NULL) {
                 ALOGV("chunk_data_size = %lld and data_offset = %lld",
                         chunk_data_size, data_offset);
-                uint8_t *buffer = new uint8_t[chunk_data_size + 1];
+                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
                 if (mDataSource->readAt(
-                    data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) {
-                    delete[] buffer;
-                    buffer = NULL;
-
+                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
                     return ERROR_IO;
                 }
                 const int kSkipBytesOfDataBox = 16;
                 mFileMetaData->setData(
                     kKeyAlbumArt, MetaData::TYPE_NONE,
-                    buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
+                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
             }
 
             *offset += chunk_size;
@@ -1633,8 +1628,9 @@
         {
             if (size == 16 && flags == 0) {
                 char tmp[16];
-                sprintf(tmp, "%d/%d",
-                        (int)buffer[size - 5], (int)buffer[size - 3]);
+                uint16_t* pTrack = (uint16_t*)&buffer[10];
+                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
+                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
 
                 mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
             }
@@ -1642,10 +1638,11 @@
         }
         case FOURCC('d', 'i', 's', 'k'):
         {
-            if (size == 14 && flags == 0) {
+            if ((size == 14 || size == 16) && flags == 0) {
                 char tmp[16];
-                sprintf(tmp, "%d/%d",
-                        (int)buffer[size - 3], (int)buffer[size - 1]);
+                uint16_t* pDisc = (uint16_t*)&buffer[10];
+                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
+                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
 
                 mFileMetaData->setCString(kKeyDiscNumber, tmp);
             }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 56e6df0..cb8a651 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -302,6 +302,20 @@
     return OK;
 }
 
+status_t MediaCodec::getName(AString *name) const {
+    sp<AMessage> msg = new AMessage(kWhatGetName, id());
+
+    sp<AMessage> response;
+    status_t err;
+    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
+        return err;
+    }
+
+    CHECK(response->findString("name", name));
+
+    return OK;
+}
+
 status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
     sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
     msg->setInt32("portIndex", kPortIndexInput);
@@ -534,16 +548,15 @@
                     CHECK_EQ(mState, INITIALIZING);
                     setState(INITIALIZED);
 
-                    AString componentName;
-                    CHECK(msg->findString("componentName", &componentName));
+                    CHECK(msg->findString("componentName", &mComponentName));
 
-                    if (componentName.startsWith("OMX.google.")) {
+                    if (mComponentName.startsWith("OMX.google.")) {
                         mFlags |= kFlagIsSoftwareCodec;
                     } else {
                         mFlags &= ~kFlagIsSoftwareCodec;
                     }
 
-                    if (componentName.endsWith(".secure")) {
+                    if (mComponentName.endsWith(".secure")) {
                         mFlags |= kFlagIsSecure;
                     } else {
                         mFlags &= ~kFlagIsSecure;
@@ -1171,6 +1184,25 @@
             break;
         }
 
+        case kWhatGetName:
+        {
+            uint32_t replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
+            if (mComponentName.empty()) {
+                sp<AMessage> response = new AMessage;
+                response->setInt32("err", INVALID_OPERATION);
+
+                response->postReply(replyID);
+                break;
+            }
+
+            sp<AMessage> response = new AMessage;
+            response->setString("name", mComponentName.c_str());
+            response->postReply(replyID);
+            break;
+        }
+
         default:
             TRESPASS();
     }
@@ -1240,6 +1272,10 @@
         mActivityNotify.clear();
     }
 
+    if (newState == UNINITIALIZED) {
+        mComponentName.clear();
+    }
+
     mState = newState;
 
     cancelPendingDequeueOperations();
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index a2f3f13..19af4fb 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -433,7 +433,7 @@
         return NULL;
     }
 
-    return strdup(mMetaData.valueAt(index).string());
+    return mMetaData.valueAt(index).string();
 }
 
 void StagefrightMetadataRetriever::parseMetaData() {
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index a38400b..2a7f628 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -401,8 +401,10 @@
         return err;
     }
 
+    // make sure that maxBytesToRead is multiple of 3, in 24-bit case
     size_t maxBytesToRead =
-        mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
+        mBitsPerSample == 8 ? kMaxFrameSize / 2 : 
+        (mBitsPerSample == 24 ? 3*(kMaxFrameSize/3): kMaxFrameSize);
 
     size_t maxBytesAvailable =
         (mCurrentPos - mOffset >= (off64_t)mSize)
@@ -425,7 +427,7 @@
 
     buffer->set_range(0, n);
 
-    if (mWaveFormat == WAVE_FORMAT_PCM) {
+    if (mWaveFormat == WAVE_FORMAT_PCM || mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
         if (mBitsPerSample == 8) {
             // Convert 8-bit unsigned samples to 16-bit signed.
 
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
index 3223871..0082d7c 100644
--- a/media/libstagefright/codecs/on2/dec/Android.mk
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -5,9 +5,9 @@
         SoftVPX.cpp
 
 LOCAL_C_INCLUDES := \
-        $(TOP)/external/libvpx \
-        $(TOP)/external/libvpx/vpx_codec \
-        $(TOP)/external/libvpx/vpx_ports \
+        $(TOP)/external/libvpx/libvpx \
+        $(TOP)/external/libvpx/libvpx/vpx_codec \
+        $(TOP)/external/libvpx/libvpx/vpx_ports \
         frameworks/av/media/libstagefright/include \
         frameworks/native/include/media/openmax \
 
@@ -21,4 +21,3 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 69274ca..22c2f5a 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -30,7 +30,7 @@
 
 static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
 
-ID3::ID3(const sp<DataSource> &source)
+ID3::ID3(const sp<DataSource> &source, bool ignoreV1)
     : mIsValid(false),
       mData(NULL),
       mSize(0),
@@ -38,7 +38,7 @@
       mVersion(ID3_UNKNOWN) {
     mIsValid = parseV2(source);
 
-    if (!mIsValid) {
+    if (!mIsValid && !ignoreV1) {
         mIsValid = parseV1(source);
     }
 }
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 8714008..3028f56 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -35,7 +35,7 @@
         ID3_V2_4,
     };
 
-    ID3(const sp<DataSource> &source);
+    ID3(const sp<DataSource> &source, bool ignoreV1 = false);
     ~ID3();
 
     bool isValid() const;
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
index 2cccb4f..2d8c1e1 100644
--- a/media/libstagefright/matroska/Android.mk
+++ b/media/libstagefright/matroska/Android.mk
@@ -5,7 +5,7 @@
         MatroskaExtractor.cpp
 
 LOCAL_C_INCLUDES:= \
-        $(TOP)/external/libvpx/mkvparser \
+        $(TOP)/external/libvpx/libwebm \
         $(TOP)/frameworks/native/include/media/openmax \
 
 LOCAL_CFLAGS += -Wno-multichar
diff --git a/media/libstagefright/mp4/FragmentedMP4Parser.cpp b/media/libstagefright/mp4/FragmentedMP4Parser.cpp
index 7fe4e63..451c837 100644
--- a/media/libstagefright/mp4/FragmentedMP4Parser.cpp
+++ b/media/libstagefright/mp4/FragmentedMP4Parser.cpp
@@ -132,6 +132,10 @@
             CHECK(mFile != NULL);
         }
 
+    virtual ~FileSource() {
+        fclose(mFile);
+    }
+
     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
         fseek(mFile, offset, SEEK_SET);
         return fread(data, 1, size, mFile);
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index fb8abc5..9e8725a 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -145,7 +145,6 @@
 
     unsigned payloadHeader = buffer->data()[0];
     unsigned CMR = payloadHeader >> 4;
-    CHECK_EQ(payloadHeader & 0x0f, 0u);  // RR
 
     Vector<uint8_t> tableOfContents;
 
diff --git a/media/libstagefright/rtsp/AH263Assembler.cpp b/media/libstagefright/rtsp/AH263Assembler.cpp
index d0313cc..75cd911 100644
--- a/media/libstagefright/rtsp/AH263Assembler.cpp
+++ b/media/libstagefright/rtsp/AH263Assembler.cpp
@@ -13,6 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AH263Assembler"
+#include <utils/Log.h>
 
 #include "AH263Assembler.h"
 
@@ -100,11 +103,34 @@
     }
 
     unsigned payloadHeader = U16_AT(buffer->data());
-    CHECK_EQ(payloadHeader >> 11, 0u);  // RR=0
     unsigned P = (payloadHeader >> 10) & 1;
     unsigned V = (payloadHeader >> 9) & 1;
     unsigned PLEN = (payloadHeader >> 3) & 0x3f;
-    // unsigned PEBIT = payloadHeader & 7;
+    unsigned PEBIT = payloadHeader & 7;
+
+    // V=0
+    if (V != 0u) {
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        ALOGW("Packet discarded due to VRC (V != 0)");
+        return MALFORMED_PACKET;
+    }
+
+    // PLEN=0
+    if (PLEN != 0u) {
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        ALOGW("Packet discarded (PLEN != 0)");
+        return MALFORMED_PACKET;
+    }
+
+    // PEBIT=0
+    if (PEBIT != 0u) {
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        ALOGW("Packet discarded (PEBIT != 0)");
+        return MALFORMED_PACKET;
+    }
 
     size_t skip = V + PLEN + (P ? 0 : 2);
 
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 539a888..161bd4f 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -830,6 +830,7 @@
 
     if (i < 0) {
         // This is an unsolicited server->client message.
+        *index = -1;
         return OK;
     }
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index deee30f..96c7683 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1091,6 +1091,10 @@
 
     void parsePlayResponse(const sp<ARTSPResponse> &response) {
         mSeekable = false;
+        if (mTracks.size() == 0) {
+            ALOGV("parsePlayResponse: late packets ignored.");
+            return;
+        }
 
         ssize_t i = response->mHeaders.indexOfKey("range");
         if (i < 0) {