Connect MediaRecorder Native to SurfaceMediaSource

Making a connection from MediaRecorder Native layer to the
SurfaceMediaSource for the purpose of encoding GL Frames. This will be
called from the java side inside the Mobile Filter Framework.

The mediarecorder native layer (client), when set the videosource to
option VIDEO_SOURCE_FRAMES, asks the StageFrightRecorder on the mediaserver
side to create a SurfaceMediaSource object and pass it back as a
sp<ISurfaceTexture> object. Using that, the client side will dequeue and
queue buffers. Connecting the GL Frames to the obtained
sp<ISurfaceTexture> is not part of this CL.

Related to bug id: 4529323

Change-Id: I651bec718dd5b935779e7d7a050b841c2d0b0fcd
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index a73267d..007aea6 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -26,6 +26,7 @@
 class ICamera;
 class ICameraRecordingProxy;
 class IMediaRecorderClient;
+class ISurfaceTexture;
 
 class IMediaRecorder: public IInterface
 {
@@ -55,6 +56,7 @@
     virtual status_t init() = 0;
     virtual status_t close() = 0;
     virtual status_t release() = 0;
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 1c08969..ef799f5 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -26,6 +26,7 @@
 
 class ICameraRecordingProxy;
 class Surface;
+class ISurfaceTexture;
 
 struct MediaRecorderBase {
     MediaRecorderBase() {}
@@ -54,6 +55,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 sp<ISurfaceTexture> querySurfaceMediaSource() const = 0;
 
 private:
     MediaRecorderBase(const MediaRecorderBase &);
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index af12d3c..72d3736 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -31,12 +31,15 @@
 class IMediaRecorder;
 class ICamera;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
+class SurfaceTextureClient;
 
 typedef void (*media_completion_f)(status_t status, void *cookie);
 
 enum video_source {
     VIDEO_SOURCE_DEFAULT = 0,
     VIDEO_SOURCE_CAMERA = 1,
+    VIDEO_SOURCE_GRALLOC_BUFFER = 2,
 
     VIDEO_SOURCE_LIST_END  // must be last - used to validate audio source type
 };
@@ -226,6 +229,7 @@
     status_t    close();
     status_t    release();
     void        notify(int msg, int ext1, int ext2);
+    sp<ISurfaceTexture>     querySurfaceMediaSourceFromMediaServer();
 
 private:
     void                    doCleanUp();
@@ -233,6 +237,12 @@
 
     sp<IMediaRecorder>          mMediaRecorder;
     sp<MediaRecorderListener>   mListener;
+
+    // Reference toISurfaceTexture
+    // for encoding GL Frames. That is useful only when the
+    // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
+    sp<ISurfaceTexture>         mSurfaceMediaSource;
+
     media_recorder_states       mCurrentState;
     bool                        mIsAudioSourceSet;
     bool                        mIsVideoSourceSet;
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index e1852ec..d772701 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -64,8 +64,8 @@
     virtual sp<MetaData> getFormat();
 
     // Get / Set the frame rate used for encoding. Default fps = 30
-    void setFrameRate(uint32_t fps) ;
-    uint32_t getFrameRate( ) const;
+    status_t setFrameRate(int32_t fps) ;
+    int32_t getFrameRate( ) const;
 
     // The call for the StageFrightRecorder to tell us that
     // it is done using the MediaBuffer data so that its state
@@ -178,7 +178,11 @@
     void dump(String8& result, const char* prefix, char* buffer,
                                                     size_t SIZE) const;
 
-    protected:
+    // isMetaDataStoredInVideoBuffers tells the encoder whether we will
+    // pass metadata through the buffers. Currently, it is force set to true
+    bool isMetaDataStoredInVideoBuffers() const;
+
+protected:
 
     // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
     // all slots.
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a44ef5a..7e44c29 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -23,14 +23,17 @@
 #include <camera/ICamera.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
+#include <gui/ISurfaceTexture.h>
 #include <unistd.h>
 
+
 namespace android {
 
 enum {
     RELEASE = IBinder::FIRST_CALL_TRANSACTION,
     INIT,
     CLOSE,
+    QUERY_SURFACE_MEDIASOURCE,
     RESET,
     STOP,
     START,
@@ -71,6 +74,19 @@
         return reply.readInt32();
     }
 
+    sp<ISurfaceTexture> querySurfaceMediaSource()
+    {
+        LOGV("Query SurfaceMediaSource");
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply);
+        int returnedNull = reply.readInt32();
+        if (returnedNull) {
+            return NULL;
+        }
+        return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
+    }
+
     status_t setPreviewSurface(const sp<Surface>& surface)
     {
         LOGV("setPreviewSurface(%p)", surface.get());
@@ -440,6 +456,20 @@
             reply->writeInt32(setCamera(camera, proxy));
             return NO_ERROR;
         } break;
+        case QUERY_SURFACE_MEDIASOURCE: {
+            LOGV("QUERY_SURFACE_MEDIASOURCE");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            // call the mediaserver side to create
+            // a surfacemediasource
+            sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource();
+            // The mediaserver might have failed to create a source
+            int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
+            reply->writeInt32(returnedNull);
+            if (!returnedNull) {
+                reply->writeStrongBinder(surfaceMediaSource->asBinder());
+            }
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 9e4edd0..fab674c 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -25,6 +25,7 @@
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 #include <media/mediaplayer.h>  // for MEDIA_ERROR_SERVER_DIED
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -127,7 +128,9 @@
         return INVALID_OPERATION;
     }
 
+    // following call is made over the Binder Interface
     status_t ret = mMediaRecorder->setVideoSource(vs);
+
     if (OK != ret) {
         LOGV("setVideoSource failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
@@ -357,7 +360,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video size without setting video source first");
+        LOGE("Cannot set video size without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -367,9 +370,27 @@
         mCurrentState = MEDIA_RECORDER_ERROR;
         return ret;
     }
+
     return ret;
 }
 
+// Query a SurfaceMediaSurface through the Mediaserver, over the
+// binder interface. This is used by the Filter Framework (MeidaEncoder)
+// to get an <ISurfaceTexture> object to hook up to ANativeWindow.
+sp<ISurfaceTexture> MediaRecorder::
+        querySurfaceMediaSourceFromMediaServer()
+{
+    Mutex::Autolock _l(mLock);
+    mSurfaceMediaSource =
+            mMediaRecorder->querySurfaceMediaSource();
+    if (mSurfaceMediaSource == NULL) {
+        LOGE("SurfaceMediaSource could not be initialized!");
+    }
+    return mSurfaceMediaSource;
+}
+
+
+
 status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
 {
     LOGV("setVideoFrameRate(%d)", frames_per_second);
@@ -382,7 +403,7 @@
         return INVALID_OPERATION;
     }
     if (!mIsVideoSourceSet) {
-        LOGE("try to set video frame rate without setting video source first");
+        LOGE("Cannot set video frame rate without setting video source first");
         return INVALID_OPERATION;
     }
 
@@ -621,7 +642,7 @@
     return INVALID_OPERATION;
 }
 
-MediaRecorder::MediaRecorder()
+MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL)
 {
     LOGV("constructor");
 
@@ -632,6 +653,8 @@
     if (mMediaRecorder != NULL) {
         mCurrentState = MEDIA_RECORDER_IDLE;
     }
+
+
     doCleanUp();
 }
 
@@ -646,6 +669,10 @@
     if (mMediaRecorder != NULL) {
         mMediaRecorder.clear();
     }
+
+    if (mSurfaceMediaSource != NULL) {
+        mSurfaceMediaSource.clear();
+    }
 }
 
 status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 115db1a..905b885 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -41,6 +41,7 @@
 #include "MediaPlayerService.h"
 
 #include "StagefrightRecorder.h"
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -57,6 +58,20 @@
     return ok;
 }
 
+
+sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource()
+{
+    LOGV("Query SurfaceMediaSource");
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NULL;
+    }
+    return mRecorder->querySurfaceMediaSource();
+}
+
+
+
 status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
                                         const sp<ICameraRecordingProxy>& proxy)
 {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index bbca529..c87a3c0 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,45 +25,51 @@
 class MediaRecorderBase;
 class MediaPlayerService;
 class ICameraRecordingProxy;
+class ISurfaceTexture;
 
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    virtual     status_t        setCamera(const sp<ICamera>& camera,
-                                          const sp<ICameraRecordingProxy>& proxy);
-    virtual     status_t        setPreviewSurface(const sp<Surface>& surface);
-    virtual     status_t        setVideoSource(int vs);
-    virtual     status_t        setAudioSource(int as);
-    virtual     status_t        setOutputFormat(int of);
-    virtual     status_t        setVideoEncoder(int ve);
-    virtual     status_t        setAudioEncoder(int ae);
-    virtual     status_t        setOutputFile(const char* path);
-    virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
-    virtual     status_t        setOutputFileAuxiliary(int fd);
-    virtual     status_t        setVideoSize(int width, int height);
-    virtual     status_t        setVideoFrameRate(int frames_per_second);
-    virtual     status_t        setParameters(const String8& params);
-    virtual     status_t        setListener(const sp<IMediaRecorderClient>& listener);
-    virtual     status_t        prepare();
-    virtual     status_t        getMaxAmplitude(int* max);
-    virtual     status_t        start();
-    virtual     status_t        stop();
-    virtual     status_t        reset();
-    virtual     status_t        init();
-    virtual     status_t        close();
-    virtual     status_t        release();
+    virtual     status_t   setCamera(const sp<ICamera>& camera,
+                                    const sp<ICameraRecordingProxy>& proxy);
+    virtual     status_t   setPreviewSurface(const sp<Surface>& surface);
+    virtual     status_t   setVideoSource(int vs);
+    virtual     status_t   setAudioSource(int as);
+    virtual     status_t   setOutputFormat(int of);
+    virtual     status_t   setVideoEncoder(int ve);
+    virtual     status_t   setAudioEncoder(int ae);
+    virtual     status_t   setOutputFile(const char* path);
+    virtual     status_t   setOutputFile(int fd, int64_t offset,
+                                                  int64_t length);
+    virtual     status_t   setOutputFileAuxiliary(int fd);
+    virtual     status_t   setVideoSize(int width, int height);
+    virtual     status_t   setVideoFrameRate(int frames_per_second);
+    virtual     status_t   setParameters(const String8& params);
+    virtual     status_t   setListener(
+                              const sp<IMediaRecorderClient>& listener);
+    virtual     status_t   prepare();
+    virtual     status_t   getMaxAmplitude(int* max);
+    virtual     status_t   start();
+    virtual     status_t   stop();
+    virtual     status_t   reset();
+    virtual     status_t   init();
+    virtual     status_t   close();
+    virtual     status_t   release();
+    virtual     status_t   dump(int fd, const Vector<String16>& args) const;
+    virtual     sp<ISurfaceTexture> querySurfaceMediaSource();
 
-    virtual     status_t        dump(int fd, const Vector<String16>& args) const;
 private:
-    friend class                MediaPlayerService;  // for accessing private constructor
+    friend class           MediaPlayerService;  // for accessing private constructor
 
-                                MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
-    virtual                     ~MediaRecorderClient();
+                           MediaRecorderClient(
+                                   const sp<MediaPlayerService>& service,
+                                                               pid_t pid);
+    virtual                ~MediaRecorderClient();
 
-    pid_t                       mPid;
-    Mutex                       mLock;
-    MediaRecorderBase           *mRecorder;
-    sp<MediaPlayerService>      mMediaPlayerService;
+    pid_t                  mPid;
+    Mutex                  mLock;
+    MediaRecorderBase      *mRecorder;
+    sp<MediaPlayerService> mMediaPlayerService;
 };
 
 }; // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 223e0be..6427bb7 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -38,10 +38,12 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SurfaceMediaSource.h>
 #include <media/MediaProfiles.h>
 #include <camera/ICamera.h>
 #include <camera/CameraParameters.h>
 #include <surfaceflinger/Surface.h>
+
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
@@ -69,7 +71,7 @@
       mOutputFd(-1), mOutputFdAux(-1),
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
-      mStarted(false) {
+      mStarted(false), mSurfaceMediaSource(NULL) {
 
     LOGV("Constructor");
     reset();
@@ -85,6 +87,14 @@
     return OK;
 }
 
+// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// and return a interface reference. The client side will use that
+// while encoding GL Frames
+sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const {
+    LOGV("Get SurfaceMediaSource");
+    return mSurfaceMediaSource;
+}
+
 status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
     LOGV("setAudioSource: %d", as);
     if (as < AUDIO_SOURCE_DEFAULT ||
@@ -1006,13 +1016,13 @@
         source = createAudioSource();
     } else {
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &source);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &source);
         if (err != OK) {
             return err;
         }
@@ -1042,20 +1052,19 @@
         }
     }
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
         if (mVideoEncoder != VIDEO_ENCODER_H264) {
             return ERROR_UNSUPPORTED;
         }
 
-        sp<CameraSource> cameraSource;
-        status_t err = setupCameraSource(&cameraSource);
+        sp<MediaSource> mediaSource;
+        status_t err = setupMediaSource(&mediaSource);
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraSource, mVideoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
 
         if (err != OK) {
             return err;
@@ -1289,6 +1298,60 @@
     }
 }
 
+// Set up the appropriate MediaSource depending on the chosen option
+status_t StagefrightRecorder::setupMediaSource(
+                      sp<MediaSource> *mediaSource) {
+    if (mVideoSource == VIDEO_SOURCE_DEFAULT
+            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+        sp<CameraSource> cameraSource;
+        status_t err = setupCameraSource(&cameraSource);
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = cameraSource;
+    } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+        // If using GRAlloc buffers, setup surfacemediasource.
+        // Later a handle to that will be passed
+        // to the client side when queried
+        status_t err = setupSurfaceMediaSource();
+        if (err != OK) {
+            return err;
+        }
+        *mediaSource = mSurfaceMediaSource;
+    } else {
+        return INVALID_OPERATION;
+    }
+    return OK;
+}
+
+// setupSurfaceMediaSource creates a source with the given
+// width and height and framerate.
+// TODO: This could go in a static function inside SurfaceMediaSource
+// similar to that in CameraSource
+status_t StagefrightRecorder::setupSurfaceMediaSource() {
+    status_t err = OK;
+    mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight);
+    if (mSurfaceMediaSource == NULL) {
+        return NO_INIT;
+    }
+
+    if (mFrameRate == -1) {
+        int32_t frameRate = 0;
+        CHECK (mSurfaceMediaSource->getFormat()->findInt32(
+                                        kKeyFrameRate, &frameRate));
+        LOGI("Frame rate is not explicitly set. Use the current frame "
+             "rate (%d fps)", frameRate);
+        mFrameRate = frameRate;
+    } else {
+        err = mSurfaceMediaSource->setFrameRate(mFrameRate);
+    }
+    CHECK(mFrameRate != -1);
+
+    mIsMetaDataStoredInVideoBuffers =
+        mSurfaceMediaSource->isMetaDataStoredInVideoBuffers();
+    return err;
+}
+
 status_t StagefrightRecorder::setupCameraSource(
         sp<CameraSource> *cameraSource) {
     status_t err = OK;
@@ -1465,29 +1528,37 @@
     status_t err = OK;
     sp<MediaWriter> writer = new MPEG4Writer(outputFd);
 
-    if (mVideoSource == VIDEO_SOURCE_DEFAULT
-            || mVideoSource == VIDEO_SOURCE_CAMERA) {
+    if (mVideoSource < VIDEO_SOURCE_LIST_END) {
 
-        sp<MediaSource> cameraMediaSource;
+        sp<MediaSource> mediaSource;
         if (useSplitCameraSource) {
+            // TODO: Check if there is a better way to handle this
+            if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+                LOGE("Cannot use split camera when encoding frames");
+                return INVALID_OPERATION;
+            }
             LOGV("Using Split camera source");
-            cameraMediaSource = mCameraSourceSplitter->createClient();
+            mediaSource = mCameraSourceSplitter->createClient();
         } else {
-            sp<CameraSource> cameraSource;
-            err = setupCameraSource(&cameraSource);
-            cameraMediaSource = cameraSource;
+           err = setupMediaSource(&mediaSource);
         }
+
         if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) {
+            // TODO: Might be able to handle downsampling even if using GRAlloc
+            if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+                LOGE("Cannot change size or Downsample when encoding frames");
+                return INVALID_OPERATION;
+            }
             // Use downsampling from the original source.
-            cameraMediaSource =
-                new VideoSourceDownSampler(cameraMediaSource, videoWidth, videoHeight);
+            mediaSource =
+                new VideoSourceDownSampler(mediaSource, videoWidth, videoHeight);
         }
         if (err != OK) {
             return err;
         }
 
         sp<MediaSource> encoder;
-        err = setupVideoEncoder(cameraMediaSource, videoBitRate, &encoder);
+        err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
         if (err != OK) {
             return err;
         }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 034b373..1618b92 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -36,6 +36,8 @@
 class MetaData;
 struct AudioSource;
 class MediaProfiles;
+class ISurfaceTexture;
+class SurfaceMediaSource;
 
 struct StagefrightRecorder : public MediaRecorderBase {
     StagefrightRecorder();
@@ -64,6 +66,8 @@
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
     virtual status_t dump(int fd, const Vector<String16>& args) const;
+    // Querying a SurfaceMediaSourcer
+    virtual sp<ISurfaceTexture> querySurfaceMediaSource() const;
 
 private:
     sp<ICamera> mCamera;
@@ -109,12 +113,18 @@
     sp<MediaSourceSplitter> mCameraSourceSplitter;
     sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
 
+
     String8 mParams;
 
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     bool mStarted;
+    // Needed when GLFrames are encoded.
+    // An <ISurfaceTexture> pointer
+    // will be sent to the client side using which the
+    // frame buffers will be queued and dequeued
+    sp<SurfaceMediaSource> mSurfaceMediaSource;
 
     status_t setupMPEG4Recording(
         bool useSplitCameraSource,
@@ -134,7 +144,14 @@
     sp<MediaSource> createAudioSource();
     status_t checkVideoEncoderCapabilities();
     status_t checkAudioEncoderCapabilities();
+    // Generic MediaSource set-up. Returns the appropriate
+    // source (CameraSource or SurfaceMediaSource)
+    // depending on the videosource type
+    status_t setupMediaSource(sp<MediaSource> *mediaSource);
     status_t setupCameraSource(sp<CameraSource> *cameraSource);
+    // setup the surfacemediasource for the encoder
+    status_t setupSurfaceMediaSource();
+
     status_t setupAudioEncoder(const sp<MediaWriter>& writer);
     status_t setupVideoEncoder(
             sp<MediaSource> cameraSource,
@@ -176,6 +193,7 @@
     void clipNumberOfAudioChannels();
     void setDefaultProfileIfNecessary();
 
+
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
 };
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index db208dd..ecacf64 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -35,18 +35,18 @@
 namespace android {
 
 SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
-    mDefaultWidth(bufW),
-    mDefaultHeight(bufH),
-    mPixelFormat(0),
-    mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
-    mClientBufferCount(0),
-    mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
-    mCurrentSlot(INVALID_BUFFER_SLOT),
-    mCurrentTimestamp(0),
-    mSynchronousMode(true),
-    mConnectedApi(NO_CONNECTED_API),
-    mFrameRate(30),
-    mStarted(false)     {
+                mDefaultWidth(bufW),
+                mDefaultHeight(bufH),
+                mPixelFormat(0),
+                mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mClientBufferCount(0),
+                mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+                mCurrentSlot(INVALID_BUFFER_SLOT),
+                mCurrentTimestamp(0),
+                mSynchronousMode(true),
+                mConnectedApi(NO_CONNECTED_API),
+                mFrameRate(30),
+                mStarted(false)   {
     LOGV("SurfaceMediaSource::SurfaceMediaSource");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -372,7 +372,7 @@
 status_t SurfaceMediaSource::connect(int api) {
     LOGV("SurfaceMediaSource::connect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
+    status_t err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
         case NATIVE_WINDOW_API_CPU:
@@ -394,7 +394,7 @@
 status_t SurfaceMediaSource::disconnect(int api) {
     LOGV("SurfaceMediaSource::disconnect");
     Mutex::Autolock lock(mMutex);
-    int err = NO_ERROR;
+    status_t err = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
         case NATIVE_WINDOW_API_CPU:
@@ -625,13 +625,23 @@
     }
 }
 
-void SurfaceMediaSource::setFrameRate(uint32_t fps)
+status_t SurfaceMediaSource::setFrameRate(int32_t fps)
 {
     Mutex::Autolock lock(mMutex);
+    const int MAX_FRAME_RATE = 60;
+    if (fps < 0 || fps > MAX_FRAME_RATE) {
+        return BAD_VALUE;
+    }
     mFrameRate = fps;
+    return OK;
 }
 
-uint32_t SurfaceMediaSource::getFrameRate( ) const {
+bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
+    LOGV("isMetaDataStoredInVideoBuffers");
+    return true;
+}
+
+int32_t SurfaceMediaSource::getFrameRate( ) const {
     Mutex::Autolock lock(mMutex);
     return mFrameRate;
 }
@@ -663,8 +673,7 @@
     LOGV("getFormat");
     Mutex::Autolock autoLock(mMutex);
     sp<MetaData> meta = new MetaData;
-    // XXX: Check if this is right. or should we wait on some
-    // condition?
+
     meta->setInt32(kKeyWidth, mDefaultWidth);
     meta->setInt32(kKeyHeight, mDefaultHeight);
     // The encoder format is set as an opaque colorformat