Bug 3438258 Add SurfaceTexture as MediaPlayer sink

This change enables the use of a SurfaceTexture in place of a Surface
as the video sink for an android.media.MediaPlayer. The new API
MediaPlayer.setTexture is currently hidden.

This includes:
 - New Java and C++ interfaces
 - C++ plumbing and implementation (JNI, Binder)
 - Stagefright AwesomePlayer and NuPlayer use ANativeWindow
   (either Surface or SurfaceTextureClient)

Change-Id: I2b568bee143d9eaf3dfc6cc4533c1bebbd5afc51
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index bba7ed7..70519ef 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -26,6 +26,7 @@
 class Parcel;
 class ISurface;
 class Surface;
+class ISurfaceTexture;
 
 class IMediaPlayer: public IInterface
 {
@@ -35,6 +36,8 @@
     virtual void            disconnect() = 0;
 
     virtual status_t        setVideoSurface(const sp<Surface>& surface) = 0;
+    virtual status_t        setVideoSurfaceTexture(
+                                    const sp<ISurfaceTexture>& surfaceTexture) = 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 048f041..117d7eb 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -34,6 +34,7 @@
 class Parcel;
 class ISurface;
 class Surface;
+class ISurfaceTexture;
 
 template<typename T> class SortedVector;
 
@@ -112,7 +113,13 @@
         return INVALID_OPERATION;
     }
 
+    // pass the buffered Surface to the media player service
     virtual status_t    setVideoSurface(const sp<Surface>& surface) = 0;
+
+    // pass the buffered ISurfaceTexture to the media player service
+    virtual status_t    setVideoSurfaceTexture(
+                                const sp<ISurfaceTexture>& surfaceTexture) = 0;
+
     virtual status_t    prepare() = 0;
     virtual status_t    prepareAsync() = 0;
     virtual status_t    start() = 0;
@@ -177,7 +184,7 @@
     sp<AudioSink>       mAudioSink;
 };
 
-// Implement this class for media players that output directo to hardware
+// Implement this class for media players that output audio directly to hardware
 class MediaPlayerHWInterface : public MediaPlayerBase
 {
 public:
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 88b0c3e..528eeb9 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -28,6 +28,7 @@
 namespace android {
 
 class Surface;
+class ISurfaceTexture;
 
 enum media_event_type {
     MEDIA_NOP               = 0, // interface test message
@@ -146,6 +147,8 @@
 
             status_t        setDataSource(int fd, int64_t offset, int64_t length);
             status_t        setVideoSurface(const sp<Surface>& surface);
+            status_t        setVideoSurfaceTexture(
+                                    const sp<ISurfaceTexture>& surfaceTexture);
             status_t        setListener(const sp<MediaPlayerListener>& listener);
             status_t        prepare();
             status_t        prepareAsync();
diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h
new file mode 100644
index 0000000..f323cbc
--- /dev/null
+++ b/include/media/stagefright/NativeWindowWrapper.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 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 NATIVE_WINDOW_WRAPPER_H_
+
+#define NATIVE_WINDOW_WRAPPER_H_
+
+#include <surfaceflinger/Surface.h>
+#include <gui/SurfaceTextureClient.h>
+
+namespace android {
+
+// Both Surface and SurfaceTextureClient are RefBase that implement the
+// ANativeWindow interface, but at different addresses. ANativeWindow is not
+// a RefBase but acts like one for use with sp<>.  This wrapper converts a
+// Surface or SurfaceTextureClient into a single reference-counted object
+// that holds an sp reference to the underlying Surface or SurfaceTextureClient,
+// It provides a method to get the ANativeWindow.
+
+struct NativeWindowWrapper : RefBase {
+    NativeWindowWrapper(
+            const sp<Surface> &surface) :
+        mSurface(surface) { }
+
+    NativeWindowWrapper(
+            const sp<SurfaceTextureClient> &surfaceTextureClient) :
+        mSurfaceTextureClient(surfaceTextureClient) { }
+
+    sp<ANativeWindow> getNativeWindow() const {
+        if (mSurface != NULL) {
+            return mSurface;
+        } else {
+            return mSurfaceTextureClient;
+        }
+    }
+
+    // If needed later we can provide a method to ask what kind of native window
+
+private:
+    // At most one of mSurface and mSurfaceTextureClient will be non-NULL
+    const sp<Surface> mSurface;
+    const sp<SurfaceTextureClient> mSurfaceTextureClient;
+
+    DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper);
+};
+
+}  // namespace android
+
+#endif  // NATIVE_WINDOW_WRAPPER_H_
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 74fb531..fd4c6c6 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -37,7 +37,8 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
-        libsurfaceflinger_client libcamera_client libstagefright_foundation
+        libsurfaceflinger_client libcamera_client libstagefright_foundation \
+        libgui
 
 LOCAL_MODULE:= libmedia
 
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index c287c0a..2399216 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -23,6 +23,7 @@
 #include <media/IMediaPlayer.h>
 #include <surfaceflinger/ISurface.h>
 #include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -45,7 +46,8 @@
     SET_METADATA_FILTER,
     GET_METADATA,
     SET_AUX_EFFECT_SEND_LEVEL,
-    ATTACH_AUX_EFFECT
+    ATTACH_AUX_EFFECT,
+    SET_VIDEO_SURFACETEXTURE,
 };
 
 class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -64,6 +66,7 @@
         remote()->transact(DISCONNECT, data, &reply);
     }
 
+    // pass the buffered Surface to the media player service
     status_t setVideoSurface(const sp<Surface>& surface)
     {
         Parcel data, reply;
@@ -73,6 +76,17 @@
         return reply.readInt32();
     }
 
+    // pass the buffered ISurfaceTexture to the media player service
+    status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        sp<IBinder> b(surfaceTexture->asBinder());
+        data.writeStrongBinder(b);
+        remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t prepareAsync()
     {
         Parcel data, reply;
@@ -220,6 +234,7 @@
         remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
         return reply.readInt32();
     }
+
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -241,6 +256,13 @@
             reply->writeInt32(setVideoSurface(surface));
             return NO_ERROR;
         } break;
+        case SET_VIDEO_SURFACETEXTURE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            sp<ISurfaceTexture> surfaceTexture =
+                    interface_cast<ISurfaceTexture>(data.readStrongBinder());
+            reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
+            return NO_ERROR;
+        } break;
         case PREPARE_ASYNC: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             reply->writeInt32(prepareAsync());
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 87c8fe4..0ee0249 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -201,6 +201,16 @@
     return mPlayer->setVideoSurface(surface);
 }
 
+status_t MediaPlayer::setVideoSurfaceTexture(
+        const sp<ISurfaceTexture>& surfaceTexture)
+{
+    LOGV("setVideoSurfaceTexture");
+    Mutex::Autolock _l(mLock);
+    if (mPlayer == 0) return NO_INIT;
+
+    return mPlayer->setVideoSurfaceTexture(surfaceTexture);
+}
+
 // must call with lock held
 status_t MediaPlayer::prepareAsync_l()
 {
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f7f0d95..e65f6d8 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -32,7 +32,8 @@
 	libstagefright        			\
 	libstagefright_omx    			\
 	libstagefright_foundation               \
-	libsurfaceflinger_client
+	libsurfaceflinger_client                \
+	libgui
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_rtsp                     \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8c6f76b..ec6188f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -935,6 +935,15 @@
     return p->setVideoSurface(surface);
 }
 
+status_t MediaPlayerService::Client::setVideoSurfaceTexture(
+        const sp<ISurfaceTexture>& surfaceTexture)
+{
+    LOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get());
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->setVideoSurfaceTexture(surfaceTexture);
+}
+
 status_t MediaPlayerService::Client::invoke(const Parcel& request,
                                             Parcel *reply)
 {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 9f41db0..1175ed0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -236,6 +236,8 @@
         // IMediaPlayer interface
         virtual void            disconnect();
         virtual status_t        setVideoSurface(const sp<Surface>& surface);
+        virtual status_t        setVideoSurfaceTexture(
+                                        const sp<ISurfaceTexture>& surfaceTexture);
         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 aa8f3f0..a98231c 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -36,6 +36,9 @@
 
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
     virtual status_t    setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; }
+    virtual status_t    setVideoSurfaceTexture(
+                                const sp<ISurfaceTexture>& surfaceTexture)
+                            { 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 da564dc..fdb4754 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -55,6 +55,14 @@
     return OK;
 }
 
+status_t StagefrightPlayer::setVideoSurfaceTexture(
+        const sp<ISurfaceTexture> &surfaceTexture) {
+    LOGV("setVideoSurfaceTexture");
+
+    mPlayer->setSurfaceTexture(surfaceTexture);
+    return OK;
+}
+
 status_t StagefrightPlayer::prepare() {
     return mPlayer->prepare();
 }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index fc72bfb..e2796d2 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -39,6 +39,8 @@
     virtual status_t setDataSource(const sp<IStreamSource> &source);
 
     virtual status_t setVideoSurface(const sp<Surface> &surface);
+    virtual status_t setVideoSurfaceTexture(
+            const sp<ISurfaceTexture> &surfaceTexture);
     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 6abd8e3..d9c3db3 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -78,6 +78,10 @@
     virtual status_t setVideoSurface(const android::sp<android::Surface>& s)  {
         return mPlayer->setVideoSurface(s);
     }
+    virtual status_t setVideoSurfaceTexture(
+            const android::sp<android::ISurfaceTexture>& st)  {
+        return mPlayer->setVideoSurfaceTexture(st);
+    }
     virtual status_t prepare() {return mPlayer->prepare();}
     virtual status_t prepareAsync()  {return mPlayer->prepareAsync();}
     virtual status_t start()  {return mPlayer->start();}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 1fcf92b..48b517e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -37,6 +37,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -76,8 +77,16 @@
 }
 
 void NuPlayer::setVideoSurface(const sp<Surface> &surface) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, id());
-    msg->setObject("surface", surface);
+    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
+    msg->setObject("native-window", new NativeWindowWrapper(surface));
+    msg->post();
+}
+
+void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
+    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
+    sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
+                new SurfaceTextureClient(surfaceTexture) : NULL);
+    msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient));
     msg->post();
 }
 
@@ -144,14 +153,14 @@
             break;
         }
 
-        case kWhatSetVideoSurface:
+        case kWhatSetVideoNativeWindow:
         {
-            LOGV("kWhatSetVideoSurface");
+            LOGV("kWhatSetVideoNativeWindow");
 
             sp<RefBase> obj;
-            CHECK(msg->findObject("surface", &obj));
+            CHECK(msg->findObject("native-window", &obj));
 
-            mSurface = static_cast<Surface *>(obj.get());
+            mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
             break;
         }
 
@@ -529,7 +538,8 @@
         new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
                      id());
 
-    *decoder = new Decoder(notify, audio ? NULL : mSurface);
+    *decoder = audio ? new Decoder(notify) :
+                       new Decoder(notify, mNativeWindow);
     looper()->registerHandler(*decoder);
 
     (*decoder)->configure(meta);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index bb65162..e7c6a42 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -20,6 +20,9 @@
 
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+#include <gui/SurfaceTextureClient.h>
+#include <surfaceflinger/Surface.h>
 
 namespace android {
 
@@ -38,6 +41,7 @@
             const char *url, const KeyedVector<String8, String8> *headers);
 
     void setVideoSurface(const sp<Surface> &surface);
+    void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
     void start();
 
@@ -65,7 +69,7 @@
 
     enum {
         kWhatSetDataSource,
-        kWhatSetVideoSurface,
+        kWhatSetVideoNativeWindow,
         kWhatSetAudioSink,
         kWhatMoreDataQueued,
         kWhatStart,
@@ -81,7 +85,7 @@
 
     wp<NuPlayerDriver> mDriver;
     sp<Source> mSource;
-    sp<Surface> mSurface;
+    sp<NativeWindowWrapper> mNativeWindow;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
     sp<Decoder> mVideoDecoder;
     sp<Decoder> mAudioDecoder;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 761dfa4..517acc9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -31,13 +31,15 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
 #include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
 NuPlayer::Decoder::Decoder(
-        const sp<AMessage> &notify, const sp<Surface> &surface)
+        const sp<AMessage> &notify,
+        const sp<NativeWindowWrapper> &nativeWindow)
     : mNotify(notify),
-      mSurface(surface) {
+      mNativeWindow(nativeWindow) {
 }
 
 NuPlayer::Decoder::~Decoder() {
@@ -55,8 +57,8 @@
 
     sp<AMessage> format = makeFormat(meta);
 
-    if (mSurface != NULL) {
-        format->setObject("surface", mSurface);
+    if (mNativeWindow != NULL) {
+        format->setObject("native-window", mNativeWindow);
     }
 
     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 3874cfe..732f090 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -28,7 +28,8 @@
 struct DecoderWrapper;
 
 struct NuPlayer::Decoder : public AHandler {
-    Decoder(const sp<AMessage> &notify, const sp<Surface> &surface = NULL);
+    Decoder(const sp<AMessage> &notify,
+            const sp<NativeWindowWrapper> &nativeWindow = NULL);
 
     void configure(const sp<MetaData> &meta);
 
@@ -47,7 +48,7 @@
     };
 
     sp<AMessage> mNotify;
-    sp<Surface> mSurface;
+    sp<NativeWindowWrapper> mNativeWindow;
 
     sp<ACodec> mCodec;
     sp<DecoderWrapper> mWrapper;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ac19a2f..0eca958 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -86,6 +86,13 @@
     return OK;
 }
 
+status_t NuPlayerDriver::setVideoSurfaceTexture(
+        const sp<ISurfaceTexture> &surfaceTexture) {
+    mPlayer->setVideoSurfaceTexture(surfaceTexture);
+
+    return OK;
+}
+
 status_t NuPlayerDriver::prepare() {
     return OK;
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index e3a5de4..67d0f3e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -36,6 +36,8 @@
     virtual status_t setDataSource(const sp<IStreamSource> &source);
 
     virtual status_t setVideoSurface(const sp<Surface> &surface);
+    virtual status_t setVideoSurfaceTexture(
+            const sp<ISurfaceTexture> &surfaceTexture);
     virtual status_t prepare();
     virtual status_t prepareAsync();
     virtual status_t start();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 505d9d4..b0ae3d8 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -11,9 +11,11 @@
 #include <media/stagefright/foundation/AMessage.h>
 
 #include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/NativeWindowWrapper.h>
 #include <media/stagefright/OMXClient.h>
 
 #include <surfaceflinger/Surface.h>
+#include <gui/SurfaceTextureClient.h>
 
 #include <OMX_Component.h>
 
@@ -1633,8 +1635,11 @@
     mCodec->configureCodec(mime.c_str(), msg);
 
     sp<RefBase> obj;
-    if (msg->findObject("surface", &obj)) {
-        mCodec->mNativeWindow = static_cast<Surface *>(obj.get());
+    if (msg->findObject("native-window", &obj)) {
+        sp<NativeWindowWrapper> nativeWindow(
+                static_cast<NativeWindowWrapper *>(obj.get()));
+        CHECK(nativeWindow != NULL);
+        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
     }
 
     CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 80eb59f..88069e9 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -74,7 +74,8 @@
         libcamera_client \
         libdrmframework  \
         libcrypto        \
-        libssl
+        libssl           \
+        libgui
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_color_conversion \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 1b63ab2..36623f6 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -43,6 +43,8 @@
 #include <media/stagefright/OMXCodec.h>
 
 #include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
 
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -83,8 +85,8 @@
 
 struct AwesomeLocalRenderer : public AwesomeRenderer {
     AwesomeLocalRenderer(
-            const sp<Surface> &surface, const sp<MetaData> &meta)
-        : mTarget(new SoftwareRenderer(surface, meta)) {
+            const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
+        : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
     }
 
     virtual void render(MediaBuffer *buffer) {
@@ -889,7 +891,7 @@
 }
 
 void AwesomePlayer::initRenderer_l() {
-    if (mSurface == NULL) {
+    if (mNativeWindow == NULL) {
         return;
     }
 
@@ -920,13 +922,13 @@
         // directly to ANativeBuffers, so we must use a renderer that
         // just pushes those buffers to the ANativeWindow.
         mVideoRenderer =
-            new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
+            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
     } else {
         // Other decoders are instantiated locally and as a consequence
         // allocate their buffers in local address space.  This renderer
         // then performs a color conversion and copy to get the data
         // into the ANativeBuffer.
-        mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta);
+        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
     }
 }
 
@@ -986,6 +988,17 @@
     Mutex::Autolock autoLock(mLock);
 
     mSurface = surface;
+    mNativeWindow = surface;
+}
+
+void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
+    Mutex::Autolock autoLock(mLock);
+
+    mSurface.clear();
+    if (surfaceTexture != NULL) {
+        mNativeWindow = new SurfaceTextureClient(surfaceTexture);
+    }
+
 }
 
 void AwesomePlayer::setAudioSink(
@@ -1164,7 +1177,7 @@
             mClient.interface(), mVideoTrack->getFormat(),
             false, // createEncoder
             mVideoTrack,
-            NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL);
+            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
 
     if (mVideoSource != NULL) {
         int64_t durationUs;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 70408d7..31afc43 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -26,14 +26,15 @@
 #include <surfaceflinger/Surface.h>
 #include <ui/android_native_buffer.h>
 #include <ui/GraphicBufferMapper.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
 SoftwareRenderer::SoftwareRenderer(
-        const sp<Surface> &surface, const sp<MetaData> &meta)
+        const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
     : mConverter(NULL),
       mYUVMode(None),
-      mSurface(surface) {
+      mNativeWindow(nativeWindow) {
     int32_t tmp;
     CHECK(meta->findInt32(kKeyColorFormat, &tmp));
     mColorFormat = (OMX_COLOR_FORMATTYPE)tmp;
@@ -65,22 +66,22 @@
             break;
     }
 
-    CHECK(mSurface.get() != NULL);
+    CHECK(mNativeWindow != NULL);
     CHECK(mWidth > 0);
     CHECK(mHeight > 0);
     CHECK(mConverter == NULL || mConverter->isValid());
 
     CHECK_EQ(0,
             native_window_set_usage(
-            mSurface.get(),
+            mNativeWindow.get(),
             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
             | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
 
-    CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2));
+    CHECK_EQ(0, native_window_set_buffer_count(mNativeWindow.get(), 2));
 
     // Width must be multiple of 32???
     CHECK_EQ(0, native_window_set_buffers_geometry(
-                mSurface.get(),
+                mNativeWindow.get(),
                 mCropRight - mCropLeft + 1,
                 mCropBottom - mCropTop + 1,
                 halFormat));
@@ -96,7 +97,7 @@
 
     if (transform) {
         CHECK_EQ(0, native_window_set_buffers_transform(
-                    mSurface.get(), transform));
+                    mNativeWindow.get(), transform));
     }
 }
 
@@ -109,12 +110,12 @@
         const void *data, size_t size, void *platformPrivate) {
     android_native_buffer_t *buf;
     int err;
-    if ((err = mSurface->dequeueBuffer(mSurface.get(), &buf)) != 0) {
+    if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) {
         LOGW("Surface::dequeueBuffer returned error %d", err);
         return;
     }
 
-    CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
+    CHECK_EQ(0, mNativeWindow->lockBuffer(mNativeWindow.get(), buf));
 
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
@@ -140,7 +141,7 @@
 
     CHECK_EQ(0, mapper.unlock(buf->handle));
 
-    if ((err = mSurface->queueBuffer(mSurface.get(), buf)) != 0) {
+    if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf)) != 0) {
         LOGW("Surface::queueBuffer returned error %d", err);
     }
     buf = NULL;
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 1497732..0e36492 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -36,6 +36,7 @@
 struct MediaExtractor;
 struct MediaSource;
 struct NuCachedSource2;
+struct ISurfaceTexture;
 
 struct ALooper;
 struct ARTSPController;
@@ -80,6 +81,7 @@
     bool isPlaying() const;
 
     void setSurface(const sp<Surface> &surface);
+    void setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
     status_t setLooping(bool shouldLoop);
 
@@ -133,6 +135,7 @@
     wp<MediaPlayerBase> mListener;
 
     sp<Surface> mSurface;
+    sp<ANativeWindow> mNativeWindow;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
     SystemTimeSource mSystemTimeSource;
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 90d3fe1..78037b9 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -20,16 +20,16 @@
 
 #include <media/stagefright/ColorConverter.h>
 #include <utils/RefBase.h>
+#include <ui/android_native_buffer.h>
 
 namespace android {
 
 struct MetaData;
-class Surface;
 
 class SoftwareRenderer {
 public:
     SoftwareRenderer(
-            const sp<Surface> &surface, const sp<MetaData> &meta);
+            const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta);
 
     ~SoftwareRenderer();
 
@@ -44,7 +44,7 @@
     OMX_COLOR_FORMATTYPE mColorFormat;
     ColorConverter *mConverter;
     YUVMode mYUVMode;
-    sp<Surface> mSurface;
+    sp<ANativeWindow> mNativeWindow;
     int32_t mWidth, mHeight;
     int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;