Squashed commit of the following:

commit 35cc68814a9537c31fde146e171e7b0bbdfe211e
Author: Andreas Huber <[email protected]>
Date:   Mon Aug 16 08:48:42 2010 -0700

    Only enable support for yuv to yuv conversion on passion, where it's available, use the slower yuv->rgb565 path everywhere else.

commit d8ac5a8814103e60d11d2acf61997fc31a1dc58d
Author: Andreas Huber <[email protected]>
Date:   Fri Aug 13 13:56:44 2010 -0700

    The software renderer takes over all rendering, converting from yuv to yuv if possible and rgb565 otherwise.

commit 684972074b74318bdcb826ed9b5b0864d2d2e273
Author: Andreas Huber <[email protected]>
Date:   Fri Aug 13 09:34:35 2010 -0700

    A first shot at supporting the new rendering APIs.

Change-Id: Iea9b32856da46950501f1a700f616b5feac710fd
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index af9a7ed..a1ce113 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -25,6 +25,7 @@
 
 class Parcel;
 class ISurface;
+class Surface;
 
 class IMediaPlayer: public IInterface
 {
@@ -33,7 +34,8 @@
 
     virtual void            disconnect() = 0;
 
-    virtual status_t        setVideoSurface(const sp<ISurface>& surface) = 0;
+    virtual status_t        setVideoISurface(const sp<ISurface>& surface) = 0;
+    virtual status_t        setVideoSurface(const sp<Surface>& surface) = 0;
     virtual status_t        prepareAsync() = 0;
     virtual status_t        start() = 0;
     virtual status_t        stop() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 3662983..13c73ac 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -33,6 +33,7 @@
 
 class Parcel;
 class ISurface;
+class Surface;
 
 template<typename T> class SortedVector;
 
@@ -104,7 +105,8 @@
             const KeyedVector<String8, String8> *headers = NULL) = 0;
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t    setVideoSurface(const sp<ISurface>& surface) = 0;
+    virtual status_t    setVideoISurface(const sp<ISurface>& surface) = 0;
+    virtual status_t    setVideoSurface(const sp<Surface>& surface) = 0;
     virtual status_t    prepare() = 0;
     virtual status_t    prepareAsync() = 0;
     virtual status_t    start() = 0;
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index df50981..657e7a6 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -43,7 +43,8 @@
             const char *url, const KeyedVector<String8, String8> *headers);
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoSurface(const sp<ISurface>& surface);
+    virtual status_t    setVideoISurface(const sp<ISurface>& surface);
+    virtual status_t    setVideoSurface(const sp<Surface>& surface);
     virtual status_t    prepare();
     virtual status_t    prepareAsync();
     virtual status_t    start();
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 294c867..28ab0fd 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -178,6 +178,7 @@
     // MediaPlayer needs access to ISurface for display
     friend class MediaPlayer;
     friend class IOMX;
+    friend class SoftwareRenderer;
     // this is just to be able to write some unit tests
     friend class Test;
 
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 0f55b19d..9dfdcb0 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -22,12 +22,14 @@
 
 #include <media/IMediaPlayer.h>
 #include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
 
 namespace android {
 
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     SET_VIDEO_SURFACE,
+    SET_VIDEO_ISURFACE,
     PREPARE_ASYNC,
     START,
     STOP,
@@ -65,11 +67,20 @@
         remote()->transact(DISCONNECT, data, &reply);
     }
 
-    status_t setVideoSurface(const sp<ISurface>& surface)
+    status_t setVideoISurface(const sp<ISurface>& surface)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
         data.writeStrongBinder(surface->asBinder());
+        remote()->transact(SET_VIDEO_ISURFACE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setVideoSurface(const sp<Surface>& surface)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        Surface::writeToParcel(surface, &data);
         remote()->transact(SET_VIDEO_SURFACE, data, &reply);
         return reply.readInt32();
     }
@@ -256,9 +267,15 @@
             disconnect();
             return NO_ERROR;
         } break;
-        case SET_VIDEO_SURFACE: {
+        case SET_VIDEO_ISURFACE: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             sp<ISurface> surface = interface_cast<ISurface>(data.readStrongBinder());
+            reply->writeInt32(setVideoISurface(surface));
+            return NO_ERROR;
+        } break;
+        case SET_VIDEO_SURFACE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            sp<Surface> surface = Surface::readFromParcel(data);
             reply->writeInt32(setVideoSurface(surface));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f3229c0..32b20c7 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -206,10 +206,15 @@
     LOGV("setVideoSurface");
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return NO_INIT;
-    if (surface != NULL)
-        return  mPlayer->setVideoSurface(surface->getISurface());
-    else
-        return  mPlayer->setVideoSurface(NULL);
+
+    status_t err = mPlayer->setVideoISurface(
+            surface == NULL ? NULL : surface->getISurface());
+
+    if (err != OK) {
+        return err;
+    }
+
+    return mPlayer->setVideoSurface(surface);
 }
 
 // must call with lock held
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b5972e7..d9b0c69 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -889,7 +889,15 @@
     return mStatus;
 }
 
-status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface)
+status_t MediaPlayerService::Client::setVideoISurface(const sp<ISurface>& surface)
+{
+    LOGV("[%d] setVideoISurface(%p)", mConnId, surface.get());
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->setVideoISurface(surface);
+}
+
+status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface)
 {
     LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());
     sp<MediaPlayerBase> p = getPlayer();
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index a967ee2..deb458c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -204,7 +204,8 @@
 
         // IMediaPlayer interface
         virtual void            disconnect();
-        virtual status_t        setVideoSurface(const sp<ISurface>& surface);
+        virtual status_t        setVideoISurface(const sp<ISurface>& surface);
+        virtual status_t        setVideoSurface(const sp<Surface>& surface);
         virtual status_t        prepareAsync();
         virtual status_t        start();
         virtual status_t        stop();
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 4a60ece..06e4b70 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -35,7 +35,8 @@
             const char* path, const KeyedVector<String8, String8> *headers);
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+    virtual status_t    setVideoISurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+    virtual status_t    setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; }
     virtual status_t    prepare();
     virtual status_t    prepareAsync();
     virtual status_t    start();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 2c96d6d..6b9bf85 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -44,13 +44,20 @@
     return mPlayer->setDataSource(dup(fd), offset, length);
 }
 
-status_t StagefrightPlayer::setVideoSurface(const sp<ISurface> &surface) {
-    LOGV("setVideoSurface");
+status_t StagefrightPlayer::setVideoISurface(const sp<ISurface> &surface) {
+    LOGV("setVideoISurface");
 
     mPlayer->setISurface(surface);
     return OK;
 }
 
+status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) {
+    LOGV("setVideoSurface");
+
+    mPlayer->setSurface(surface);
+    return OK;
+}
+
 status_t StagefrightPlayer::prepare() {
     return mPlayer->prepare();
 }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 781eb44..dd37102 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -35,7 +35,8 @@
             const char *url, const KeyedVector<String8, String8> *headers);
 
     virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t setVideoSurface(const sp<ISurface> &surface);
+    virtual status_t setVideoISurface(const sp<ISurface> &surface);
+    virtual status_t setVideoSurface(const sp<Surface> &surface);
     virtual status_t prepare();
     virtual status_t prepareAsync();
     virtual status_t start();
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 6e6c3cd..5eaf592 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -75,7 +75,10 @@
 
 
     // All the methods below wrap the mPlayer instance.
-    virtual status_t setVideoSurface(const android::sp<android::ISurface>& s)  {
+    virtual status_t setVideoISurface(const android::sp<android::ISurface>& s)  {
+        return mPlayer->setVideoISurface(s);
+    }
+    virtual status_t setVideoSurface(const android::sp<android::Surface>& s)  {
         return mPlayer->setVideoSurface(s);
     }
     virtual status_t prepare() {return mPlayer->prepare();}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f2653cf..b7beb6b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -44,7 +44,7 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXCodec.h>
 
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
 
 #include <media/stagefright/foundation/ALooper.h>
 
@@ -97,13 +97,14 @@
             bool previewOnly,
             const char *componentName,
             OMX_COLOR_FORMATTYPE colorFormat,
-            const sp<ISurface> &surface,
+            const sp<ISurface> &isurface,
+            const sp<Surface> &surface,
             size_t displayWidth, size_t displayHeight,
             size_t decodedWidth, size_t decodedHeight)
         : mTarget(NULL),
           mLibHandle(NULL) {
             init(previewOnly, componentName,
-                 colorFormat, surface, displayWidth,
+                 colorFormat, isurface, surface, displayWidth,
                  displayHeight, decodedWidth, decodedHeight);
     }
 
@@ -135,7 +136,8 @@
             bool previewOnly,
             const char *componentName,
             OMX_COLOR_FORMATTYPE colorFormat,
-            const sp<ISurface> &surface,
+            const sp<ISurface> &isurface,
+            const sp<Surface> &surface,
             size_t displayWidth, size_t displayHeight,
             size_t decodedWidth, size_t decodedHeight);
 
@@ -147,7 +149,8 @@
         bool previewOnly,
         const char *componentName,
         OMX_COLOR_FORMATTYPE colorFormat,
-        const sp<ISurface> &surface,
+        const sp<ISurface> &isurface,
+        const sp<Surface> &surface,
         size_t displayWidth, size_t displayHeight,
         size_t decodedWidth, size_t decodedHeight) {
     if (!previewOnly) {
@@ -173,7 +176,7 @@
 
             if (func) {
                 mTarget =
-                    (*func)(surface, componentName, colorFormat,
+                    (*func)(isurface, componentName, colorFormat,
                         displayWidth, displayHeight,
                         decodedWidth, decodedHeight);
             }
@@ -619,8 +622,18 @@
     return OK;
 }
 
+void AwesomePlayer::notifyVideoSize_l() {
+    sp<MetaData> meta = mVideoSource->getFormat();
+
+    int32_t decodedWidth, decodedHeight;
+    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
+    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+
+    notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
+}
+
 void AwesomePlayer::initRenderer_l() {
-    if (mISurface != NULL) {
+    if (mSurface != NULL || mISurface != NULL) {
         sp<MetaData> meta = mVideoSource->getFormat();
 
         int32_t format;
@@ -637,7 +650,18 @@
         // before creating a new one.
         IPCThreadState::self()->flushCommands();
 
-        if (!strncmp("OMX.", component, 4)) {
+        if (mSurface != NULL) {
+            // Other decoders are instantiated locally and as a consequence
+            // allocate their buffers in local address space.
+            mVideoRenderer = new AwesomeLocalRenderer(
+                false,  // previewOnly
+                component,
+                (OMX_COLOR_FORMATTYPE)format,
+                mISurface,
+                mSurface,
+                mVideoWidth, mVideoHeight,
+                decodedWidth, decodedHeight);
+        } else {
             // Our OMX codecs allocate buffers on the media_server side
             // therefore they require a remote IOMXRenderer that knows how
             // to display them.
@@ -647,16 +671,6 @@
                         (OMX_COLOR_FORMATTYPE)format,
                         decodedWidth, decodedHeight,
                         mVideoWidth, mVideoHeight));
-        } else {
-            // Other decoders are instantiated locally and as a consequence
-            // allocate their buffers in local address space.
-            mVideoRenderer = new AwesomeLocalRenderer(
-                false,  // previewOnly
-                component,
-                (OMX_COLOR_FORMATTYPE)format,
-                mISurface,
-                mVideoWidth, mVideoHeight,
-                decodedWidth, decodedHeight);
         }
     }
 }
@@ -695,6 +709,12 @@
     mISurface = isurface;
 }
 
+void AwesomePlayer::setSurface(const sp<Surface> &surface) {
+    Mutex::Autolock autoLock(mLock);
+
+    mSurface = surface;
+}
+
 void AwesomePlayer::setAudioSink(
         const sp<MediaPlayerBase::AudioSink> &audioSink) {
     Mutex::Autolock autoLock(mLock);
@@ -937,6 +957,8 @@
                 if (err == INFO_FORMAT_CHANGED) {
                     LOGV("VideoSource signalled format change.");
 
+                    notifyVideoSize_l();
+
                     if (mVideoRenderer != NULL) {
                         mVideoRendererIsPreview = false;
                         initRenderer_l();
@@ -1422,10 +1444,10 @@
     Mutex::Autolock autoLock(mLock);
 
     if (mIsAsyncPrepare) {
-        if (mVideoWidth < 0 || mVideoHeight < 0) {
+        if (mVideoSource == NULL) {
             notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
         } else {
-            notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
+            notifyVideoSize_l();
         }
 
         notifyListener_l(MEDIA_PREPARED);
@@ -1540,13 +1562,14 @@
 
     mFlags = state->mFlags & (LOOPING | AT_EOS);
 
-    if (state->mLastVideoFrame && mISurface != NULL) {
+    if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
         mVideoRenderer =
             new AwesomeLocalRenderer(
                     true,  // previewOnly
                     "",
                     (OMX_COLOR_FORMATTYPE)state->mColorFormat,
                     mISurface,
+                    mSurface,
                     state->mVideoWidth,
                     state->mVideoHeight,
                     state->mDecodedWidth,
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index b9ba1be..4a924c8 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -17,6 +17,11 @@
         libsurfaceflinger_client\
         libcamera_client
 
+# ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+ifeq ($(TARGET_PRODUCT),passion)
+	LOCAL_CFLAGS += -DHAS_YCBCR420_SP_ADRENO
+endif
+
 LOCAL_MODULE:= libstagefright_color_conversion
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a6dbf69..6d1dd25 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -22,65 +22,169 @@
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryHeapPmem.h>
 #include <media/stagefright/MediaDebug.h>
-#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
+#include <ui/android_native_buffer.h>
+#include <ui/GraphicBufferMapper.h>
 
 namespace android {
 
 SoftwareRenderer::SoftwareRenderer(
         OMX_COLOR_FORMATTYPE colorFormat,
-        const sp<ISurface> &surface,
+        const sp<Surface> &surface,
         size_t displayWidth, size_t displayHeight,
         size_t decodedWidth, size_t decodedHeight)
     : mColorFormat(colorFormat),
-      mConverter(colorFormat, OMX_COLOR_Format16bitRGB565),
-      mISurface(surface),
+      mConverter(NULL),
+      mYUVMode(None),
+      mSurface(surface),
       mDisplayWidth(displayWidth),
       mDisplayHeight(displayHeight),
       mDecodedWidth(decodedWidth),
-      mDecodedHeight(decodedHeight),
-      mFrameSize(mDecodedWidth * mDecodedHeight * 2),  // RGB565
-      mIndex(0) {
-    mMemoryHeap = new MemoryHeapBase("/dev/pmem_adsp", 2 * mFrameSize);
-    if (mMemoryHeap->heapID() < 0) {
-        LOGI("Creating physical memory heap failed, reverting to regular heap.");
-        mMemoryHeap = new MemoryHeapBase(2 * mFrameSize);
-    } else {
-        sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(mMemoryHeap);
-        pmemHeap->slap();
-        mMemoryHeap = pmemHeap;
+      mDecodedHeight(decodedHeight) {
+    LOGI("input format = %d", mColorFormat);
+    LOGI("display = %d x %d, decoded = %d x %d",
+            mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight);
+
+    int halFormat;
+    switch (mColorFormat) {
+#if HAS_YCBCR420_SP_ADRENO
+        case OMX_COLOR_FormatYUV420Planar:
+        {
+            halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
+            mYUVMode = YUV420ToYUV420sp;
+            break;
+        }
+
+        case 0x7fa30c00:
+        {
+            halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO;
+            mYUVMode = YUV420spToYUV420sp;
+            break;
+        }
+#endif
+
+        default:
+            halFormat = HAL_PIXEL_FORMAT_RGB_565;
+
+            mConverter = new ColorConverter(
+                    mColorFormat, OMX_COLOR_Format16bitRGB565);
+            CHECK(mConverter->isValid());
+            break;
     }
 
-    CHECK(mISurface.get() != NULL);
+    CHECK(mSurface.get() != NULL);
     CHECK(mDecodedWidth > 0);
     CHECK(mDecodedHeight > 0);
-    CHECK(mMemoryHeap->heapID() >= 0);
-    CHECK(mConverter.isValid());
+    CHECK(mConverter == NULL || mConverter->isValid());
 
-    ISurface::BufferHeap bufferHeap(
-            mDisplayWidth, mDisplayHeight,
-            mDecodedWidth, mDecodedHeight,
-            PIXEL_FORMAT_RGB_565,
-            mMemoryHeap);
+    CHECK_EQ(0,
+            native_window_set_usage(
+            mSurface.get(),
+            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
+            | GRALLOC_USAGE_HW_TEXTURE));
 
-    status_t err = mISurface->registerBuffers(bufferHeap);
-    CHECK_EQ(err, OK);
+    CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2));
+
+    // Width must be multiple of 32???
+    CHECK_EQ(0, native_window_set_buffers_geometry(
+                mSurface.get(), mDecodedWidth, mDecodedHeight,
+                halFormat));
 }
 
 SoftwareRenderer::~SoftwareRenderer() {
-    mISurface->unregisterBuffers();
+    delete mConverter;
+    mConverter = NULL;
+}
+
+static inline size_t ALIGN(size_t x, size_t alignment) {
+    return (x + alignment - 1) & ~(alignment - 1);
 }
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
-    size_t offset = mIndex * mFrameSize;
-    void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+    android_native_buffer_t *buf;
+    CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf));
+    CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
 
-    mConverter.convert(
-            mDecodedWidth, mDecodedHeight,
-            data, 0, dst, 2 * mDecodedWidth);
+    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
-    mISurface->postBuffer(offset);
-    mIndex = 1 - mIndex;
+    Rect bounds(mDecodedWidth, mDecodedHeight);
+
+    void *dst;
+    CHECK_EQ(0, mapper.lock(
+                buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
+
+    if (mConverter) {
+        mConverter->convert(
+                mDecodedWidth, mDecodedHeight,
+                data, 0, dst, buf->stride * 2);
+    } else if (mYUVMode == YUV420spToYUV420sp) {
+        // Input and output are both YUV420sp, but the alignment requirements
+        // are different.
+        size_t srcYStride = mDecodedWidth;
+        const uint8_t *srcY = (const uint8_t *)data;
+        uint8_t *dstY = (uint8_t *)dst;
+        for (size_t i = 0; i < mDecodedHeight; ++i) {
+            memcpy(dstY, srcY, mDecodedWidth);
+            srcY += srcYStride;
+            dstY += buf->stride;
+        }
+
+        size_t srcUVStride = (mDecodedWidth + 1) & ~1;
+        size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
+
+        const uint8_t *srcUV = (const uint8_t *)data
+            + mDecodedHeight * mDecodedWidth;
+
+        size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
+        uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
+
+        for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
+            memcpy(dstUV, srcUV, (mDecodedWidth + 1) & ~1);
+            srcUV += srcUVStride;
+            dstUV += dstUVStride;
+        }
+    } else if (mYUVMode == YUV420ToYUV420sp) {
+        // Input is YUV420 planar, output is YUV420sp, adhere to proper
+        // alignment requirements.
+        size_t srcYStride = mDecodedWidth;
+        const uint8_t *srcY = (const uint8_t *)data;
+        uint8_t *dstY = (uint8_t *)dst;
+        for (size_t i = 0; i < mDecodedHeight; ++i) {
+            memcpy(dstY, srcY, mDecodedWidth);
+            srcY += srcYStride;
+            dstY += buf->stride;
+        }
+
+        size_t srcUVStride = (mDecodedWidth + 1) / 2;
+        size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32) * 2;
+
+        const uint8_t *srcU = (const uint8_t *)data
+            + mDecodedHeight * mDecodedWidth;
+
+        const uint8_t *srcV =
+            srcU + ((mDecodedWidth + 1) / 2) * ((mDecodedHeight + 1) / 2);
+
+        size_t dstUVOffset = ALIGN(ALIGN(mDecodedHeight, 32) * buf->stride, 4096);
+        uint8_t *dstUV = (uint8_t *)dst + dstUVOffset;
+
+        for (size_t i = 0; i < (mDecodedHeight + 1) / 2; ++i) {
+            for (size_t j = 0; j < (mDecodedWidth + 1) / 2; ++j) {
+                dstUV[2 * j + 1] = srcU[j];
+                dstUV[2 * j] = srcV[j];
+            }
+            srcU += srcUVStride;
+            srcV += srcUVStride;
+            dstUV += dstUVStride;
+        }
+    } else {
+        memcpy(dst, data, size);
+    }
+
+    CHECK_EQ(0, mapper.unlock(buf->handle));
+
+    CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf));
+    buf = NULL;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 55e2c36..f34eb45 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -76,6 +76,7 @@
     bool isPlaying() const;
 
     void setISurface(const sp<ISurface> &isurface);
+    void setSurface(const sp<Surface> &surface);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
     status_t setLooping(bool shouldLoop);
 
@@ -117,6 +118,7 @@
     wp<MediaPlayerBase> mListener;
 
     sp<ISurface> mISurface;
+    sp<Surface> mSurface;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
     SystemTimeSource mSystemTimeSource;
@@ -219,6 +221,7 @@
     status_t seekTo_l(int64_t timeUs);
     status_t pause_l();
     void initRenderer_l();
+    void notifyVideoSize_l();
     void seekAudioIfNecessary_l();
 
     void cancelPlayerEvents(bool keepBufferingGoing = false);
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 9eed089..8d58056 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -24,14 +24,14 @@
 
 namespace android {
 
-class ISurface;
+class Surface;
 class MemoryHeapBase;
 
 class SoftwareRenderer : public VideoRenderer {
 public:
     SoftwareRenderer(
             OMX_COLOR_FORMATTYPE colorFormat,
-            const sp<ISurface> &surface,
+            const sp<Surface> &surface,
             size_t displayWidth, size_t displayHeight,
             size_t decodedWidth, size_t decodedHeight);
 
@@ -41,14 +41,18 @@
             const void *data, size_t size, void *platformPrivate);
 
 private:
+    enum YUVMode {
+        None,
+        YUV420ToYUV420sp,
+        YUV420spToYUV420sp,
+    };
+
     OMX_COLOR_FORMATTYPE mColorFormat;
-    ColorConverter mConverter;
-    sp<ISurface> mISurface;
+    ColorConverter *mConverter;
+    YUVMode mYUVMode;
+    sp<Surface> mSurface;
     size_t mDisplayWidth, mDisplayHeight;
     size_t mDecodedWidth, mDecodedHeight;
-    size_t mFrameSize;
-    sp<MemoryHeapBase> mMemoryHeap;
-    int mIndex;
 
     SoftwareRenderer(const SoftwareRenderer &);
     SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 6de761f..88b9605 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -495,12 +495,17 @@
     }
 
     if (!impl) {
+#if 0
         LOGW("Using software renderer.");
         impl = new SoftwareRenderer(
                 colorFormat,
                 surface,
                 displayWidth, displayHeight,
                 encodedWidth, encodedHeight);
+#else
+        CHECK(!"Should not be here.");
+        return NULL;
+#endif
     }
 
     return new OMXRenderer(impl);
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index b3cc8b6..53308be 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -26,6 +26,7 @@
 
 using android::INVALID_OPERATION;
 using android::ISurface;
+using android::Surface;
 using android::MediaPlayerBase;
 using android::OK;
 using android::Parcel;
@@ -67,7 +68,8 @@
     }
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) {return OK;}
-    virtual status_t    setVideoSurface(const sp<ISurface>& surface) {return OK;}
+    virtual status_t    setVideoISurface(const sp<ISurface>& surface) {return OK;}
+    virtual status_t    setVideoSurface(const sp<Surface>& surface) {return OK;}
     virtual status_t    prepare() {return OK;}
     virtual status_t    prepareAsync() {return OK;}
     virtual status_t    start() {return OK;}
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 79772ed..e4825d0 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -22,7 +22,7 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 ifeq ($(TARGET_BOARD_PLATFORM), omap3)
-	LOCAL_CFLAGS += -DNO_RGBX_8888
+	LOCAL_CFLAGS += -DNO_RGBX_8888 -DHAS_PUSH_BUFFERS
 endif
 
 # need "-lrt" on Linux simulator to pick up clock_gettime
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d257897..af7c3bf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -165,7 +165,7 @@
 {
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
-    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
+    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
     mBootFinished = true;
     property_set("ctl.stop", "bootanim");
 }
@@ -201,10 +201,10 @@
     mServerHeap = new MemoryHeapBase(4096,
             MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
     LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
-    
+
     mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
     LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
-    
+
     new(mServerCblk) surface_flinger_cblk_t;
 
     // initialize primary screen
@@ -233,7 +233,7 @@
 
     // Initialize OpenGL|ES
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-    glPixelStorei(GL_PACK_ALIGNMENT, 4); 
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnable(GL_SCISSOR_TEST);
     glShadeModel(GL_FLAT);
@@ -267,7 +267,7 @@
 
     // start boot animation
     property_set("ctl.start", "bootanim");
-    
+
     return NO_ERROR;
 }
 
@@ -662,7 +662,7 @@
 
         // Update aboveOpaqueLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
-        
+
         // Store the visible region is screen space
         layer->setVisibleRegion(visibleRegion);
         layer->setCoveredRegion(coveredRegion);
@@ -781,8 +781,8 @@
     glLoadIdentity();
 
     uint32_t flags = hw.getFlags();
-    if ((flags & DisplayHardware::SWAP_RECTANGLE) || 
-        (flags & DisplayHardware::BUFFER_PRESERVED)) 
+    if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
+        (flags & DisplayHardware::BUFFER_PRESERVED))
     {
         // we can redraw only what's dirty, but since SWAP_RECTANGLE only
         // takes a rectangle, we must make sure to update that whole
@@ -1129,7 +1129,7 @@
     if (android_atomic_dec(&mTransactionCount) == 1) {
         signalEvent();
 
-        // if there is a transaction with a resize, wait for it to 
+        // if there is a transaction with a resize, wait for it to
         // take effect before returning.
         Mutex::Autolock _l(mStateLock);
         while (mResizeTransationPending) {
@@ -1173,7 +1173,7 @@
     return NO_ERROR;
 }
 
-int SurfaceFlinger::setOrientation(DisplayID dpy, 
+int SurfaceFlinger::setOrientation(DisplayID dpy,
         int orientation, uint32_t flags)
 {
     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
@@ -1206,14 +1206,17 @@
                 int(w), int(h));
         return surfaceHandle;
     }
-    
+
     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
     sp<Layer> normalLayer;
     switch (flags & eFXSurfaceMask) {
         case eFXSurfaceNormal:
+#if HAS_PUSH_BUFFERS
             if (UNLIKELY(flags & ePushBuffers)) {
                 layer = createPushBuffersSurface(client, d, w, h, flags);
-            } else {
+            } else
+#endif
+            {
                 normalLayer = createNormalSurface(client, d, w, h, flags, format);
                 layer = normalLayer;
             }
@@ -1232,7 +1235,7 @@
         ssize_t token = addClientLayer(client, layer);
 
         surfaceHandle = layer->getSurface();
-        if (surfaceHandle != 0) { 
+        if (surfaceHandle != 0) {
             params->token = token;
             params->identity = surfaceHandle->getIdentity();
             params->width = w;
@@ -1316,7 +1319,7 @@
     /*
      * called by the window manager, when a surface should be marked for
      * destruction.
-     * 
+     *
      * The surface is removed from the current and drawing lists, but placed
      * in the purgatory queue, so it's not destroyed right-away (we need
      * to wait for all client's references to go away first).
@@ -1337,7 +1340,7 @@
 status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
 {
     // called by ~ISurface() when all references are gone
-    
+
     class MessageDestroySurface : public MessageBase {
         SurfaceFlinger* flinger;
         sp<LayerBaseClient> layer;
@@ -1350,9 +1353,9 @@
             layer.clear(); // clear it outside of the lock;
             Mutex::Autolock _l(flinger->mStateLock);
             /*
-             * remove the layer from the current list -- chances are that it's 
-             * not in the list anyway, because it should have been removed 
-             * already upon request of the client (eg: window manager). 
+             * remove the layer from the current list -- chances are that it's
+             * not in the list anyway, because it should have been removed
+             * already upon request of the client (eg: window manager).
              * However, a buggy client could have not done that.
              * Since we know we don't have any more clients, we don't need
              * to use the purgatory.
@@ -1467,7 +1470,7 @@
         }
         const bool locked(retry >= 0);
         if (!locked) {
-            snprintf(buffer, SIZE, 
+            snprintf(buffer, SIZE,
                     "SurfaceFlinger appears to be unresponsive, "
                     "dumping anyways (no locks held)\n");
             result.append(buffer);