The IOMX interface now instantiates IOMXRenderers to hide the details of hardware accelerated blitting.
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index f2a657a..4661af6 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -5,6 +5,7 @@
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
 #include <media/IOMX.h>
+#include <ui/ISurface.h>
 
 namespace android {
 
@@ -23,7 +24,9 @@
     OBSERVE_NODE,
     FILL_BUFFER,
     EMPTY_BUFFER,
+    CREATE_RENDERER,
     OBSERVER_ON_MSG,
+    RENDERER_RENDER,
 };
 
 static void *readVoidStar(const Parcel *parcel) {
@@ -262,6 +265,28 @@
         remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
     }
 #endif
+
+    virtual sp<IOMXRenderer> createRenderer(
+            const sp<ISurface> &surface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+
+        data.writeStrongBinder(surface->asBinder());
+        data.writeCString(componentName);
+        data.writeInt32(colorFormat);
+        data.writeInt32(encodedWidth);
+        data.writeInt32(encodedHeight);
+        data.writeInt32(displayWidth);
+        data.writeInt32(displayHeight);
+
+        remote()->transact(CREATE_RENDERER, data, &reply);
+
+        return interface_cast<IOMXRenderer>(reply.readStrongBinder());
+    }
 };
 
 IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
@@ -513,6 +538,33 @@
         }
 #endif
 
+        case CREATE_RENDERER:
+        {
+            CHECK_INTERFACE(IOMX, data, reply);
+
+            sp<ISurface> isurface =
+                interface_cast<ISurface>(data.readStrongBinder());
+
+            const char *componentName = data.readCString();
+
+            OMX_COLOR_FORMATTYPE colorFormat =
+                static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
+
+            size_t encodedWidth = (size_t)data.readInt32();
+            size_t encodedHeight = (size_t)data.readInt32();
+            size_t displayWidth = (size_t)data.readInt32();
+            size_t displayHeight = (size_t)data.readInt32();
+
+            sp<IOMXRenderer> renderer =
+                createRenderer(isurface, componentName, colorFormat,
+                               encodedWidth, encodedHeight,
+                               displayWidth, displayHeight);
+
+            reply->writeStrongBinder(renderer->asBinder());
+
+            return OK;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -558,4 +610,44 @@
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXRenderer : public BpInterface<IOMXRenderer> {
+public:
+    BpOMXRenderer(const sp<IBinder> &impl)
+        : BpInterface<IOMXRenderer>(impl) {
+    }
+
+    virtual void render(IOMX::buffer_id buffer) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
+        writeVoidStar(buffer, &data);
+
+        // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
+        // so that the caller knows when to recycle the buffer.
+        remote()->transact(RENDERER_RENDER, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
+
+status_t BnOMXRenderer::onTransact(
+    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+    switch (code) {
+        case RENDERER_RENDER:
+        {
+            CHECK_INTERFACE(IOMXRenderer, data, reply);
+
+            IOMX::buffer_id buffer = readVoidStar(&data);
+
+            render(buffer);
+
+            return NO_ERROR;
+        }
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
 }  // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 5be9224..0a44762 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -19,14 +19,10 @@
         MediaSource.cpp           \
         MetaData.cpp              \
         MmapSource.cpp            \
-        QComHardwareRenderer.cpp  \
         SampleTable.cpp           \
         ShoutcastSource.cpp       \
-        SoftwareRenderer.cpp      \
-        SurfaceRenderer.cpp       \
         TimeSource.cpp            \
         TimedEventQueue.cpp       \
-        TIHardwareRenderer.cpp    \
         Utils.cpp                 \
         AudioPlayer.cpp           \
         ESDS.cpp                  \
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index 04c9a11..341f002 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -35,12 +35,8 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXDecoder.h>
-#include <media/stagefright/QComHardwareRenderer.h>
 #include <media/stagefright/ShoutcastSource.h>
-#include <media/stagefright/SoftwareRenderer.h>
-#include <media/stagefright/SurfaceRenderer.h>
 #include <media/stagefright/TimeSource.h>
-#include <media/stagefright/TIHardwareRenderer.h>
 #include <ui/PixelFormat.h>
 #include <ui/Surface.h>
 
@@ -61,7 +57,6 @@
       mDuration(0),
       mPlaying(false),
       mPaused(false),
-      mRenderer(NULL),
       mSeeking(false),
       mFrameSize(0),
       mUseSoftwareColorConversion(false) {
@@ -121,7 +116,6 @@
       mDuration(0),
       mPlaying(false),
       mPaused(false),
-      mRenderer(NULL),
       mSeeking(false),
       mFrameSize(0),
       mUseSoftwareColorConversion(false) {
@@ -379,7 +373,7 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        if (mRenderer != NULL) {
+        if (mVideoRenderer.get() != NULL) {
             sendFrameToISurface(buffer);
         }
     }
@@ -652,52 +646,26 @@
     success = success && meta->findInt32(kKeyHeight, &decodedHeight);
     assert(success);
 
-    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+    const sp<ISurface> &isurface =
+        mSurface.get() != NULL ? mSurface->getISurface() : mISurface;
 
-    if (mSurface.get() != NULL) {
-        LOGW("Using SurfaceRenderer.");
-        mRenderer =
-            new SurfaceRenderer(
-                    mSurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else if (format == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
-        && !strncmp(component, "OMX.qcom.video.decoder.", 23)) {
-        LOGW("Using QComHardwareRenderer.");
-        mRenderer =
-            new QComHardwareRenderer(
-                    mISurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else if (format == OMX_COLOR_FormatCbYCrY
-            && !strcmp(component, "OMX.TI.Video.Decoder")) {
-        LOGW("Using TIHardwareRenderer.");
-        mRenderer =
-            new TIHardwareRenderer(
-                    mISurface, mVideoWidth, mVideoHeight,
-                    decodedWidth, decodedHeight);
-    } else {
-        LOGW("Using software renderer.");
-        mRenderer = new SoftwareRenderer(
-                mISurface, mVideoWidth, mVideoHeight,
-                decodedWidth, decodedHeight);
-    }
+    mVideoRenderer =
+        mClient.interface()->createRenderer(
+                isurface, component,
+                (OMX_COLOR_FORMATTYPE)format,
+                decodedWidth, decodedHeight,
+                mVideoWidth, mVideoHeight);
 }
 
 void MediaPlayerImpl::depopulateISurface() {
-    delete mRenderer;
-    mRenderer = NULL;
+    mVideoRenderer.clear();
 }
 
 void MediaPlayerImpl::sendFrameToISurface(MediaBuffer *buffer) {
-    void *platformPrivate;
-    if (!buffer->meta_data()->findPointer(
-                kKeyPlatformPrivate, &platformPrivate)) {
-        platformPrivate = NULL;
+    void *id;
+    if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
+        mVideoRenderer->render((IOMX::buffer_id)id);
     }
-
-    mRenderer->render(
-        (const uint8_t *)buffer->data() + buffer->range_offset(),
-        buffer->range_length(),
-        platformPrivate);
 }
 
 void MediaPlayerImpl::setAudioSink(
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index 5e44999..780cd2e 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -154,8 +154,7 @@
     if (!strncmp(codec, "OMX.qcom.video.", 15)) {
         quirks |= kRequiresLoadedToIdleAfterAllocation;
     }
-    if (!strcmp(codec, "OMX.TI.AAC.decode")
-        || !strcmp(codec, "OMX.TI.MP3.decode")) {
+    if (!strcmp(codec, "OMX.TI.MP3.decode")) {
         quirks |= kMeasuresTimeInMilliseconds;
     }
 
@@ -1551,6 +1550,10 @@
             kKeyPlatformPrivate,
             msg.u.extended_buffer_data.platform_private);
 
+    media_buffer->meta_data()->setPointer(
+            kKeyBufferID,
+            msg.u.extended_buffer_data.buffer);
+
     if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
         mErrorCondition = ERROR_END_OF_STREAM;
     }
diff --git a/media/libstagefright/SurfaceRenderer.cpp b/media/libstagefright/SurfaceRenderer.cpp
deleted file mode 100644
index e54288d..0000000
--- a/media/libstagefright/SurfaceRenderer.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceRenderer"
-#include <utils/Log.h>
-
-#undef NDEBUG
-#include <assert.h>
-
-#include <media/stagefright/SurfaceRenderer.h>
-#include <ui/Surface.h>
-
-namespace android {
-
-SurfaceRenderer::SurfaceRenderer(
-        const sp<Surface> &surface,
-        size_t displayWidth, size_t displayHeight,
-        size_t decodedWidth, size_t decodedHeight)
-    : mSurface(surface),
-      mDisplayWidth(displayWidth),
-      mDisplayHeight(displayHeight),
-      mDecodedWidth(decodedWidth),
-      mDecodedHeight(decodedHeight) {
-}
-
-SurfaceRenderer::~SurfaceRenderer() {
-}
-
-void SurfaceRenderer::render(
-        const void *data, size_t size, void *platformPrivate) {
-    Surface::SurfaceInfo info;
-    status_t err = mSurface->lock(&info);
-    if (err != OK) {
-        return;
-    }
-
-    const uint8_t *src = (const uint8_t *)data;
-    uint8_t *dst = (uint8_t *)info.bits;
-
-    for (size_t i = 0; i < mDisplayHeight; ++i) {
-        memcpy(dst, src, mDisplayWidth);
-        src += mDecodedWidth;
-        dst += mDisplayWidth;
-    }
-    src += (mDecodedHeight - mDisplayHeight) * mDecodedWidth;
-    
-    for (size_t i = 0; i < (mDisplayHeight + 1) / 2; ++i) {
-        memcpy(dst, src, (mDisplayWidth + 1) & ~1);
-        src += (mDecodedWidth + 1) & ~1;
-        dst += (mDisplayWidth + 1) & ~1;
-    }
-
-    mSurface->unlockAndPost();
-}
-
-}  // namespace android
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 9c6d475..2e564e9 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -9,13 +9,17 @@
 LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY)
 
 LOCAL_SRC_FILES:=                 \
-	OMX.cpp
+	OMX.cpp                   \
+        QComHardwareRenderer.cpp  \
+        SoftwareRenderer.cpp      \
+        TIHardwareRenderer.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-        libbinder         \
-        libmedia          \
-	libutils          \
-        libui             \
+LOCAL_SHARED_LIBRARIES :=       \
+        libbinder               \
+        libmedia                \
+	libutils                \
+        libui                   \
+        libcutils               \
         libopencore_common
 
 LOCAL_PRELINK_MODULE:= false
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index daaa741..062afd4 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -24,9 +24,15 @@
 #include <assert.h>
 
 #include "OMX.h"
+#include "OMXRenderer.h"
+
 #include "pv_omxcore.h"
 
 #include <binder/IMemory.h>
+#include <media/stagefright/QComHardwareRenderer.h>
+#include <media/stagefright/SoftwareRenderer.h>
+#include <media/stagefright/TIHardwareRenderer.h>
+#include <media/stagefright/VideoRenderer.h>
 
 #include <OMX_Component.h>
 
@@ -619,5 +625,62 @@
 }
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+
+sp<IOMXRenderer> OMX::createRenderer(
+        const sp<ISurface> &surface,
+        const char *componentName,
+        OMX_COLOR_FORMATTYPE colorFormat,
+        size_t encodedWidth, size_t encodedHeight,
+        size_t displayWidth, size_t displayHeight) {
+    VideoRenderer *impl = NULL;
+
+    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+    if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
+        && !strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
+        LOGW("Using QComHardwareRenderer.");
+        impl =
+            new QComHardwareRenderer(
+                    surface,
+                    displayWidth, displayHeight,
+                    encodedWidth, encodedHeight);
+    } else if (colorFormat == OMX_COLOR_FormatCbYCrY
+            && !strcmp(componentName, "OMX.TI.Video.Decoder")) {
+        LOGW("Using TIHardwareRenderer.");
+        impl =
+            new TIHardwareRenderer(
+                    surface,
+                    displayWidth, displayHeight,
+                    encodedWidth, encodedHeight);
+    } else {
+        LOGW("Using software renderer.");
+        impl = new SoftwareRenderer(
+                surface,
+                displayWidth, displayHeight,
+                encodedWidth, encodedHeight);
+    }
+
+    return new OMXRenderer(impl);
+}
+
+OMXRenderer::OMXRenderer(VideoRenderer *impl)
+    : mImpl(impl) {
+}
+
+OMXRenderer::~OMXRenderer() {
+    delete mImpl;
+    mImpl = NULL;
+}
+
+void OMXRenderer::render(IOMX::buffer_id buffer) {
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+
+    mImpl->render(
+            header->pBuffer + header->nOffset,
+            header->nFilledLen,
+            header->pPlatformPrivate);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/omx/OMX.h
index ed4e5dd..20430bb 100644
--- a/media/libstagefright/omx/OMX.h
+++ b/media/libstagefright/omx/OMX.h
@@ -79,6 +79,13 @@
             OMX_U32 flags, OMX_TICKS timestamp);
 #endif
 
+    virtual sp<IOMXRenderer> createRenderer(
+            const sp<ISurface> &surface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight);
+
 private:
     static OMX_CALLBACKTYPE kCallbacks;
 
diff --git a/media/libstagefright/omx/OMXRenderer.h b/media/libstagefright/omx/OMXRenderer.h
new file mode 100644
index 0000000..4d194ce
--- /dev/null
+++ b/media/libstagefright/omx/OMXRenderer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OMX_RENDERER_H_
+
+#define OMX_RENDERER_H_
+
+#include <media/IOMX.h>
+
+namespace android {
+
+class VideoRenderer;
+
+class OMXRenderer : public BnOMXRenderer {
+public:
+    // Assumes ownership of "impl".
+    OMXRenderer(VideoRenderer *impl);
+    virtual ~OMXRenderer();
+
+    virtual void render(IOMX::buffer_id buffer);
+
+private:
+    VideoRenderer *mImpl;
+
+    OMXRenderer(const OMXRenderer &);
+    OMXRenderer &operator=(const OMXRenderer &);
+};
+
+}  // namespace android
+
+#endif  // OMX_RENDERER_H_
diff --git a/media/libstagefright/QComHardwareRenderer.cpp b/media/libstagefright/omx/QComHardwareRenderer.cpp
similarity index 100%
rename from media/libstagefright/QComHardwareRenderer.cpp
rename to media/libstagefright/omx/QComHardwareRenderer.cpp
diff --git a/media/libstagefright/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
similarity index 96%
rename from media/libstagefright/SoftwareRenderer.cpp
rename to media/libstagefright/omx/SoftwareRenderer.cpp
index 66b6b07..5483238 100644
--- a/media/libstagefright/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -61,6 +61,10 @@
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+    }
     assert(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
 
     static const signed kClipMin = -278;
diff --git a/media/libstagefright/TIHardwareRenderer.cpp b/media/libstagefright/omx/TIHardwareRenderer.cpp
similarity index 100%
rename from media/libstagefright/TIHardwareRenderer.cpp
rename to media/libstagefright/omx/TIHardwareRenderer.cpp