IOMX: consolidate createInputSurface APIs

- Create GraphicBufferSource in IOMX regardless of persistency.

- Remove createInputSurface on IOMXNode, only keep setInputSurface
  which accepts either a persistent or non-persistent surface.

- Instead of holding a IGraphicBufferConsumer, hold
  IGraphicBufferSource across session as the persistent surface.

- Fix up GraphicBufferSource to allow usage across sessions.
  GraphicBufferSource itself becomes agnostic to persistency.

- Remove max encoder input buffers profiling code.

bug: 31399200
Change-Id: I15ed52cc64509fd87736372a580abf7b51bf4de7
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 68a65f0..3e05532 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -28,8 +28,8 @@
 }
 class ICameraRecordingProxy;
 class IMediaRecorderClient;
-class IGraphicBufferConsumer;
 class IGraphicBufferProducer;
+struct PersistentSurface;
 
 class IMediaRecorder: public IInterface
 {
@@ -60,7 +60,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
 };
 
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index ef01688..311119b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,8 +19,6 @@
 #define ANDROID_IOMX_H_
 
 #include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/List.h>
 #include <utils/String8.h>
@@ -34,8 +32,10 @@
 
 namespace android {
 
+class IGraphicBufferProducer;
 class IGraphicBufferSource;
 class IMemory;
+class IOMXBufferSource;
 class IOMXNode;
 class IOMXObserver;
 class NativeHandle;
@@ -61,9 +61,9 @@
             const char *name, const sp<IOMXObserver> &observer,
             sp<IOMXNode> *omxNode) = 0;
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
+            sp<IGraphicBufferSource> *bufferSource) = 0;
 };
 
 class IOMXNode : public IInterface {
@@ -125,21 +125,8 @@
             OMX_U32 port_index,
             const sp<NativeHandle> &nativeHandle, buffer_id buffer) = 0;
 
-    // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
-    // well as on success.
-    virtual status_t createInputSurface(
-            OMX_U32 port_index, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type = NULL) = 0;
-
-    // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
-    // well as on success.
     virtual status_t setInputSurface(
-            OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) = 0;
+            const sp<IOMXBufferSource> &bufferSource) = 0;
 
     // Allocate an opaque buffer as a native handle. If component supports returning native
     // handles, those are returned in *native_handle. Otherwise, the allocated buffer is
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5195993..59dfd18 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -25,9 +25,8 @@
 namespace android {
 
 class ICameraRecordingProxy;
-class Surface;
-class IGraphicBufferConsumer;
 class IGraphicBufferProducer;
+struct PersistentSurface;
 
 struct MediaRecorderBase {
     MediaRecorderBase(const String16 &opPackageName)
@@ -59,7 +58,7 @@
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
     virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
 
 
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 92a5593..13f82f0 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -36,6 +36,7 @@
 
 class MediaCodecBuffer;
 struct PersistentSurface;
+class Surface;
 
 struct CodecBase : public AHandler, /* static */ ColorUtils {
     enum {
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 18b1955..f9a46a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -21,8 +21,7 @@
 #include <media/stagefright/foundation/AHandlerReflector.h>
 #include <media/stagefright/foundation/Mutexed.h>
 #include <media/stagefright/MediaSource.h>
-
-#include <gui/IGraphicBufferConsumer.h>
+#include <media/stagefright/PersistentSurface.h>
 
 namespace android {
 
@@ -44,7 +43,7 @@
             const sp<ALooper> &looper,
             const sp<AMessage> &format,
             const sp<MediaSource> &source,
-            const sp<IGraphicBufferConsumer> &consumer = NULL,
+            const sp<PersistentSurface> &persistentSurface = NULL,
             uint32_t flags = 0);
 
     bool isVideo() const { return mIsVideo; }
@@ -88,7 +87,7 @@
             const sp<ALooper> &looper,
             const sp<AMessage> &outputFormat,
             const sp<MediaSource> &source,
-            const sp<IGraphicBufferConsumer> &consumer,
+            const sp<PersistentSurface> &persistentSurface,
             uint32_t flags = 0);
 
     status_t onStart(MetaData *params);
@@ -121,7 +120,7 @@
     int32_t mEncoderDataSpace;
     sp<AMessage> mEncoderActivityNotify;
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
-    sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
+    sp<PersistentSurface> mPersistentSurface;
     List<MediaBuffer *> mInputBufferQueue;
     List<size_t> mAvailEncoderInputIndices;
     List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/PersistentSurface.h b/include/media/stagefright/PersistentSurface.h
index a35b9f1..d8b75a2 100644
--- a/include/media/stagefright/PersistentSurface.h
+++ b/include/media/stagefright/PersistentSurface.h
@@ -19,29 +19,46 @@
 #define PERSISTENT_SURFACE_H_
 
 #include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
+#include <android/IGraphicBufferSource.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <binder/Parcel.h>
 
 namespace android {
 
 struct PersistentSurface : public RefBase {
+    PersistentSurface() {}
+
     PersistentSurface(
             const sp<IGraphicBufferProducer>& bufferProducer,
-            const sp<IGraphicBufferConsumer>& bufferConsumer) :
+            const sp<IGraphicBufferSource>& bufferSource) :
         mBufferProducer(bufferProducer),
-        mBufferConsumer(bufferConsumer) { }
+        mBufferSource(bufferSource) { }
 
     sp<IGraphicBufferProducer> getBufferProducer() const {
         return mBufferProducer;
     }
 
-    sp<IGraphicBufferConsumer> getBufferConsumer() const {
-        return mBufferConsumer;
+    sp<IGraphicBufferSource> getBufferSource() const {
+        return mBufferSource;
+    }
+
+    status_t writeToParcel(Parcel *parcel) const {
+        parcel->writeStrongBinder(IInterface::asBinder(mBufferProducer));
+        parcel->writeStrongBinder(IInterface::asBinder(mBufferSource));
+        return NO_ERROR;
+    }
+
+    status_t readFromParcel(const Parcel *parcel) {
+        mBufferProducer = interface_cast<IGraphicBufferProducer>(
+                parcel->readStrongBinder());
+        mBufferSource = interface_cast<IGraphicBufferSource>(
+                parcel->readStrongBinder());
+        return NO_ERROR;
     }
 
 private:
-    const sp<IGraphicBufferProducer> mBufferProducer;
-    const sp<IGraphicBufferConsumer> mBufferConsumer;
+    sp<IGraphicBufferProducer> mBufferProducer;
+    sp<IGraphicBufferSource> mBufferSource;
 
     DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface);
 };
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 08b3af0..0b1bb2b 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -93,9 +93,14 @@
     $(TOP)/frameworks/native/include/media/openmax \
     $(TOP)/frameworks/av/include/media/ \
     $(TOP)/frameworks/av/media/libstagefright \
+    $(TOP)/frameworks/av/media/libmedia/aidl \
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
 
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    frameworks/av/include/media \
+    frameworks/av/media/libmedia/aidl
+
 LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
 LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
 
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a6860e2..5599830 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -29,6 +29,7 @@
 #include <media/IMediaRecorder.h>
 #include <gui/Surface.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <media/stagefright/PersistentSurface.h>
 
 namespace android {
 
@@ -79,12 +80,12 @@
         return reply.readInt32();
     }
 
-    status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+    status_t setInputSurface(const sp<PersistentSurface>& surface)
     {
         ALOGV("setInputSurface(%p)", surface.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(surface));
+        surface->writeToParcel(&data);
         remote()->transact(SET_INPUT_SURFACE, data, &reply);
         return reply.readInt32();
     }
@@ -490,8 +491,8 @@
         case SET_INPUT_SURFACE: {
             ALOGV("SET_INPUT_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
-                    data.readStrongBinder());
+            sp<PersistentSurface> surface = new PersistentSurface();
+            surface->readFromParcel(&data);
             reply->writeInt32(setInputSurface(surface));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 9360777..1901d8c 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -27,7 +27,9 @@
 #include <media/openmax/OMX_IndexExt.h>
 #include <utils/NativeHandle.h>
 
+#include <gui/IGraphicBufferProducer.h>
 #include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
 
 namespace android {
 
@@ -45,7 +47,6 @@
     USE_BUFFER,
     USE_GRAPHIC_BUFFER,
     CREATE_INPUT_SURFACE,
-    CREATE_PERSISTENT_INPUT_SURFACE,
     SET_INPUT_SURFACE,
     STORE_META_DATA_IN_BUFFERS,
     PREPARE_FOR_ADAPTIVE_PLAYBACK,
@@ -111,13 +112,13 @@
         return err;
     }
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer) {
+            sp<IGraphicBufferSource> *bufferSource) {
         Parcel data, reply;
         status_t err;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
+        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
         if (err != OK) {
             ALOGW("binder transaction failed: %d", err);
             return err;
@@ -130,7 +131,7 @@
 
         *bufferProducer = IGraphicBufferProducer::asInterface(
                 reply.readStrongBinder());
-        *bufferConsumer = IGraphicBufferConsumer::asInterface(
+        *bufferSource = IGraphicBufferSource::asInterface(
                 reply.readStrongBinder());
 
         return err;
@@ -328,72 +329,21 @@
         return err;
     }
 
-    virtual status_t createInputSurface(
-            OMX_U32 port_index, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) {
-        Parcel data, reply;
-        status_t err;
-        data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        data.writeInt32(port_index);
-        data.writeInt32(dataSpace);
-        err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
-        if (err != OK) {
-            ALOGW("binder transaction failed: %d", err);
-            return err;
-        }
-
-        // read type even if createInputSurface failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
-        err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        *bufferProducer = IGraphicBufferProducer::asInterface(
-                reply.readStrongBinder());
-        *bufferSource = IGraphicBufferSource::asInterface(
-                reply.readStrongBinder());
-
-        return err;
-    }
-
     virtual status_t setInputSurface(
-            OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type) {
+            const sp<IOMXBufferSource> &bufferSource) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
-        status_t err;
-        data.writeInt32(port_index);
-        data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
 
-        err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
+        data.writeStrongBinder(IInterface::asBinder(bufferSource));
+
+        status_t err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
 
         if (err != OK) {
             ALOGW("binder transaction failed: %d", err);
             return err;
         }
 
-        // read type even if setInputSurface failed
-        int negotiatedType = reply.readInt32();
-        if (type != NULL) {
-            *type = (MetadataBufferType)negotiatedType;
-        }
-
         err = reply.readInt32();
-        if (err != OK) {
-            return err;
-        }
-
-        *bufferSource = IGraphicBufferSource::asInterface(
-                reply.readStrongBinder());
 
         return err;
     }
@@ -651,20 +601,19 @@
             return NO_ERROR;
         }
 
-        case CREATE_PERSISTENT_INPUT_SURFACE:
+        case CREATE_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
 
             sp<IGraphicBufferProducer> bufferProducer;
-            sp<IGraphicBufferConsumer> bufferConsumer;
-            status_t err = createPersistentInputSurface(
-                    &bufferProducer, &bufferConsumer);
+            sp<IGraphicBufferSource> bufferSource;
+            status_t err = createInputSurface(&bufferProducer, &bufferSource);
 
             reply->writeInt32(err);
 
             if (err == OK) {
                 reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
-                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
+                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
             }
 
             return NO_ERROR;
@@ -897,62 +846,16 @@
             return NO_ERROR;
         }
 
-        case CREATE_INPUT_SURFACE:
-        {
-            CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
-            OMX_U32 port_index = data.readInt32();
-            android_dataspace dataSpace = (android_dataspace)data.readInt32();
-
-            sp<IGraphicBufferProducer> bufferProducer;
-            sp<IGraphicBufferSource> bufferSource;
-            MetadataBufferType type = kMetadataBufferTypeInvalid;
-            status_t err = createInputSurface(
-                    port_index, dataSpace, &bufferProducer, &bufferSource, &type);
-
-            if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
-                android_errorWriteLog(0x534e4554, "26324358");
-            }
-
-            reply->writeInt32(type);
-            reply->writeInt32(err);
-
-            if (err == OK) {
-                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
-                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
-            }
-
-            return NO_ERROR;
-        }
-
         case SET_INPUT_SURFACE:
         {
             CHECK_OMX_INTERFACE(IOMXNode, data, reply);
 
-            OMX_U32 port_index = data.readInt32();
+            sp<IOMXBufferSource> bufferSource =
+                    interface_cast<IOMXBufferSource>(data.readStrongBinder());
 
-            sp<IGraphicBufferConsumer> bufferConsumer =
-                    interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
-
-            sp<IGraphicBufferSource> bufferSource;
-            MetadataBufferType type = kMetadataBufferTypeInvalid;
-
-            status_t err = INVALID_OPERATION;
-            if (bufferConsumer == NULL) {
-                ALOGE("b/26392700");
-            } else {
-                err = setInputSurface(port_index, bufferConsumer, &bufferSource, &type);
-
-                if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
-                   android_errorWriteLog(0x534e4554, "26324358");
-                }
-            }
-
-            reply->writeInt32(type);
+            status_t err = setInputSurface(bufferSource);
             reply->writeInt32(err);
-            if (err == OK) {
-                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
-            }
+
             return NO_ERROR;
         }
 
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
index adbb75f..e9bf739 100644
--- a/media/libmedia/aidl/android/IGraphicBufferSource.aidl
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -16,12 +16,15 @@
 
 package android;
 
+import android.IOMXNode;
+
 /**
  * Binder interface for controlling a graphic buffer source.
  *
  * @hide
  */
 interface IGraphicBufferSource {
+    void configure(IOMXNode omxNode, int dataSpace);
     void setSuspend(boolean suspend);
     void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
     void setMaxTimestampGapUs(long maxGapUs);
diff --git a/media/libmedia/aidl/android/IOMXNode.aidl b/media/libmedia/aidl/android/IOMXNode.aidl
new file mode 100644
index 0000000..ec87fd2
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android;
+
+/** @hide */
+interface IOMXNode {
+    // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IOMXNode.h b/media/libmedia/aidl/android/IOMXNode.h
new file mode 100644
index 0000000..7b17614
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#include <media/IOMX.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 59c077a..6eb208c 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -361,7 +361,7 @@
         return INVALID_OPERATION;
     }
 
-    return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
+    return mMediaRecorder->setInputSurface(surface);
 }
 
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d011d70..94ceae4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -52,7 +52,7 @@
     return ok;
 }
 
-status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<PersistentSurface>& surface)
 {
     ALOGV("setInputSurface");
     Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index eceb653..12656cf 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,7 +25,6 @@
 class MediaRecorderBase;
 class MediaPlayerService;
 class ICameraRecordingProxy;
-class IGraphicBufferProducer;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
@@ -73,7 +72,7 @@
     virtual     status_t   close();
     virtual     status_t   release();
     virtual     status_t   dump(int fd, const Vector<String16>& args);
-    virtual     status_t   setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual     status_t   setInputSurface(const sp<PersistentSurface>& surface);
     virtual     sp<IGraphicBufferProducer> querySurfaceMediaSource();
 
 private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a748b46..279bc86 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -45,6 +45,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaCodecSource.h>
+#include <media/stagefright/PersistentSurface.h>
 #include <media/MediaProfiles.h>
 #include <camera/CameraParameters.h>
 
@@ -248,7 +249,7 @@
 }
 
 status_t StagefrightRecorder::setInputSurface(
-        const sp<IGraphicBufferConsumer>& surface) {
+        const sp<PersistentSurface>& surface) {
     mPersistentSurface = surface;
 
     return OK;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 4dbd039..4c2e65c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -38,9 +38,6 @@
 class MetaData;
 struct AudioSource;
 class MediaProfiles;
-class IGraphicBufferConsumer;
-class IGraphicBufferProducer;
-class SurfaceMediaSource;
 struct ALooper;
 
 struct StagefrightRecorder : public MediaRecorderBase {
@@ -57,7 +54,7 @@
     virtual status_t setVideoFrameRate(int frames_per_second);
     virtual status_t setCamera(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
-    virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+    virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8 &params);
     virtual status_t setListener(const sp<IMediaRecorderClient> &listener);
@@ -78,7 +75,7 @@
     sp<hardware::ICamera> mCamera;
     sp<ICameraRecordingProxy> mCameraProxy;
     sp<IGraphicBufferProducer> mPreviewSurface;
-    sp<IGraphicBufferConsumer> mPersistentSurface;
+    sp<PersistentSurface> mPersistentSurface;
     sp<IMediaRecorderClient> mListener;
     String16 mClientName;
     uid_t mClientUid;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 93d4199..478de35 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -56,8 +56,6 @@
 #include "include/SharedMemoryBuffer.h"
 #include "omx/OMXUtils.h"
 
-#include <android/IGraphicBufferSource.h>
-
 namespace android {
 
 using binder::Status;
@@ -6559,7 +6557,25 @@
 }
 
 status_t ACodec::LoadedState::setupInputSurface() {
-    status_t err = OK;
+    if (mCodec->mGraphicBufferSource == NULL) {
+        return BAD_VALUE;
+    }
+
+    android_dataspace dataSpace;
+    status_t err =
+        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+    if (err != OK) {
+        ALOGE("Failed to get default data space");
+        return err;
+    }
+
+    err = statusFromBinderStatus(
+            mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
+    if (err != OK) {
+        ALOGE("[%s] Unable to configure for node (err %d)",
+              mCodec->mComponentName.c_str(), err);
+        return err;
+    }
 
     if (mCodec->mRepeatFrameDelayUs > 0ll) {
         err = statusFromBinderStatus(
@@ -6655,30 +6671,20 @@
     sp<AMessage> notify = mCodec->mNotify->dup();
     notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
 
-    android_dataspace dataSpace;
-    status_t err =
-        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
-    notify->setMessage("input-format", mCodec->mInputFormat);
-    notify->setMessage("output-format", mCodec->mOutputFormat);
-
     sp<IGraphicBufferProducer> bufferProducer;
-    if (err == OK) {
-        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMXNode->createInputSurface(
-                mCodec->kPortIndexInput, dataSpace,
-                &bufferProducer, &mCodec->mGraphicBufferSource,
-                &mCodec->mInputMetadataType);
-        // framework uses ANW buffers internally instead of gralloc handles
-        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        }
-    }
+    status_t err = mCodec->mOMX->createInputSurface(
+            &bufferProducer, &mCodec->mGraphicBufferSource);
 
     if (err == OK) {
         err = setupInputSurface();
     }
 
     if (err == OK) {
+        mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+
+        notify->setMessage("input-format", mCodec->mInputFormat);
+        notify->setMessage("output-format", mCodec->mOutputFormat);
+
         notify->setObject("input-surface",
                 new BufferProducerWrapper(bufferProducer));
     } else {
@@ -6702,32 +6708,16 @@
     sp<RefBase> obj;
     CHECK(msg->findObject("input-surface", &obj));
     sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
+    mCodec->mGraphicBufferSource = surface->getBufferSource();
 
-    android_dataspace dataSpace;
-    status_t err =
-        mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
-    notify->setMessage("input-format", mCodec->mInputFormat);
-    notify->setMessage("output-format", mCodec->mOutputFormat);
+    status_t err = setupInputSurface();
 
     if (err == OK) {
         mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        err = mCodec->mOMXNode->setInputSurface(
-                mCodec->kPortIndexInput,
-                surface->getBufferConsumer(),
-                &mCodec->mGraphicBufferSource,
-                &mCodec->mInputMetadataType);
-        // framework uses ANW buffers internally instead of gralloc handles
-        if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
-            mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
-        }
-    }
 
-    if (err == OK) {
-        surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace);
-        err = setupInputSurface();
-    }
-
-    if (err != OK) {
+        notify->setMessage("input-format", mCodec->mInputFormat);
+        notify->setMessage("output-format", mCodec->mOutputFormat);
+    } else {
         // Can't use mCodec->signalError() here -- MediaCodec won't forward
         // the error through because it's in the "configured" state.  We
         // send a kWhatInputSurfaceAccepted with an error value instead.
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fc9f644..465ebc8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -213,50 +213,24 @@
 // static
 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
     OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
+    if (client.connect() != OK) {
+        ALOGE("Failed to connect to OMX to create persistent input surface.");
+        return NULL;
+    }
+
     sp<IOMX> omx = client.interface();
 
-    const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
-    if (mediaCodecList == NULL) {
-        ALOGE("Failed to obtain MediaCodecList!");
-        return NULL; // if called from Java should raise IOException
-    }
-
-    AString tmp;
-    sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
-    if (globalSettings == NULL || !globalSettings->findString(
-            kMaxEncoderInputBuffers, &tmp)) {
-        ALOGE("Failed to get encoder input buffer count!");
-        return NULL;
-    }
-
-    int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
-    if (bufferCount <= 0
-            || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
-        ALOGE("Encoder input buffer count is invalid!");
-        return NULL;
-    }
-
     sp<IGraphicBufferProducer> bufferProducer;
-    sp<IGraphicBufferConsumer> bufferConsumer;
+    sp<IGraphicBufferSource> bufferSource;
 
-    status_t err = omx->createPersistentInputSurface(
-            &bufferProducer, &bufferConsumer);
+    status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
 
     if (err != OK) {
         ALOGE("Failed to create persistent input surface.");
         return NULL;
     }
 
-    err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
-
-    if (err != NO_ERROR) {
-        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                bufferCount, err);
-        return NULL;
-    }
-
-    return new PersistentSurface(bufferProducer, bufferConsumer);
+    return new PersistentSurface(bufferProducer, bufferSource);
 }
 
 MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
@@ -1311,6 +1285,8 @@
                     status_t err = NO_ERROR;
                     sp<AMessage> response = new AMessage();
                     if (!msg->findInt32("err", &err)) {
+                        CHECK(msg->findMessage("input-format", &mInputFormat));
+                        CHECK(msg->findMessage("output-format", &mOutputFormat));
                         mHaveInputSurface = true;
                     } else {
                         response->setInt32("err", err);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 1f869b1..93643c2 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -44,8 +44,6 @@
 
 namespace android {
 
-const char *kMaxEncoderInputBuffers = "max-video-encoder-input-buffers";
-
 static Mutex sInitMutex;
 
 static bool parseBoolean(const char *s) {
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 33795f3..095fc6a 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -127,61 +127,6 @@
     return format;
 }
 
-static size_t doProfileEncoderInputBuffers(
-        const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
-    ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str());
-
-    sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps);
-    if (format == NULL) {
-        return 0;
-    }
-
-    format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
-    ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str());
-
-    status_t err = OK;
-    sp<ALooper> looper = new ALooper;
-    looper->setName("MediaCodec_looper");
-    looper->start(
-            false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
-
-    sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
-    if (err != OK) {
-        ALOGE("Failed to create codec: %s", name.c_str());
-        return 0;
-    }
-
-    err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
-    if (err != OK) {
-        ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
-        codec->release();
-        return 0;
-    }
-
-    sp<IGraphicBufferProducer> bufferProducer;
-    err = codec->createInputSurface(&bufferProducer);
-    if (err != OK) {
-        ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str());
-        codec->release();
-        return 0;
-    }
-
-    int minUndequeued = 0;
-    err = bufferProducer->query(
-            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued);
-    if (err != OK) {
-        ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS");
-        minUndequeued = 0;
-    }
-
-    err = codec->release();
-    if (err != OK) {
-        ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
-    }
-
-    return minUndequeued;
-}
-
 static size_t doProfileCodecs(
         bool isEncoder, const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
     sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps);
@@ -276,7 +221,6 @@
         bool forceToMeasure) {
     KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
     AString supportMultipleSecureCodecs = "true";
-    size_t maxEncoderInputBuffers = 0;
     for (size_t i = 0; i < infos.size(); ++i) {
         const sp<MediaCodecInfo> info = infos[i];
         AString name = info->getCodecName();
@@ -319,21 +263,9 @@
                         supportMultipleSecureCodecs = "false";
                     }
                 }
-                if (info->isEncoder() && mimes[i].startsWith("video/")) {
-                    size_t encoderInputBuffers =
-                        doProfileEncoderInputBuffers(name, mimes[i], caps);
-                    if (encoderInputBuffers > maxEncoderInputBuffers) {
-                        maxEncoderInputBuffers = encoderInputBuffers;
-                    }
-                }
             }
         }
     }
-    if (maxEncoderInputBuffers > 0) {
-        char tmp[32];
-        sprintf(tmp, "%zu", maxEncoderInputBuffers);
-        global_results->add(kMaxEncoderInputBuffers, tmp);
-    }
     global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
 }
 
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 8391d76..de4d06f 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -20,7 +20,6 @@
 
 #include <inttypes.h>
 
-#include <gui/IGraphicBufferConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
 #include <media/ICrypto.h>
@@ -36,7 +35,6 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/PersistentSurface.h>
 #include <media/stagefright/Utils.h>
 
 namespace android {
@@ -326,10 +324,10 @@
         const sp<ALooper> &looper,
         const sp<AMessage> &format,
         const sp<MediaSource> &source,
-        const sp<IGraphicBufferConsumer> &consumer,
+        const sp<PersistentSurface> &persistentSurface,
         uint32_t flags) {
-    sp<MediaCodecSource> mediaSource =
-            new MediaCodecSource(looper, format, source, consumer, flags);
+    sp<MediaCodecSource> mediaSource = new MediaCodecSource(
+            looper, format, source, persistentSurface, flags);
 
     if (mediaSource->init() == OK) {
         return mediaSource;
@@ -405,7 +403,7 @@
         const sp<ALooper> &looper,
         const sp<AMessage> &outputFormat,
         const sp<MediaSource> &source,
-        const sp<IGraphicBufferConsumer> &consumer,
+        const sp<PersistentSurface> &persistentSurface,
         uint32_t flags)
     : mLooper(looper),
       mOutputFormat(outputFormat),
@@ -418,7 +416,7 @@
       mSetEncoderFormat(false),
       mEncoderFormat(0),
       mEncoderDataSpace(0),
-      mGraphicBufferConsumer(consumer),
+      mPersistentSurface(persistentSurface),
       mInputBufferTimeOffsetUs(0),
       mFirstSampleSystemTimeUs(-1ll),
       mPausePending(false),
@@ -515,12 +513,11 @@
     if (mFlags & FLAG_USE_SURFACE_INPUT) {
         CHECK(mIsVideo);
 
-        if (mGraphicBufferConsumer != NULL) {
+        if (mPersistentSurface != NULL) {
             // When using persistent surface, we are only interested in the
             // consumer, but have to use PersistentSurface as a wrapper to
             // pass consumer over messages (similar to BufferProducerWrapper)
-            err = mEncoder->setInputSurface(
-                    new PersistentSurface(NULL, mGraphicBufferConsumer));
+            err = mEncoder->setInputSurface(mPersistentSurface);
         } else {
             err = mEncoder->createInputSurface(&mGraphicBufferProducer);
         }
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 2e62806..9edd0de 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -37,9 +37,9 @@
             const char *name, const sp<IOMXObserver> &observer,
             sp<IOMXNode> *omxNode);
 
-    virtual status_t createPersistentInputSurface(
+    virtual status_t createInputSurface(
             sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer);
+            sp<IGraphicBufferSource> *bufferSource);
 
     virtual void binderDied(const wp<IBinder> &the_late_who);
 
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 30d0b75..d911508 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -25,7 +25,6 @@
 #include <utils/threads.h>
 
 namespace android {
-class IGraphicBufferSource;
 class IOMXBufferSource;
 class IOMXObserver;
 struct OMXMaster;
@@ -81,21 +80,8 @@
             OMX_U32 portIndex, const sp<NativeHandle> &nativeHandle,
             OMX::buffer_id buffer);
 
-    status_t createInputSurface(
-            OMX_U32 portIndex, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
-
-    static status_t createPersistentInputSurface(
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferConsumer> *bufferConsumer);
-
     status_t setInputSurface(
-            OMX_U32 portIndex,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
+            const sp<IOMXBufferSource> &bufferSource);
 
     status_t allocateSecureBuffer(
             OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
@@ -252,12 +238,6 @@
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
             OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
 
-    status_t createGraphicBufferSource(
-            OMX_U32 portIndex, android_dataspace dataSpace,
-            const sp<IGraphicBufferConsumer> &bufferConsumer,
-            sp<IGraphicBufferProducer> *bufferProducer,
-            sp<IGraphicBufferSource> *bufferSource,
-            MetadataBufferType *type);
     sp<IOMXBufferSource> getBufferSource();
     void setBufferSource(const sp<IOMXBufferSource> &bufferSource);
     // Called when omx_message::FILL_BUFFER_DONE is received. (Currently the
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 25bc41c..afb8173 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -31,93 +31,22 @@
 #include <ui/GraphicBuffer.h>
 #include <gui/BufferItem.h>
 #include <HardwareAPI.h>
+#include "omx/OMXUtils.h"
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
 
 #include <inttypes.h>
 #include "FrameDropper.h"
 
 namespace android {
 
-GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
-        const wp<IGraphicBufferConsumer> &consumer,
-        const wp<ConsumerListener>& consumerListener) :
-    mConsumerListener(consumerListener),
-    mConsumer(consumer) {}
+static const OMX_U32 kPortIndexInput = 0;
 
-GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
-        const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onFrameAvailable(item);
-    } else {
-        sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
-        if (consumer == NULL) {
-            return;
-        }
-        BufferItem bi;
-        status_t err = consumer->acquireBuffer(&bi, 0);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->detachBuffer(bi.mSlot);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->attachBuffer(&bi.mSlot, bi.mGraphicBuffer);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
-            return;
-        }
-
-        err = consumer->releaseBuffer(bi.mSlot, 0,
-                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
-        if (err != OK) {
-            ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
-        }
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
-        const BufferItem& item) {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onFrameReplaced(item);
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onBuffersReleased();
-    }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
-    sp<ConsumerListener> listener(mConsumerListener.promote());
-    if (listener != NULL) {
-        listener->onSidebandStreamChanged();
-    }
-}
-
-GraphicBufferSource::GraphicBufferSource(
-        const sp<IOMXNode> &omxNode,
-        uint32_t bufferWidth,
-        uint32_t bufferHeight,
-        uint32_t bufferCount,
-        uint32_t consumerUsage,
-        const sp<IGraphicBufferConsumer> &consumer) :
+GraphicBufferSource::GraphicBufferSource() :
     mInitCheck(UNKNOWN_ERROR),
-    mOMXNode(omxNode),
     mExecuting(false),
     mSuspended(false),
     mLastDataSpace(HAL_DATASPACE_UNKNOWN),
-    mIsPersistent(false),
-    mConsumer(consumer),
     mNumFramesAvailable(0),
     mNumBufferAcquired(0),
     mEndOfStream(false),
@@ -129,6 +58,7 @@
     mRepeatAfterUs(-1ll),
     mRepeatLastFrameGeneration(0),
     mRepeatLastFrameTimestamp(-1ll),
+    mRepeatLastFrameCount(0),
     mLatestBufferId(-1),
     mLatestBufferFrameNum(0),
     mLatestBufferFence(Fence::NO_FENCE),
@@ -138,48 +68,21 @@
     mPrevCaptureUs(-1ll),
     mPrevFrameUs(-1ll),
     mInputBufferTimeOffsetUs(0ll) {
+    ALOGV("GraphicBufferSource");
 
-    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
-            bufferWidth, bufferHeight, bufferCount);
+    String8 name("GraphicBufferSource");
 
-    if (bufferWidth == 0 || bufferHeight == 0) {
-        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
-        mInitCheck = BAD_VALUE;
-        return;
-    }
+    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    mConsumer->setConsumerName(name);
 
-    if (mConsumer == NULL) {
-        String8 name("GraphicBufferSource");
-
-        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        mConsumer->setConsumerName(name);
-
-        // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
-        // for backward compatibility.
-        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
-        mConsumer->setConsumerUsageBits(consumerUsage);
-
-        mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
-        if (mInitCheck != NO_ERROR) {
-            ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
-                    bufferCount, mInitCheck);
-            return;
-        }
-    } else {
-        mIsPersistent = true;
-    }
-    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
     // reference once the ctor ends, as that would cause the refcount of 'this'
     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
     // that's what we create.
-    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
-    sp<IConsumerListener> proxy;
-    if (!mIsPersistent) {
-        proxy = new BufferQueue::ProxyConsumerListener(listener);
-    } else {
-        proxy = new PersistentProxyListener(mConsumer, listener);
-    }
+    wp<BufferQueue::ConsumerListener> listener =
+            static_cast<BufferQueue::ConsumerListener*>(this);
+    sp<IConsumerListener> proxy =
+            new BufferQueue::ProxyConsumerListener(listener);
 
     mInitCheck = mConsumer->consumerConnect(proxy, false);
     if (mInitCheck != NO_ERROR) {
@@ -194,15 +97,14 @@
 }
 
 GraphicBufferSource::~GraphicBufferSource() {
+    ALOGV("~GraphicBufferSource");
     if (mLatestBufferId >= 0) {
-        releaseBuffer(
-                mLatestBufferId, mLatestBufferFrameNum,
-                mBufferSlot[mLatestBufferId], mLatestBufferFence);
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
     }
     if (mNumBufferAcquired != 0) {
         ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
     }
-    if (mConsumer != NULL && !mIsPersistent) {
+    if (mConsumer != NULL) {
         status_t err = mConsumer->consumerDisconnect();
         if (err != NO_ERROR) {
             ALOGW("consumerDisconnect failed: %d", err);
@@ -291,15 +193,33 @@
         mLooper.clear();
     }
 
-    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
-            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
+    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d acquired=%d",
+            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent, mNumBufferAcquired);
 
-    // Codec is no longer executing.  Discard all codec-related state.
+    // Codec is no longer executing.  Releasing all buffers to bq.
+    for (int i = (int)mCodecBuffers.size() - 1; i >= 0; --i) {
+        if (mCodecBuffers[i].mGraphicBuffer != NULL) {
+            int id = mCodecBuffers[i].mSlot;
+            if (id != mLatestBufferId) {
+                ALOGV("releasing buffer for codec: slot=%d, useCount=%d, latest=%d",
+                        id, mBufferUseCount[id], mLatestBufferId);
+                sp<Fence> fence = new Fence(-1);
+                releaseBuffer(id, mCodecBuffers[i].mFrameNumber, fence);
+                mBufferUseCount[id] = 0;
+            }
+        }
+    }
+    // Also release the latest buffer
+    if (mLatestBufferId >= 0) {
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+        mBufferUseCount[mLatestBufferId] = 0;
+        mLatestBufferId = -1;
+    }
+
     mCodecBuffers.clear();
-    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
-    //       are null; complain if not
-
+    mOMXNode.clear();
     mExecuting = false;
+
     return Status::ok();
 }
 
@@ -313,7 +233,7 @@
         return Status::fromServiceSpecificError(INVALID_OPERATION);
     }
 
-    ALOGV("addCodecBuffer id=%u", bufferID);
+    ALOGV("addCodecBuffer: bufferID=%u", bufferID);
 
     CodecBuffer codecBuffer;
     codecBuffer.mBufferID = bufferID;
@@ -336,14 +256,14 @@
     int cbi = findMatchingCodecBuffer_l(bufferID);
     if (cbi < 0) {
         // This should never happen.
-        ALOGE("codecBufferEmptied: buffer not recognized (id=%u)", bufferID);
+        ALOGE("codecBufferEmptied: buffer not recognized (bufferID=%u)", bufferID);
         if (fenceFd >= 0) {
             ::close(fenceFd);
         }
         return Status::fromServiceSpecificError(BAD_VALUE);
     }
 
-    ALOGV("codecBufferEmptied id=%u", bufferID);
+    ALOGV("codecBufferEmptied: bufferID=%u, cbi=%d", bufferID, cbi);
     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
 
     // header->nFilledLen may not be the original value, so we can't compare
@@ -374,19 +294,19 @@
         mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
         mBufferUseCount[id]--;
 
-        ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, handle=%p",
-                id, cbi, mBufferUseCount[id], mBufferSlot[id]->handle);
-
         if (mBufferUseCount[id] < 0) {
             ALOGW("mBufferUseCount for bq slot %d < 0 (=%d)", id, mBufferUseCount[id]);
             mBufferUseCount[id] = 0;
         }
         if (id != mLatestBufferId && mBufferUseCount[id] == 0) {
-            releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
+            releaseBuffer(id, codecBuffer.mFrameNumber, fence);
         }
+        ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, acquired=%d, handle=%p",
+                id, cbi, mBufferUseCount[id], mNumBufferAcquired, mBufferSlot[id]->handle);
     } else {
-        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
-                cbi);
+        ALOGV("codecBufferEmptied: no match for emptied buffer, "
+                "slot=%d, cbi=%d, useCount=%d, acquired=%d",
+                id, cbi, mBufferUseCount[id], mNumBufferAcquired);
         // we will not reuse codec buffer, so there is no need to wait for fence
     }
 
@@ -453,34 +373,19 @@
     ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
             mNumFramesAvailable);
     BufferItem item;
-    status_t err = mConsumer->acquireBuffer(&item, 0);
-    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-        // shouldn't happen
-        ALOGW("fillCodecBuffer_l: frame was not available");
-        return false;
-    } else if (err != OK) {
-        // now what? fake end-of-stream?
-        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
+    status_t err = acquireBuffer(&item);
+    if (err != OK) {
+        ALOGE("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
         return false;
     }
 
-    mNumBufferAcquired++;
     mNumFramesAvailable--;
 
-    // If this is the first time we're seeing this buffer, add it to our
-    // slot table.
-    if (item.mGraphicBuffer != NULL) {
-        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mSlot);
-        mBufferSlot[item.mSlot] = item.mGraphicBuffer;
-        mBufferUseCount[item.mSlot] = 0;
-    }
-
     if (item.mDataSpace != mLastDataSpace) {
         onDataSpaceChanged_l(
                 item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
     }
 
-
     err = UNKNOWN_ERROR;
 
     // only submit sample if start time is unspecified, or sample
@@ -505,10 +410,18 @@
 
     if (err != OK) {
         ALOGV("submitBuffer_l failed, releasing bq slot %d", item.mSlot);
-        releaseBuffer(item.mSlot, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
+        releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
     } else {
-        ALOGV("buffer submitted (bq %d, cbi %d)", item.mSlot, cbi);
-        setLatestBuffer_l(item, dropped);
+        // Don't set the last buffer id if we're not repeating,
+        // we'll be holding on to the last buffer for nothing.
+        if (mRepeatAfterUs > 0ll) {
+            setLatestBuffer_l(item);
+        }
+        if (!dropped) {
+            ++mBufferUseCount[item.mSlot];
+        }
+        ALOGV("buffer submitted: slot=%d, cbi=%d, useCount=%d, acquired=%d",
+                item.mSlot, cbi, mBufferUseCount[item.mSlot], mNumBufferAcquired);
     }
 
     return true;
@@ -577,24 +490,16 @@
     return true;
 }
 
-void GraphicBufferSource::setLatestBuffer_l(
-        const BufferItem &item, bool dropped) {
-    if (mLatestBufferId >= 0) {
-        if (mBufferUseCount[mLatestBufferId] == 0) {
-            releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
-                    mBufferSlot[mLatestBufferId], mLatestBufferFence);
-            // mLatestBufferFence will be set to new fence just below
-        }
+void GraphicBufferSource::setLatestBuffer_l(const BufferItem &item) {
+    if (mLatestBufferId >= 0 && mBufferUseCount[mLatestBufferId] == 0) {
+        releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+        // mLatestBufferFence will be set to new fence just below
     }
 
     mLatestBufferId = item.mSlot;
     mLatestBufferFrameNum = item.mFrameNumber;
     mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
 
-    if (!dropped) {
-        ++mBufferUseCount[item.mSlot];
-    }
-
     ALOGV("setLatestBuffer_l: slot=%d, useCount=%d",
             item.mSlot, mBufferUseCount[item.mSlot]);
 
@@ -709,7 +614,7 @@
         return err;
     }
 
-    ALOGV("emptyGraphicBuffer succeeded, id=%u buf=%p bufhandle=%p",
+    ALOGV("emptyGraphicBuffer succeeded, bufferID=%u buf=%p bufhandle=%p",
             bufferID, buffer->getNativeBuffer(), buffer->handle);
     return OK;
 }
@@ -740,7 +645,7 @@
     if (err != OK) {
         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
     } else {
-        ALOGV("submitEndOfInputStream_l: buffer submitted, id=%u cbi=%d",
+        ALOGV("submitEndOfInputStream_l: buffer submitted, bufferID=%u cbi=%d",
                 bufferID, cbi);
         mEndOfStreamSent = true;
     }
@@ -766,34 +671,39 @@
     return -1;
 }
 
+status_t GraphicBufferSource::acquireBuffer(BufferItem *bi) {
+    status_t err = mConsumer->acquireBuffer(bi, 0);
+    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+        // shouldn't happen
+        ALOGW("acquireBuffer: frame was not available");
+        return err;
+    } else if (err != OK) {
+        ALOGW("acquireBuffer: failed with err=%d", err);
+        return err;
+    }
+    // If this is the first time we're seeing this buffer, add it to our
+    // slot table.
+    if (bi->mGraphicBuffer != NULL) {
+        ALOGV("acquireBuffer: setting mBufferSlot %d", bi->mSlot);
+        mBufferSlot[bi->mSlot] = bi->mGraphicBuffer;
+        mBufferUseCount[bi->mSlot] = 0;
+    }
+    mNumBufferAcquired++;
+    return OK;
+}
+
 /*
- * Releases an acquired buffer back to the consumer for either persistent
- * or non-persistent surfaces.
+ * Releases an acquired buffer back to the consumer.
  *
- * id: buffer slot to release (in persistent case the id might be changed)
+ * id: buffer slot to release
  * frameNum: frame number of the frame being released
- * buffer: GraphicBuffer pointer to release (note this must not be & as we
- *         will clear the original mBufferSlot in persistent case)
- *         Use NOLINT to supress warning on the copy of 'buffer'.
  * fence: fence of the frame being released
  */
 void GraphicBufferSource::releaseBuffer(
-        int &id, uint64_t frameNum,
-        const sp<GraphicBuffer> buffer, const sp<Fence> &fence) {  // NOLINT
+        int id, uint64_t frameNum, const sp<Fence> &fence) {
     ALOGV("releaseBuffer: slot=%d", id);
-    if (mIsPersistent) {
-        mConsumer->detachBuffer(id);
-        mBufferSlot[id] = NULL;
-
-        if (mConsumer->attachBuffer(&id, buffer) == OK) {
-            mConsumer->releaseBuffer(
-                    id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
-        }
-    } else {
-        mConsumer->releaseBuffer(
-                id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
-    }
-    id = -1; // invalidate id
+    mConsumer->releaseBuffer(
+            id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
     mNumBufferAcquired--;
 }
 
@@ -804,7 +714,7 @@
     ALOGV("onFrameAvailable exec=%d avail=%zu",
             mExecuting, mNumFramesAvailable);
 
-    if (mEndOfStream || mSuspended) {
+    if (mOMXNode == NULL || mEndOfStream || mSuspended) {
         if (mEndOfStream) {
             // This should only be possible if a new buffer was queued after
             // EOS was signaled, i.e. the app is misbehaving.
@@ -815,20 +725,11 @@
         }
 
         BufferItem item;
-        status_t err = mConsumer->acquireBuffer(&item, 0);
+        status_t err = acquireBuffer(&item);
         if (err == OK) {
-            mNumBufferAcquired++;
-
-            // If this is the first time we're seeing this buffer, add it to our
-            // slot table.
-            if (item.mGraphicBuffer != NULL) {
-                ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mSlot);
-                mBufferSlot[item.mSlot] = item.mGraphicBuffer;
-                mBufferUseCount[item.mSlot] = 0;
-            }
-
-            releaseBuffer(item.mSlot, item.mFrameNumber,
-                    item.mGraphicBuffer, item.mFence);
+            releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+        } else {
+            ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
         }
         return;
     }
@@ -857,6 +758,18 @@
 
     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
         if ((slotMask & 0x01) != 0) {
+            // Last buffer (if set) is always acquired even if its use count
+            // is 0, because we could have skipped that frame but kept it for
+            // repeating. Otherwise a buffer is only acquired if use count>0.
+            if (mBufferSlot[i] != NULL &&
+                    (mBufferUseCount[i] > 0 || mLatestBufferId == i)) {
+                ALOGV("releasing acquired buffer: slot=%d, useCount=%d, latest=%d",
+                        i, mBufferUseCount[i], mLatestBufferId);
+                mNumBufferAcquired--;
+            }
+            if (mLatestBufferId == i) {
+                mLatestBufferId = -1;
+            }
             mBufferSlot[i] = NULL;
             mBufferUseCount[i] = 0;
         }
@@ -869,11 +782,99 @@
     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
 }
 
-void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
-    // no need for mutex as we are not yet running
-    ALOGD("setting dataspace: %#x", dataSpace);
-    mConsumer->setDefaultBufferDataSpace(dataSpace);
-    mLastDataSpace = dataSpace;
+Status GraphicBufferSource::configure(
+        const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+    if (omxNode == NULL) {
+        return Status::fromServiceSpecificError(BAD_VALUE);
+    }
+
+    // Do setInputSurface() first, the node will try to enable metadata
+    // mode on input, and does necessary error checking. If this fails,
+    // we can't use this input surface on the node.
+    status_t err = omxNode->setInputSurface(this);
+    if (err != NO_ERROR) {
+        ALOGE("Unable to set input surface: %d", err);
+        return Status::fromServiceSpecificError(err);
+    }
+
+    // use consumer usage bits queried from encoder, but always add
+    // HW_VIDEO_ENCODER for backward compatibility.
+    uint32_t consumerUsage;
+    if (omxNode->getParameter(
+            (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+            &consumerUsage, sizeof(consumerUsage)) != OK) {
+        consumerUsage = 0;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = omxNode->getParameter(
+            OMX_IndexParamPortDefinition, &def, sizeof(def));
+    if (err != NO_ERROR) {
+        ALOGE("Failed to get port definition: %d", err);
+        return Status::fromServiceSpecificError(UNKNOWN_ERROR);
+    }
+
+    // Call setMaxAcquiredBufferCount without lock.
+    // setMaxAcquiredBufferCount could call back to onBuffersReleased
+    // if the buffer count change results in releasing of existing buffers,
+    // which would lead to deadlock.
+    err = mConsumer->setMaxAcquiredBufferCount(def.nBufferCountActual);
+    if (err != NO_ERROR) {
+        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
+                def.nBufferCountActual, err);
+        return Status::fromServiceSpecificError(err);
+    }
+
+    {
+        Mutex::Autolock autoLock(mMutex);
+        mOMXNode = omxNode;
+
+        err = mConsumer->setDefaultBufferSize(
+                def.format.video.nFrameWidth,
+                def.format.video.nFrameHeight);
+        if (err != NO_ERROR) {
+            ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
+                    def.format.video.nFrameWidth,
+                    def.format.video.nFrameHeight,
+                    err);
+            return Status::fromServiceSpecificError(err);
+        }
+
+        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+        mConsumer->setConsumerUsageBits(consumerUsage);
+
+        // Sets the default buffer data space
+        ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumBufferAcquired);
+        mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
+        mLastDataSpace = (android_dataspace)dataSpace;
+
+        mExecuting = false;
+        mSuspended = false;
+        mEndOfStream = false;
+        mEndOfStreamSent = false;
+        mMaxTimestampGapUs = -1ll;
+        mPrevOriginalTimeUs = -1ll;
+        mPrevModifiedTimeUs = -1ll;
+        mSkipFramesBeforeNs = -1ll;
+        mRepeatAfterUs = -1ll;
+        mRepeatLastFrameGeneration = 0;
+        mRepeatLastFrameTimestamp = -1ll;
+        mRepeatLastFrameCount = 0;
+        mLatestBufferId = -1;
+        mLatestBufferFrameNum = 0;
+        mLatestBufferFence = Fence::NO_FENCE;
+        mRepeatBufferDeferred = false;
+        mTimePerCaptureUs = -1ll;
+        mTimePerFrameUs = -1ll;
+        mPrevCaptureUs = -1ll;
+        mPrevFrameUs = -1ll;
+        mInputBufferTimeOffsetUs = 0;
+    }
+
+    return Status::ok();
 }
 
 Status GraphicBufferSource::setSuspend(bool suspend) {
@@ -886,22 +887,16 @@
 
         while (mNumFramesAvailable > 0) {
             BufferItem item;
-            status_t err = mConsumer->acquireBuffer(&item, 0);
+            status_t err = acquireBuffer(&item);
 
-            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-                // shouldn't happen.
-                ALOGW("suspend: frame was not available");
-                break;
-            } else if (err != OK) {
-                ALOGW("suspend: acquireBuffer returned err=%d", err);
+            if (err != OK) {
+                ALOGE("setSuspend: acquireBuffer returned err=%d", err);
                 break;
             }
 
-            ++mNumBufferAcquired;
             --mNumFramesAvailable;
 
-            releaseBuffer(item.mSlot, item.mFrameNumber,
-                    item.mGraphicBuffer, item.mFence);
+            releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
         }
         return Status::ok();
     }
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 88fab02..045a86a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -58,14 +58,7 @@
                             public BnOMXBufferSource,
                             public BufferQueue::ConsumerListener {
 public:
-    GraphicBufferSource(
-            const sp<IOMXNode> &omxNode,
-            uint32_t bufferWidth,
-            uint32_t bufferHeight,
-            uint32_t bufferCount,
-            uint32_t consumerUsage,
-            const sp<IGraphicBufferConsumer> &consumer = NULL
-    );
+    GraphicBufferSource();
 
     virtual ~GraphicBufferSource();
 
@@ -81,9 +74,6 @@
         return mProducer;
     }
 
-    // Sets the default buffer data space
-    void setDefaultDataSpace(android_dataspace dataSpace);
-
     // This is called when OMX transitions to OMX_StateExecuting, which means
     // we can start handing it buffers.  If we already have buffers of data
     // sitting in the BufferQueue, this will send them to the codec.
@@ -108,6 +98,10 @@
     Status onInputBufferEmptied(
             int32_t bufferID, const OMXFenceParcelable& fenceParcel) override;
 
+    // Configure the buffer source to be used with an OMX node with the default
+    // data space.
+    Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+
     // This is called after the last input frame has been submitted.  We
     // need to submit an empty buffer with the EOS flag set.  If we don't
     // have a codec buffer ready, we just set the mEndOfStream flag.
@@ -174,30 +168,6 @@
     void onSidebandStreamChanged() override;
 
 private:
-    // PersistentProxyListener is similar to BufferQueue::ProxyConsumerListener
-    // except that it returns (acquire/detach/re-attache/release) buffers
-    // in onFrameAvailable() if the actual consumer object is no longer valid.
-    //
-    // This class is used in persistent input surface case to prevent buffer
-    // loss when onFrameAvailable() is received while we don't have a valid
-    // consumer around.
-    class PersistentProxyListener : public BnConsumerListener {
-        public:
-            PersistentProxyListener(
-                    const wp<IGraphicBufferConsumer> &consumer,
-                    const wp<ConsumerListener>& consumerListener);
-            virtual ~PersistentProxyListener();
-            virtual void onFrameAvailable(const BufferItem& item) override;
-            virtual void onFrameReplaced(const BufferItem& item) override;
-            virtual void onBuffersReleased() override;
-            virtual void onSidebandStreamChanged() override;
-         private:
-            // mConsumerListener is a weak reference to the IConsumerListener.
-            wp<ConsumerListener> mConsumerListener;
-            // mConsumer is a weak reference to the IGraphicBufferConsumer, use
-            // a weak ref to avoid circular ref between mConsumer and this class
-            wp<IGraphicBufferConsumer> mConsumer;
-    };
 
     // Keep track of codec input buffers.  They may either be available
     // (mGraphicBuffer == NULL) or in use by the codec.
@@ -242,12 +212,13 @@
     // doing anything if we don't have a codec buffer available.
     void submitEndOfInputStream_l();
 
-    // Release buffer to the consumer
-    void releaseBuffer(
-            int &id, uint64_t frameNum,
-            const sp<GraphicBuffer> buffer, const sp<Fence> &fence);
+    // Acquire buffer from the consumer
+    status_t acquireBuffer(BufferItem *bi);
 
-    void setLatestBuffer_l(const BufferItem &item, bool dropped);
+    // Release buffer to the consumer
+    void releaseBuffer(int id, uint64_t frameNum, const sp<Fence> &fence);
+
+    void setLatestBuffer_l(const BufferItem &item);
     bool repeatLatestBuffer_l();
     bool getTimestamp(const BufferItem &item, int64_t *timeUs, int64_t *codecTimeUs);
 
@@ -274,7 +245,6 @@
     // Our BufferQueue interfaces. mProducer is passed to the producer through
     // getIGraphicBufferProducer, and mConsumer is used internally to retrieve
     // the buffers queued by the producer.
-    bool mIsPersistent;
     sp<IGraphicBufferProducer> mProducer;
     sp<IGraphicBufferConsumer> mConsumer;
 
@@ -340,7 +310,6 @@
 
     int64_t mInputBufferTimeOffsetUs;
 
-    MetadataBufferType mMetadataBufferType;
     ColorAspects mColorAspects;
 
     void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 70b9c17..7907c62 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -27,6 +27,7 @@
 #include "../include/OMXNodeInstance.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include "GraphicBufferSource.h"
 
 #include "OMXMaster.h"
 #include "OMXUtils.h"
@@ -154,11 +155,26 @@
     return StatusFromOMXError(err);
 }
 
-status_t OMX::createPersistentInputSurface(
+status_t OMX::createInputSurface(
         sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferConsumer> *bufferConsumer) {
-    return OMXNodeInstance::createPersistentInputSurface(
-            bufferProducer, bufferConsumer);
+        sp<IGraphicBufferSource> *bufferSource) {
+    if (bufferProducer == NULL || bufferSource == NULL) {
+        ALOGE("b/25884056");
+        return BAD_VALUE;
+    }
+
+    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+    status_t err = graphicBufferSource->initCheck();
+    if (err != OK) {
+        ALOGE("Failed to create persistent input surface: %s (%d)",
+                strerror(-err), err);
+        return err;
+    }
+
+    *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+    *bufferSource = graphicBufferSource;
+
+    return OK;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index e45507c..ef18958 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -23,8 +23,6 @@
 #include "../include/OMXNodeInstance.h"
 #include "OMXMaster.h"
 #include "OMXUtils.h"
-#include "GraphicBufferSource.h"
-#include <android/IGraphicBufferSource.h>
 #include <android/IOMXBufferSource.h>
 
 #include <OMX_Component.h>
@@ -482,6 +480,7 @@
     status_t err = mOwner->freeNode(this);
 
     mDispatcher.clear();
+    mOMXBufferSource.clear();
 
     mHandle = NULL;
     CLOG_IF_ERROR(freeNode, err, "");
@@ -1196,35 +1195,23 @@
     return OK;
 }
 
-status_t OMXNodeInstance::createGraphicBufferSource(
-        OMX_U32 portIndex, android_dataspace dataSpace,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
+status_t OMXNodeInstance::setInputSurface(
+        const sp<IOMXBufferSource> &bufferSource) {
+    Mutex::Autolock autolock(mLock);
+
     status_t err;
 
     // only allow graphic source on input port, when there are no allocated buffers yet
-    if (portIndex != kPortIndexInput) {
-        android_errorWriteLog(0x534e4554, "29422020");
-        return BAD_VALUE;
-    } else if (mNumPortBuffers[portIndex] > 0) {
+    if (mNumPortBuffers[kPortIndexInput] > 0) {
         android_errorWriteLog(0x534e4554, "29422020");
         return INVALID_OPERATION;
     }
 
     if (getBufferSource() != NULL) {
-        if (portIndex < NELEM(mMetadataType) && type != NULL) {
-            *type = mMetadataType[portIndex];
-        }
         return ALREADY_EXISTS;
     }
 
-    // Input buffers will hold meta-data (ANativeWindowBuffer references).
-    if (type != NULL) {
-        *type = kMetadataBufferTypeANWBuffer;
-    }
-    err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
+    err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
     if (err != OK) {
         return err;
     }
@@ -1233,13 +1220,13 @@
     // codec was configured.
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
-    def.nPortIndex = portIndex;
+    def.nPortIndex = kPortIndexInput;
     OMX_ERRORTYPE oerr = OMX_GetParameter(
             mHandle, OMX_IndexParamPortDefinition, &def);
     if (oerr != OMX_ErrorNone) {
         OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
-        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
-                asString(index), index, portString(portIndex), portIndex);
+        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
+                index, portString(kPortIndexInput), kPortIndexInput);
         return UNKNOWN_ERROR;
     }
 
@@ -1250,97 +1237,18 @@
         return INVALID_OPERATION;
     }
 
-    uint32_t usageBits;
-    oerr = OMX_GetParameter(
-            mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
-    if (oerr != OMX_ErrorNone) {
-        usageBits = 0;
-    }
-
-    sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(
-            this,
-            def.format.video.nFrameWidth,
-            def.format.video.nFrameHeight,
-            def.nBufferCountActual,
-            usageBits,
-            bufferConsumer);
-
-    if ((err = graphicBufferSource->initCheck()) != OK) {
-        return err;
-    }
-    setBufferSource(graphicBufferSource);
-
-    if (bufferConsumer == NULL) {
-        graphicBufferSource->setDefaultDataSpace(dataSpace);
-    }
-
-    if (bufferProducer != NULL) {
-        *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
-    }
-
-    *bufferSource = graphicBufferSource;
-
-    return OK;
-}
-
-status_t OMXNodeInstance::createInputSurface(
-        OMX_U32 portIndex, android_dataspace dataSpace,
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    if (bufferProducer == NULL) {
-        ALOGE("b/25884056");
+    if (def.format.video.nFrameWidth == 0
+            || def.format.video.nFrameHeight == 0) {
+        ALOGE("Invalid video dimension %ux%u",
+                def.format.video.nFrameWidth,
+                def.format.video.nFrameHeight);
         return BAD_VALUE;
     }
 
-    Mutex::Autolock autolock(mLock);
-    return createGraphicBufferSource(
-            portIndex, dataSpace, NULL /* bufferConsumer */,
-            bufferProducer, bufferSource, type);
-}
-
-//static
-status_t OMXNodeInstance::createPersistentInputSurface(
-        sp<IGraphicBufferProducer> *bufferProducer,
-        sp<IGraphicBufferConsumer> *bufferConsumer) {
-    if (bufferProducer == NULL || bufferConsumer == NULL) {
-        ALOGE("b/25884056");
-        return BAD_VALUE;
-    }
-    String8 name("GraphicBufferSource");
-
-    sp<IGraphicBufferProducer> producer;
-    sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer);
-    consumer->setConsumerName(name);
-    consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
-
-    sp<BufferQueue::ProxyConsumerListener> proxy =
-        new BufferQueue::ProxyConsumerListener(NULL);
-    status_t err = consumer->consumerConnect(proxy, false);
-    if (err != NO_ERROR) {
-        ALOGE("Error connecting to BufferQueue: %s (%d)",
-                strerror(-err), err);
-        return err;
-    }
-
-    *bufferProducer = producer;
-    *bufferConsumer = consumer;
-
+    setBufferSource(bufferSource);
     return OK;
 }
 
-status_t OMXNodeInstance::setInputSurface(
-        OMX_U32 portIndex,
-        const sp<IGraphicBufferConsumer> &bufferConsumer,
-        sp<IGraphicBufferSource> *bufferSource,
-        MetadataBufferType *type) {
-    Mutex::Autolock autolock(mLock);
-    return createGraphicBufferSource(
-            portIndex, android_dataspace::HAL_DATASPACE_UNKNOWN,
-            bufferConsumer, NULL, bufferSource, type);
-}
-
 status_t OMXNodeInstance::allocateSecureBuffer(
         OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
         void **buffer_data, sp<NativeHandle> *native_handle) {