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/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;
 }