OMXCodec now notifies the reader of changes in the output format by returning a special result/error code.
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 6674620..4d4d013 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -71,7 +71,12 @@
             options.clearSeekTo();
 
             bool shouldSeek = false;
-            if (err != OK) {
+            if (err == INFO_FORMAT_CHANGED) {
+                CHECK_EQ(buffer, NULL);
+
+                printf("format changed.\n");
+                continue;
+            } else if (err != OK) {
                 printf("reached EOF.\n");
 
                 shouldSeek = true;
@@ -136,6 +141,12 @@
 
             if (err != OK) {
                 CHECK_EQ(buffer, NULL);
+
+                if (err == INFO_FORMAT_CHANGED) {
+                    printf("format changed.\n");
+                    continue;
+                }
+
                 break;
             }
 
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index 2bb0ed6..73d0f77 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -36,6 +36,9 @@
     ERROR_BUFFER_TOO_SMALL  = MEDIA_ERROR_BASE - 9,
     ERROR_UNSUPPORTED       = MEDIA_ERROR_BASE - 10,
     ERROR_END_OF_STREAM     = MEDIA_ERROR_BASE - 11,
+
+    // Not technically an error.
+    INFO_FORMAT_CHANGED    = MEDIA_ERROR_BASE - 12,
 };
 
 }  // namespace android
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index d1fa114..96d57e7 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -51,6 +51,9 @@
     // buffer is available, an error is encountered of the end of the stream
     // is reached.
     // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+    // A result of INFO_FORMAT_CHANGED indicates that the format of this
+    // MediaSource has changed mid-stream, the client can continue reading
+    // but should be prepared for buffers of the new configuration.
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index ff7e34a..ec043a9 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -124,6 +124,7 @@
     bool mInitialBufferSubmit;
     bool mSignalledEOS;
     bool mNoMoreOutputData;
+    bool mOutputPortSettingsHaveChanged;
     int64_t mSeekTimeUs;
 
     Mutex mLock;
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 64e9f2f..0e92162 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -130,7 +130,10 @@
     decoder->start();
 
     MediaBuffer *buffer;
-    status_t err = decoder->read(&buffer);
+    status_t err;
+    do {
+        err = decoder->read(&buffer);
+    } while (err == INFO_FORMAT_CHANGED);
 
     if (err != OK) {
         CHECK_EQ(buffer, NULL);
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index 2c4a30b..b58e076 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -250,6 +250,13 @@
         status_t err = mVideoDecoder->read(&buffer, &options);
         CHECK((err == OK && buffer != NULL) || (err != OK && buffer == NULL));
 
+        if (err == INFO_FORMAT_CHANGED) {
+            LOGI("format changed.");
+            depopulateISurface();
+            populateISurface();
+            continue;
+        }
+
         if (err == ERROR_END_OF_STREAM || err != OK) {
             eof = true;
             continue;
@@ -601,6 +608,9 @@
     success = success && meta->findInt32(kKeyHeight, &decodedHeight);
     CHECK(success);
 
+    LOGI("mVideoWidth=%ld, mVideoHeight=%ld, decodedWidth=%ld, decodedHeight=%ld",
+         mVideoWidth, mVideoHeight, decodedWidth, decodedHeight);
+
     if (mSurface.get() != NULL) {
         mVideoRenderer =
             mClient.interface()->createRenderer(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 11c207c..8eb4738 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -677,6 +677,7 @@
       mInitialBufferSubmit(true),
       mSignalledEOS(false),
       mNoMoreOutputData(false),
+      mOutputPortSettingsHaveChanged(false),
       mSeekTimeUs(-1) {
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
@@ -1078,6 +1079,9 @@
             if (mState == RECONFIGURING) {
                 CHECK_EQ(portIndex, kPortIndexOutput);
 
+                initOutputFormat(mSource->getFormat());
+                mOutputPortSettingsHaveChanged = true;
+
                 enablePortAsync(portIndex);
 
                 status_t err = allocateBuffersOnPort(portIndex);
@@ -1782,6 +1786,7 @@
     mInitialBufferSubmit = true;
     mSignalledEOS = false;
     mNoMoreOutputData = false;
+    mOutputPortSettingsHaveChanged = false;
     mSeekTimeUs = -1;
     mFilledBuffers.clear();
 
@@ -1852,6 +1857,8 @@
 }
 
 sp<MetaData> OMXCodec::getFormat() {
+    Mutex::Autolock autoLock(mLock);
+
     return mOutputFormat;
 }
 
@@ -1915,6 +1922,12 @@
         return ERROR_END_OF_STREAM;
     }
 
+    if (mOutputPortSettingsHaveChanged) {
+        mOutputPortSettingsHaveChanged = false;
+
+        return INFO_FORMAT_CHANGED;
+    }
+
     size_t index = *mFilledBuffers.begin();
     mFilledBuffers.erase(mFilledBuffers.begin());