Squashed commit of the following:

commit 63be8ceb8b2354fb997a277c0092abae015ecf10
Author: Andreas Huber <andih@google.com>
Date:   Fri Dec 17 13:45:34 2010 -0800

    Enable handling of discontinuities that involve potential format changes.

    Change-Id: I21848a113db8764abb54bdcf302b0923253eaf4d

commit d18a7f80ec09af382026809263dcbbfa9e7a9ec8
Author: Andreas Huber <andih@google.com>
Date:   Fri Dec 17 13:45:01 2010 -0800

    Signal whether or not a format change occured as part of the discontinuity.

    Change-Id: I06e64f542f4369549c9cebbb892dc612346ae43d

commit c400adbd5fdbd65cfef7aed9ec65bcaace4bb69b
Author: Andreas Huber <andih@google.com>
Date:   Fri Dec 17 13:44:46 2010 -0800

    A little more instrumentation of ACodec

    Change-Id: I07f4aeccbbd15cdd9f80f48c3f92ee984ef6d92b

commit 1d802ee01f47b3cdc5b89502cec7fbb595e197a3
Author: Andreas Huber <andih@google.com>
Date:   Fri Dec 17 13:43:58 2010 -0800

    Only sync audio/video queues if both types of media are actually present.

    Change-Id: Ic88edf9bb1ebd4034c08747cce9877a4e28e0d35

commit e402da39d9a4d8b75653a78f728e20a3ef0fb497
Author: Andreas Huber <andih@google.com>
Date:   Fri Dec 17 13:42:24 2010 -0800

    Disable the random seek for now.

    Change-Id: Iddd597b546e2f229e88214f9bdd6452bb188105e

Change-Id: I27c4d9ba916080be94ce6117dbb095e9022ed62b
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
index 9738e33..4d4cd8d 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
@@ -151,6 +151,7 @@
             const sp<AMessage> &notify);
 
     void start();
+    void stop();
     void readMore(bool flush = false);
 
 protected:
@@ -189,6 +190,10 @@
     readMore();
 }
 
+void DecoderWrapper::WrapperReader::stop() {
+    CHECK_EQ(mDecoder->stop(), (status_t)OK);
+}
+
 void DecoderWrapper::WrapperReader::readMore(bool flush) {
     if (!flush && mEOS) {
         return;
@@ -351,6 +356,10 @@
             onSetup(msg);
             break;
 
+        case kWhatShutdown:
+            onShutdown();
+            break;
+
         case kWhatInputDataRequested:
         {
             postFillBuffer();
@@ -493,6 +502,25 @@
     ++mNumPendingDecodes;
 }
 
+void DecoderWrapper::onShutdown() {
+    mReaderLooper->stop();
+    mReaderLooper.clear();
+
+    mReader->stop();
+    mReader.clear();
+
+    mSource.clear();
+
+    mNumOutstandingInputBuffers = 0;
+    mNumOutstandingOutputBuffers = 0;
+    mNumPendingDecodes = 0;
+    mFlushing = false;
+
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+    notify->post();
+}
+
 void DecoderWrapper::postFillBuffer() {
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", ACodec::kWhatFillThisBuffer);
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.h b/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
index 883b356..b9be12c 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
@@ -66,6 +66,7 @@
     bool mFlushing;
 
     void onSetup(const sp<AMessage> &msg);
+    void onShutdown();
     void onFlush();
     void onResume();
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e99c24a..d3dab13 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -23,6 +23,7 @@
 #include "NuPlayerRenderer.h"
 #include "NuPlayerStreamListener.h"
 
+#include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -31,6 +32,8 @@
 #include <media/stagefright/MetaData.h>
 #include <surfaceflinger/Surface.h>
 
+#define SHUTDOWN_ON_DISCONTINUITY       0
+
 namespace android {
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -132,10 +135,16 @@
 
         case kWhatScanSources:
         {
-            instantiateDecoder(false, &mVideoDecoder);
+            instantiateDecoder(
+                    false,
+                    &mVideoDecoder,
+                    false /* ignoreCodecSpecificData */);
 
             if (mAudioSink != NULL) {
-                instantiateDecoder(true, &mAudioDecoder);
+                instantiateDecoder(
+                        true,
+                        &mAudioDecoder,
+                        false /* ignoreCodecSpecificData */);
             }
 
             if (mEOS) {
@@ -182,22 +191,20 @@
 
                 LOGI("decoder %s flush completed", audio ? "audio" : "video");
 
-                if (mFlushingAudio == FLUSHED && mFlushingVideo == FLUSHED) {
-                    LOGI("both audio and video are flushed now.");
+#if SHUTDOWN_ON_DISCONTINUITY
+                LOGI("initiating %s decoder shutdown",
+                     audio ? "audio" : "video");
 
-                    mRenderer->signalTimeDiscontinuity();
+                (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
 
-                    if (mAudioDecoder != NULL) {
-                        mAudioDecoder->signalResume();
-                    }
-
-                    if (mVideoDecoder != NULL) {
-                        mVideoDecoder->signalResume();
-                    }
-
-                    mFlushingAudio = NONE;
-                    mFlushingVideo = NONE;
+                if (audio) {
+                    mFlushingAudio = SHUTTING_DOWN_DECODER;
+                } else {
+                    mFlushingVideo = SHUTTING_DOWN_DECODER;
                 }
+#endif
+
+                finishFlushIfPossible();
             } else if (what == ACodec::kWhatOutputFormatChanged) {
                 CHECK(audio);
 
@@ -213,6 +220,23 @@
                 mAudioSink->close();
                 CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
                 mAudioSink->start();
+
+                mRenderer->signalAudioSinkChanged();
+            } else if (what == ACodec::kWhatShutdownCompleted) {
+                LOGI("%s shutdown completed", audio ? "audio" : "video");
+                if (audio) {
+                    mAudioDecoder.clear();
+
+                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
+                    mFlushingAudio = SHUT_DOWN;
+                } else {
+                    mVideoDecoder.clear();
+
+                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
+                    mFlushingVideo = SHUT_DOWN;
+                }
+
+                finishFlushIfPossible();
             } else {
                 CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
 
@@ -265,6 +289,43 @@
     }
 }
 
+void NuPlayer::finishFlushIfPossible() {
+    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
+        return;
+    }
+
+    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
+        return;
+    }
+
+    LOGI("both audio and video are flushed now.");
+
+    mRenderer->signalTimeDiscontinuity();
+
+    if (mFlushingAudio == SHUT_DOWN) {
+        instantiateDecoder(
+                true,
+                &mAudioDecoder,
+                true /* ignoreCodecSpecificData */);
+        CHECK(mAudioDecoder != NULL);
+    } else if (mAudioDecoder != NULL) {
+        mAudioDecoder->signalResume();
+    }
+
+    if (mFlushingVideo == SHUT_DOWN) {
+        instantiateDecoder(
+                false,
+                &mVideoDecoder,
+                true /* ignoreCodecSpecificData */);
+        CHECK(mVideoDecoder != NULL);
+    } else if (mVideoDecoder != NULL) {
+        mVideoDecoder->signalResume();
+    }
+
+    mFlushingAudio = NONE;
+    mFlushingVideo = NONE;
+}
+
 void NuPlayer::feedMoreTSData() {
     CHECK(!mEOS);
 
@@ -285,7 +346,10 @@
         } else {
             if (buffer[0] == 0x00) {
                 // XXX legacy
-                mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
+                mTSParser->signalDiscontinuity(
+                        buffer[1] == 0x00
+                            ? ATSParser::DISCONTINUITY_SEEK
+                            : ATSParser::DISCONTINUITY_FORMATCHANGE);
             } else {
                 mTSParser->feedTSPacket(buffer, sizeof(buffer));
             }
@@ -354,7 +418,7 @@
 }
 
 status_t NuPlayer::instantiateDecoder(
-        bool audio, sp<Decoder> *decoder) {
+        bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData) {
     if (*decoder != NULL) {
         return OK;
     }
@@ -378,7 +442,7 @@
     looper()->registerHandler(*decoder);
 
     const sp<MetaData> &meta = source->getFormat();
-    (*decoder)->configure(meta);
+    (*decoder)->configure(meta, ignoreCodecSpecificData);
 
     return OK;
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 9a5a6c4..fad1ce1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -79,14 +79,16 @@
         NONE,
         AWAITING_DISCONTINUITY,
         FLUSHING_DECODER,
-        FLUSHED
+        SHUTTING_DOWN_DECODER,
+        FLUSHED,
+        SHUT_DOWN,
     };
 
     FlushStatus mFlushingAudio;
     FlushStatus mFlushingVideo;
 
     status_t instantiateDecoder(
-            bool audio, sp<Decoder> *decoder);
+            bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData);
 
     status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
     void renderBuffer(bool audio, const sp<AMessage> &msg);
@@ -100,6 +102,8 @@
     void feedMoreTSData();
     void notifyListener(int msg, int ext1, int ext2);
 
+    void finishFlushIfPossible();
+
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index d1ed222..1d78808 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -42,7 +42,8 @@
 NuPlayer::Decoder::~Decoder() {
 }
 
-void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
+void NuPlayer::Decoder::configure(
+        const sp<MetaData> &meta, bool ignoreCodecSpecificData) {
     CHECK(mCodec == NULL);
     CHECK(mWrapper == NULL);
 
@@ -54,6 +55,10 @@
 
     sp<AMessage> format = makeFormat(meta);
 
+    if (ignoreCodecSpecificData) {
+        mCSD.clear();
+    }
+
     if (mSurface != NULL) {
         format->setObject("surface", mSurface);
     }
@@ -282,5 +287,14 @@
     }
 }
 
+void NuPlayer::Decoder::initiateShutdown() {
+    if (mCodec != NULL) {
+        mCodec->initiateShutdown();
+    } else {
+        CHECK(mWrapper != NULL);
+        mWrapper->initiateShutdown();
+    }
+}
+
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 77800be..07fe47e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -29,9 +29,12 @@
 struct NuPlayer::Decoder : public AHandler {
     Decoder(const sp<AMessage> &notify, const sp<Surface> &surface = NULL);
 
-    void configure(const sp<MetaData> &meta);
+    void configure(
+            const sp<MetaData> &meta, bool ignoreCodecSpecificData);
+
     void signalFlush();
     void signalResume();
+    void initiateShutdown();
 
 protected:
     virtual ~Decoder();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 855bc0ae..57a652c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -39,7 +39,9 @@
       mAnchorTimeRealUs(-1),
       mFlushingAudio(false),
       mFlushingVideo(false),
-      mSyncQueues(true) {
+      mHasAudio(mAudioSink != NULL),
+      mHasVideo(true),
+      mSyncQueues(mHasAudio && mHasVideo) {
 }
 
 NuPlayer::Renderer::~Renderer() {
@@ -87,7 +89,7 @@
     CHECK(mVideoQueue.empty());
     mAnchorTimeMediaUs = -1;
     mAnchorTimeRealUs = -1;
-    mSyncQueues = true;
+    mSyncQueues = mHasAudio && mHasVideo;
 }
 
 void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
@@ -142,6 +144,12 @@
             break;
         }
 
+        case kWhatAudioSinkChanged:
+        {
+            onAudioSinkChanged();
+            break;
+        }
+
         default:
             TRESPASS();
             break;
@@ -163,6 +171,10 @@
     msg->post(10000);
 }
 
+void NuPlayer::Renderer::signalAudioSinkChanged() {
+    (new AMessage(kWhatAudioSinkChanged, id()))->post();
+}
+
 void NuPlayer::Renderer::onDrainAudioQueue() {
     uint32_t numFramesPlayed;
     CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
@@ -264,7 +276,7 @@
         if (mAnchorTimeMediaUs < 0) {
             delayUs = 0;
 
-            if (mAudioSink == NULL) {
+            if (!mHasAudio) {
                 mAnchorTimeMediaUs = mediaTimeUs;
                 mAnchorTimeRealUs = ALooper::GetNowUs();
             }
@@ -492,5 +504,10 @@
     return true;
 }
 
+void NuPlayer::Renderer::onAudioSinkChanged() {
+    CHECK(!mDrainAudioQueuePending);
+    mNumFramesWritten = 0;
+}
+
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 834ddc5..eaa004a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -37,6 +37,8 @@
 
     void signalTimeDiscontinuity();
 
+    void signalAudioSinkChanged();
+
     enum {
         kWhatEOS,
         kWhatFlushComplete,
@@ -54,6 +56,7 @@
         kWhatQueueBuffer,
         kWhatQueueEOS,
         kWhatFlush,
+        kWhatAudioSinkChanged,
     };
 
     struct QueueEntry {
@@ -81,6 +84,8 @@
     bool mFlushingAudio;
     bool mFlushingVideo;
 
+    bool mHasAudio;
+    bool mHasVideo;
     bool mSyncQueues;
 
     void onDrainAudioQueue();
@@ -92,6 +97,7 @@
     void onQueueBuffer(const sp<AMessage> &msg);
     void onQueueEOS(const sp<AMessage> &msg);
     void onFlush(const sp<AMessage> &msg);
+    void onAudioSinkChanged();
 
     void notifyEOS(bool audio);
     void notifyFlushComplete(bool audio);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 77276ab..3bb61f2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1157,6 +1157,9 @@
     if (!msg->findObject("buffer", &obj)) {
         CHECK(msg->findInt32("err", &err));
 
+        LOGV("[%s] saw error %d instead of an input buffer",
+             mCodec->mComponentName.c_str(), err);
+
         obj.clear();
     }
 
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 30ac404..cc7189c 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -468,13 +468,16 @@
         return;
     }
 
-    if (explicitDiscontinuity
-            || (mPrevBandwidthIndex >= 0
-                && (size_t)mPrevBandwidthIndex != bandwidthIndex)) {
+    bool bandwidthChanged =
+        mPrevBandwidthIndex >= 0
+            && (size_t)mPrevBandwidthIndex != bandwidthIndex;
+
+    if (explicitDiscontinuity || bandwidthChanged) {
         // Signal discontinuity.
 
         sp<ABuffer> tmp = new ABuffer(188);
         memset(tmp->data(), 0, tmp->size());
+        tmp->data()[1] = bandwidthChanged;
 
         mDataSource->queueBuffer(tmp);
     }
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index de6346b..afacb2e 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -284,7 +284,7 @@
     : mProgram(program),
       mElementaryPID(elementaryPID),
       mStreamType(streamType),
-      mBuffer(new ABuffer(128 * 1024)),
+      mBuffer(new ABuffer(192 * 1024)),
       mPayloadStarted(false),
       mQueue(streamType == 0x1b
               ? ElementaryStreamQueue::H264 : ElementaryStreamQueue::AAC) {