Extractor service

Run extractors in a separate process. Currently all data is copied through a
binder transaction, and WVMExtractor is still run in the mediaserver process.

Change-Id: Ic5dbce87126dd321ad792f4dd540c2ff6b068d13
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 20c0094..05fa34f 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -35,7 +35,7 @@
         record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -59,7 +59,7 @@
         recordvideo.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -84,7 +84,7 @@
         audioloop.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 6e9e6ec..db0c12d 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -109,7 +109,7 @@
         meta->setInt32(kKeyMaxInputSize, maxInputSize);
     }
 
-    sp<MediaSource> encoder = OMXCodec::Create(
+    sp<IMediaSource> encoder = OMXCodec::Create(
             client.interface(),
             meta, true /* createEncoder */,
             source);
@@ -128,7 +128,7 @@
         writer->stop();
     } else {
         // otherwise decode to speaker
-        sp<MediaSource> decoder = OMXCodec::Create(
+        sp<IMediaSource> decoder = OMXCodec::Create(
                 client.interface(),
                 meta, false /* createEncoder */,
                 encoder);
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 594c933..cd9c8dc 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -325,7 +325,7 @@
     encMeta->setInt32(kKeyMaxInputSize, 8192);
     encMeta->setInt32(kKeyBitRate, kAudioBitRate);
 
-    sp<MediaSource> encoder =
+    sp<IMediaSource> encoder =
         OMXCodec::Create(client.interface(), encMeta, true, audioSource);
 
     encoder->start();
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 2ad40bd..05b50be 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -299,7 +299,7 @@
         enc_meta->setInt32(kKeyVideoProfile, profile);
     }
 
-    sp<MediaSource> encoder =
+    sp<IMediaSource> encoder =
         OMXCodec::Create(
                 client.interface(), enc_meta, true /* createEncoder */, source,
                 0, preferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 0d64d2f..1a4bf08 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -118,7 +118,7 @@
                     DataSource::CreateFromURI(
                             NULL /* httpService */, mURI.c_str());
 
-                sp<MediaExtractor> extractor =
+                sp<IMediaExtractor> extractor =
                     MediaExtractor::Create(dataSource);
 
                 for (size_t i = 0; i < extractor->countTracks(); ++i) {
@@ -264,7 +264,7 @@
     sp<Surface> mSurface;
     bool mRenderToSurface;
     sp<ACodec> mCodec;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     bool mIsVorbis;
 
     Vector<sp<ABuffer> > mCSD;
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 9368309..d9023cc 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -130,7 +130,7 @@
     }
 }
 
-static void dumpSource(const sp<MediaSource> &source, const String8 &filename) {
+static void dumpSource(const sp<IMediaSource> &source, const String8 &filename) {
     FILE *out = fopen(filename.string(), "wb");
 
     CHECK_EQ((status_t)OK, source->start());
@@ -163,13 +163,13 @@
     out = NULL;
 }
 
-static void playSource(OMXClient *client, sp<MediaSource> &source) {
+static void playSource(OMXClient *client, sp<IMediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
-    sp<MediaSource> rawSource;
+    sp<IMediaSource> rawSource;
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
         rawSource = source;
     } else {
@@ -397,7 +397,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 struct DetectSyncSource : public MediaSource {
-    DetectSyncSource(const sp<MediaSource> &source);
+    DetectSyncSource(const sp<IMediaSource> &source);
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -414,14 +414,14 @@
         OTHER,
     };
 
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     StreamType mStreamType;
     bool mSawFirstIDRFrame;
 
     DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
 };
 
-DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
+DetectSyncSource::DetectSyncSource(const sp<IMediaSource> &source)
     : mSource(source),
       mStreamType(OTHER),
       mSawFirstIDRFrame(false) {
@@ -503,7 +503,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 static void writeSourcesToMP4(
-        Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
+        Vector<sp<IMediaSource> > &sources, bool syncInfoPresent) {
 #if 0
     sp<MPEG4Writer> writer =
         new MPEG4Writer(gWriteMP4Filename.string());
@@ -521,7 +521,7 @@
     writer->setMaxFileDuration(60000000ll);
 
     for (size_t i = 0; i < sources.size(); ++i) {
-        sp<MediaSource> source = sources.editItemAt(i);
+        sp<IMediaSource> source = sources.editItemAt(i);
 
         CHECK_EQ(writer->addSource(
                     syncInfoPresent ? source : new DetectSyncSource(source)),
@@ -538,7 +538,7 @@
     writer->stop();
 }
 
-static void performSeekTest(const sp<MediaSource> &source) {
+static void performSeekTest(const sp<IMediaSource> &source) {
     CHECK_EQ((status_t)OK, source->start());
 
     int64_t durationUs;
@@ -985,8 +985,8 @@
             isJPEG = true;
         }
 
-        Vector<sp<MediaSource> > mediaSources;
-        sp<MediaSource> mediaSource;
+        Vector<sp<IMediaSource> > mediaSources;
+        sp<IMediaSource> mediaSource;
 
         if (isJPEG) {
             mediaSource = new JPEGSource(dataSource);
@@ -1005,7 +1005,7 @@
                 mediaSources.push(mediaSource);
             }
         } else {
-            sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+            sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
 
             if (extractor == NULL) {
                 fprintf(stderr, "could not create extractor.\n");
@@ -1032,7 +1032,7 @@
                 bool haveAudio = false;
                 bool haveVideo = false;
                 for (size_t i = 0; i < numTracks; ++i) {
-                    sp<MediaSource> source = extractor->getTrack(i);
+                    sp<IMediaSource> source = extractor->getTrack(i);
 
                     const char *mime;
                     CHECK(source->getFormat()->findCString(
@@ -1106,7 +1106,7 @@
             OMXClient client;
             CHECK_EQ(client.connect(), (status_t)OK);
 
-            sp<MediaSource> decSource =
+            sp<IMediaSource> decSource =
                 OMXCodec::Create(
                         client.interface(),
                         mediaSource->getFormat(),
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 1a40e53..bca3832 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -165,7 +165,7 @@
 
     CHECK(dataSource != NULL);
 
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
     CHECK(extractor != NULL);
 
     mWriter = new MPEG2TSWriter(
diff --git a/include/media/IMediaExtractor.h b/include/media/IMediaExtractor.h
new file mode 100644
index 0000000..9f7a719
--- /dev/null
+++ b/include/media/IMediaExtractor.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMEDIA_EXTRACTOR_BASE_H_
+
+#define IMEDIA_EXTRACTOR_BASE_H_
+
+#include <media/IMediaSource.h>
+
+namespace android {
+
+class MetaData;
+
+class IMediaExtractor : public IInterface {
+public:
+    DECLARE_META_INTERFACE(MediaExtractor);
+
+    virtual size_t countTracks() = 0;
+    virtual sp<IMediaSource> getTrack(size_t index) = 0;
+
+    enum GetTrackMetaDataFlags {
+        kIncludeExtensiveMetaData = 1
+    };
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags = 0) = 0;
+
+    // Return container specific meta-data. The default implementation
+    // returns an empty metadata object.
+    virtual sp<MetaData> getMetaData() = 0;
+
+    enum Flags {
+        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
+        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
+        CAN_PAUSE          = 4,
+        CAN_SEEK           = 8,  // the "seek bar"
+    };
+
+    // If subclasses do _not_ override this, the default is
+    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
+    virtual uint32_t flags() const = 0;
+
+    // for DRM
+    virtual void setDrmFlag(bool flag) = 0;
+    virtual bool getDrmFlag() = 0;
+    virtual char* getDrmTrackInfo(size_t trackID, int *len)  = 0;
+    virtual void setUID(uid_t uid)  = 0;
+
+    virtual const char * name() = 0;
+};
+
+
+class BnMediaExtractor: public BnInterface<IMediaExtractor>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+
+}  // namespace android
+
+#endif  // IMEDIA_EXTRACTOR_BASE_H_
diff --git a/include/media/IMediaExtractorService.h b/include/media/IMediaExtractorService.h
new file mode 100644
index 0000000..4d7b317
--- /dev/null
+++ b/include/media/IMediaExtractorService.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IMEDIAEXTRACTORSERVICE_H
+#define ANDROID_IMEDIAEXTRACTORSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <media/IDataSource.h>
+#include <media/IMediaExtractor.h>
+
+namespace android {
+
+class IMediaExtractorService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaExtractorService);
+
+    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
+
+};
+
+class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+}   // namespace android
+
+#endif  // ANDROID_IMEDIAEXTRACTORSERVICE_H
diff --git a/include/media/IMediaSource.h b/include/media/IMediaSource.h
new file mode 100644
index 0000000..1420120
--- /dev/null
+++ b/include/media/IMediaSource.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IMEDIA_SOURCE_BASE_H_
+
+#define IMEDIA_SOURCE_BASE_H_
+
+#include <binder/IInterface.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct MediaSource;
+class MetaData;
+class MediaBuffer;
+
+class IMediaSource : public IInterface {
+public:
+    DECLARE_META_INTERFACE(MediaSource);
+
+    // To be called before any other methods on this object, except
+    // getFormat().
+    virtual status_t start(MetaData *params = NULL) = 0;
+
+    // Any blocking read call returns immediately with a result of NO_INIT.
+    // It is an error to call any methods other than start after this call
+    // returns. Any buffers the object may be holding onto at the time of
+    // the stop() call are released.
+    // Also, it is imperative that any buffers output by this object and
+    // held onto by callers be released before a call to stop() !!!
+    virtual status_t stop() = 0;
+
+    // Returns the format of the data output by this media source.
+    virtual sp<MetaData> getFormat() = 0;
+
+    // Options that modify read() behaviour. The default is to
+    // a) not request a seek
+    // b) not be late, i.e. lateness_us = 0
+    struct ReadOptions {
+        enum SeekMode {
+            SEEK_PREVIOUS_SYNC,
+            SEEK_NEXT_SYNC,
+            SEEK_CLOSEST_SYNC,
+            SEEK_CLOSEST,
+        };
+
+        ReadOptions();
+
+        // Reset everything back to defaults.
+        void reset();
+
+        void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
+        void clearSeekTo();
+        bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
+
+        void setLateBy(int64_t lateness_us);
+        int64_t getLateBy() const;
+
+        void setNonBlocking();
+        void clearNonBlocking();
+        bool getNonBlocking() const;
+
+    private:
+        enum Options {
+            kSeekTo_Option      = 1,
+        };
+
+        uint32_t mOptions;
+        int64_t mSeekTimeUs;
+        SeekMode mSeekMode;
+        int64_t mLatenessUs;
+        bool mNonBlocking;
+    };
+
+    // Returns a new buffer of data. Call blocks until a
+    // buffer is available, an error is encountered of the end of the stream
+    // is reached.
+    // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+    // A result of INFO_FORMAT_CHANGED indicates that the format of this
+    // MediaSource has changed mid-stream, the client can continue reading
+    // but should be prepared for buffers of the new configuration.
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
+
+    // Causes this source to suspend pulling data from its upstream source
+    // until a subsequent read-with-seek. Currently only supported by
+    // OMXCodec.
+    virtual status_t pause()  = 0;
+
+    // The consumer of this media source requests that the given buffers
+    // are to be returned exclusively in response to read calls.
+    // This will be called after a successful start() and before the
+    // first read() call.
+    // Callee assumes ownership of the buffers if no error is returned.
+    virtual status_t setBuffers(const Vector<MediaBuffer *> & /* buffers */) = 0;
+
+};
+
+class BnMediaSource: public BnInterface<IMediaSource>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+
+    virtual status_t pause() {
+        return ERROR_UNSUPPORTED;
+    }
+
+    virtual status_t setBuffers(const Vector<MediaBuffer *> & /* buffers */) {
+        return ERROR_UNSUPPORTED;
+    }
+};
+
+
+}  // namespace android
+
+#endif  // IMEDIA_SOURCE_BASE_H_
diff --git a/include/media/stagefright/AACWriter.h b/include/media/stagefright/AACWriter.h
index aa60a19..a1f63d7 100644
--- a/include/media/stagefright/AACWriter.h
+++ b/include/media/stagefright/AACWriter.h
@@ -31,7 +31,7 @@
 
     status_t initCheck() const;
 
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
     virtual bool reachedEOS();
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop() { return reset(); }
@@ -48,7 +48,7 @@
 
     int   mFd;
     status_t mInitCheck;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     bool mStarted;
     volatile bool mPaused;
     volatile bool mResumed;
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index b38be55..fbbdf2e 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -20,12 +20,12 @@
 
 #include <stdio.h>
 
+#include <media/IMediaSource.h>
 #include <media/stagefright/MediaWriter.h>
 #include <utils/threads.h>
 
 namespace android {
 
-struct MediaSource;
 class MetaData;
 
 struct AMRWriter : public MediaWriter {
@@ -33,7 +33,7 @@
 
     status_t initCheck() const;
 
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
     virtual bool reachedEOS();
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop() { return reset(); }
@@ -45,7 +45,7 @@
 private:
     int   mFd;
     status_t mInitCheck;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     bool mStarted;
     volatile bool mPaused;
     volatile bool mResumed;
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index e0cd965..b495f91 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -18,6 +18,7 @@
 
 #define AUDIO_PLAYER_H_
 
+#include <media/IMediaSource.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/TimeSource.h>
@@ -28,7 +29,6 @@
 struct AudioPlaybackRate;
 class AudioTrack;
 struct AwesomePlayer;
-class MediaSource;
 
 class AudioPlayer : public TimeSource {
 public:
@@ -52,7 +52,7 @@
     virtual ~AudioPlayer();
 
     // Caller retains ownership of "source".
-    void setSource(const sp<MediaSource> &source);
+    void setSource(const sp<IMediaSource> &source);
 
     // Return time in us.
     virtual int64_t getRealTimeUs();
@@ -81,7 +81,7 @@
 
 private:
     friend class VideoEditorAudioPlayer;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     sp<AudioTrack> mAudioTrack;
 
     MediaBuffer *mInputBuffer;
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index 3d7960b..4516fb6 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -34,7 +34,7 @@
             void *cookie,
             ssize_t (*write)(void *cookie, const void *data, size_t size));
 
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
     virtual status_t start(MetaData *param = NULL);
     virtual status_t stop() { return reset(); }
     virtual status_t pause();
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index a195fe8..a6901a8 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 
+#include <media/IMediaSource.h>
 #include <media/stagefright/MediaWriter.h>
 #include <utils/List.h>
 #include <utils/threads.h>
@@ -28,7 +29,6 @@
 
 class AMessage;
 class MediaBuffer;
-class MediaSource;
 class MetaData;
 
 class MPEG4Writer : public MediaWriter {
@@ -39,7 +39,7 @@
     // 1. No more than 2 tracks can be added
     // 2. Only video or audio source can be added
     // 3. No more than one video and/or one audio source can be added.
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
 
     // Returns INVALID_OPERATION if there is no source or track.
     virtual status_t start(MetaData *param = NULL);
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 183933a..6bf8c9e 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -18,7 +18,8 @@
 
 #define MEDIA_EXTRACTOR_H_
 
-#include <utils/RefBase.h>
+#include <media/IMediaExtractor.h>
+#include <media/IMediaSource.h>
 
 namespace android {
 
@@ -26,13 +27,15 @@
 class MediaSource;
 class MetaData;
 
-class MediaExtractor : public RefBase {
+class MediaExtractor : public BnMediaExtractor {
 public:
-    static sp<MediaExtractor> Create(
+    static sp<IMediaExtractor> Create(
+            const sp<DataSource> &source, const char *mime = NULL);
+    static sp<MediaExtractor> CreateFromService(
             const sp<DataSource> &source, const char *mime = NULL);
 
     virtual size_t countTracks() = 0;
-    virtual sp<MediaSource> getTrack(size_t index) = 0;
+    virtual sp<IMediaSource> getTrack(size_t index) = 0;
 
     enum GetTrackMetaDataFlags {
         kIncludeExtensiveMetaData = 1
@@ -68,8 +71,10 @@
     virtual void setUID(uid_t uid) {
     }
 
+    virtual const char * name() { return "<unspecified>"; }
+
 protected:
-    MediaExtractor() : mIsDrm(false) {}
+    MediaExtractor();
     virtual ~MediaExtractor() {}
 
 private:
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index a653db9..78da861 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 
+#include <media/IMediaSource.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
@@ -29,7 +30,7 @@
 class MediaBuffer;
 class MetaData;
 
-struct MediaSource : public virtual RefBase {
+struct MediaSource : public BnMediaSource {
     MediaSource();
 
     // To be called before any other methods on this object, except
@@ -47,8 +48,6 @@
     // Returns the format of the data output by this media source.
     virtual sp<MetaData> getFormat() = 0;
 
-    struct ReadOptions;
-
     // Returns a new buffer of data. Call blocks until a
     // buffer is available, an error is encountered of the end of the stream
     // is reached.
@@ -59,45 +58,6 @@
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
 
-    // Options that modify read() behaviour. The default is to
-    // a) not request a seek
-    // b) not be late, i.e. lateness_us = 0
-    struct ReadOptions {
-        enum SeekMode {
-            SEEK_PREVIOUS_SYNC,
-            SEEK_NEXT_SYNC,
-            SEEK_CLOSEST_SYNC,
-            SEEK_CLOSEST,
-        };
-
-        ReadOptions();
-
-        // Reset everything back to defaults.
-        void reset();
-
-        void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
-        void clearSeekTo();
-        bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
-
-        void setLateBy(int64_t lateness_us);
-        int64_t getLateBy() const;
-
-        void setNonBlocking();
-        void clearNonBlocking();
-        bool getNonBlocking() const;
-
-    private:
-        enum Options {
-            kSeekTo_Option      = 1,
-        };
-
-        uint32_t mOptions;
-        int64_t mSeekTimeUs;
-        SeekMode mSeekMode;
-        int64_t mLatenessUs;
-        bool mNonBlocking;
-    };
-
     // Causes this source to suspend pulling data from its upstream source
     // until a subsequent read-with-seek. Currently only supported by
     // OMXCodec.
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index 8e02506..b6476c9 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -20,10 +20,10 @@
 
 #include <utils/RefBase.h>
 #include <media/IMediaRecorderClient.h>
+#include <media/IMediaSource.h>
 
 namespace android {
 
-struct MediaSource;
 class MetaData;
 
 struct MediaWriter : public RefBase {
@@ -32,7 +32,7 @@
           mMaxFileDurationLimitUs(0) {
     }
 
-    virtual status_t addSource(const sp<MediaSource> &source) = 0;
+    virtual status_t addSource(const sp<IMediaSource> &source) = 0;
     virtual bool reachedEOS() = 0;
     virtual status_t start(MetaData *params = NULL) = 0;
     virtual status_t stop() = 0;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 8d4e15a..59686ed 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -22,6 +22,7 @@
 
 #include <stdint.h>
 
+#include <binder/Parcel.h>
 #include <utils/RefBase.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
@@ -239,6 +240,10 @@
 
     void dumpToLog() const;
 
+    status_t writeToParcel(Parcel &parcel);
+    status_t updateFromParcel(const Parcel &parcel);
+    static sp<MetaData> createFromParcel(const Parcel &parcel);
+
 protected:
     virtual ~MetaData();
 
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
index fd74452..1ba9545 100644
--- a/include/media/stagefright/NuMediaExtractor.h
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -19,6 +19,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/MediaSource.h>
+#include <media/IMediaExtractor.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -84,7 +85,7 @@
     };
 
     struct TrackInfo {
-        sp<MediaSource> mSource;
+        sp<IMediaSource> mSource;
         size_t mTrackIndex;
         status_t mFinalResult;
         MediaBuffer *mSample;
@@ -97,7 +98,7 @@
 
     sp<DataSource> mDataSource;
 
-    sp<MediaExtractor> mImpl;
+    sp<IMediaExtractor> mImpl;
     bool mIsWidevineExtractor;
 
     Vector<TrackInfo> mSelectedTracks;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 7fabcb3..03ca88b 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -34,7 +34,7 @@
 struct CodecProfileLevel;
 class SkipCutBuffer;
 
-struct OMXCodec : public MediaSource,
+struct OMXCodec : public BnMediaSource,
                   public MediaBufferObserver {
     enum CreationFlags {
         kPreferSoftwareCodecs    = 1,
@@ -61,10 +61,10 @@
         // Secure decoding mode
         kUseSecureInputBuffers = 256,
     };
-    static sp<MediaSource> Create(
+    static sp<IMediaSource> Create(
             const sp<IOMX> &omx,
             const sp<MetaData> &meta, bool createEncoder,
-            const sp<MediaSource> &source,
+            const sp<IMediaSource> &source,
             const char *matchComponentName = NULL,
             uint32_t flags = 0,
             const sp<ANativeWindow> &nativeWindow = NULL);
@@ -189,7 +189,7 @@
     char *mMIME;
     char *mComponentName;
     sp<MetaData> mOutputFormat;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     Vector<CodecSpecificData *> mCodecSpecificData;
     size_t mCodecSpecificDataIndex;
 
@@ -234,7 +234,7 @@
     OMXCodec(const sp<IOMX> &omx, IOMX::node_id node,
              uint32_t quirks, uint32_t flags,
              bool isEncoder, const char *mime, const char *componentName,
-             const sp<MediaSource> &source,
+             const sp<IMediaSource> &source,
              const sp<ANativeWindow> &nativeWindow);
 
     void addCodecSpecificData(const void *data, size_t size);
diff --git a/include/media/stagefright/timedtext/TimedTextDriver.h b/include/media/stagefright/timedtext/TimedTextDriver.h
index 6f7c693..6e699a6 100644
--- a/include/media/stagefright/timedtext/TimedTextDriver.h
+++ b/include/media/stagefright/timedtext/TimedTextDriver.h
@@ -17,6 +17,7 @@
 #ifndef TIMED_TEXT_DRIVER_H_
 #define TIMED_TEXT_DRIVER_H_
 
+#include <media/IMediaSource.h>
 #include <media/stagefright/foundation/ABase.h> // for DISALLOW_* macro
 #include <utils/Errors.h> // for status_t
 #include <utils/RefBase.h>
@@ -27,7 +28,6 @@
 struct ALooper;
 struct IMediaHTTPService;
 class MediaPlayerBase;
-class MediaSource;
 class Parcel;
 class TimedTextPlayer;
 class TimedTextSource;
@@ -49,7 +49,7 @@
     status_t seekToAsync(int64_t timeUs);
 
     status_t addInBandTextSource(
-            size_t trackIndex, const sp<MediaSource>& source);
+            size_t trackIndex, const sp<IMediaSource>& source);
 
     status_t addOutOfBandTextSource(
             size_t trackIndex, const char *uri, const char *mimeType);
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index be88aa0..285c33e 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -33,11 +33,14 @@
     IMediaHTTPConnection.cpp \
     IMediaHTTPService.cpp \
     IMediaLogService.cpp \
+    IMediaExtractor.cpp           \
+    IMediaExtractorService.cpp \
     IMediaPlayerService.cpp \
     IMediaPlayerClient.cpp \
     IMediaRecorderClient.cpp \
     IMediaPlayer.cpp \
     IMediaRecorder.cpp \
+    IMediaSource.cpp \
     IRemoteDisplay.cpp \
     IRemoteDisplayClient.cpp \
     IResourceManagerClient.cpp \
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
new file mode 100644
index 0000000..85362fd
--- /dev/null
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "BpMediaExtractor"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <media/IMediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+enum {
+    COUNTTRACKS = IBinder::FIRST_CALL_TRANSACTION,
+    GETTRACK,
+    GETTRACKMETADATA,
+    GETMETADATA,
+    FLAGS,
+    SETDRMFLAG,
+    GETDRMFLAG,
+    GETDRMTRACKINFO,
+    SETUID,
+    NAME
+};
+
+class BpMediaExtractor : public BpInterface<IMediaExtractor> {
+public:
+    BpMediaExtractor(const sp<IBinder>& impl)
+        : BpInterface<IMediaExtractor>(impl)
+    {
+    }
+
+    virtual size_t countTracks() {
+        ALOGV("countTracks");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        status_t ret = remote()->transact(COUNTTRACKS, data, &reply);
+        size_t numTracks = 0;
+        if (ret == NO_ERROR) {
+            numTracks = reply.readUint32();
+        }
+        return numTracks;
+    }
+    virtual sp<IMediaSource> getTrack(size_t index) {
+        ALOGV("getTrack(%zu)", index);
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        data.writeUint32(index);
+        status_t ret = remote()->transact(GETTRACK, data, &reply);
+        if (ret == NO_ERROR) {
+            return interface_cast<IMediaSource>(reply.readStrongBinder());
+        }
+        return NULL;
+    }
+
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags) {
+        ALOGV("getTrackMetaData(%zu, %u)", index, flags);
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        data.writeUint32(index);
+        data.writeUint32(flags);
+        status_t ret = remote()->transact(GETTRACKMETADATA, data, &reply);
+        if (ret == NO_ERROR) {
+            return MetaData::createFromParcel(reply);
+        }
+        return NULL;
+    }
+
+    virtual sp<MetaData> getMetaData() {
+        ALOGV("getMetaData");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
+        status_t ret = remote()->transact(GETMETADATA, data, &reply);
+        if (ret == NO_ERROR) {
+            return MetaData::createFromParcel(reply);
+        }
+        return NULL;
+    }
+
+    virtual uint32_t flags() const {
+        ALOGV("flags NOT IMPLEMENTED");
+        return 0;
+    }
+
+    virtual void setDrmFlag(bool flag __unused) {
+        ALOGV("setDrmFlag NOT IMPLEMENTED");
+    }
+    virtual bool getDrmFlag() {
+        ALOGV("getDrmFlag NOT IMPLEMENTED");
+       return false;
+    }
+    virtual char* getDrmTrackInfo(size_t trackID __unused, int *len __unused) {
+        ALOGV("getDrmTrackInfo NOT IMPLEMENTED");
+        return NULL;
+    }
+    virtual void setUID(uid_t uid __unused) {
+        ALOGV("setUID NOT IMPLEMENTED");
+    }
+
+    virtual const char * name() {
+        ALOGV("name NOT IMPLEMENTED");
+        return NULL;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
+
+#undef LOG_TAG
+#define LOG_TAG "BnMediaExtractor"
+
+status_t BnMediaExtractor::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case COUNTTRACKS: {
+            ALOGV("countTracks");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            size_t numTracks = countTracks();
+            if (numTracks > INT32_MAX) {
+                numTracks = 0;
+            }
+            reply->writeUint32(uint32_t(numTracks));
+            return NO_ERROR;
+        }
+        case GETTRACK: {
+            ALOGV("getTrack()");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            uint32_t idx;
+            if (data.readUint32(&idx) == NO_ERROR) {
+                return reply->writeStrongBinder(IInterface::asBinder(getTrack((size_t(idx)))));
+            }
+            return UNKNOWN_ERROR;
+        }
+        case GETTRACKMETADATA: {
+            ALOGV("getTrackMetaData");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            uint32_t idx;
+            uint32_t flags;
+            if (data.readUint32(&idx) == NO_ERROR &&
+                    data.readUint32(&flags) == NO_ERROR) {
+                sp<MetaData> meta = getTrackMetaData(idx, flags);
+                meta->writeToParcel(*reply);
+                return NO_ERROR;
+            }
+            return UNKNOWN_ERROR;
+        }
+        case GETMETADATA: {
+            ALOGV("getMetaData");
+            CHECK_INTERFACE(IMediaExtractor, data, reply);
+            sp<MetaData> meta = getMetaData();
+            if (meta != NULL) {
+                meta->writeToParcel(*reply);
+                return NO_ERROR;
+            }
+            return UNKNOWN_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+
+}  // namespace android
+
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
new file mode 100644
index 0000000..51a3c1a
--- /dev/null
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -0,0 +1,81 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "IMediaExtractorService"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IMediaExtractorService.h>
+
+namespace android {
+
+enum {
+    MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
+{
+public:
+    BpMediaExtractorService(const sp<IBinder>& impl)
+        : BpInterface<IMediaExtractorService>(impl)
+    {
+    }
+
+    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(source));
+        if (mime != NULL) {
+            data.writeCString(mime);
+        }
+        status_t ret = remote()->transact(MAKE_EXTRACTOR, data, &reply);
+        if (ret == NO_ERROR) {
+            return interface_cast<IMediaExtractor>(reply.readStrongBinder());
+        }
+        return NULL;
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaExtractorService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+
+        case MAKE_EXTRACTOR: {
+            CHECK_INTERFACE(IMediaExtractorService, data, reply);
+            sp<IDataSource> source = interface_cast<IDataSource>(data.readStrongBinder());
+            const char *mime = data.readCString();
+            sp<IMediaExtractor> ex = makeExtractor(source, mime);
+            reply->writeStrongBinder(IInterface::asBinder(ex));
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
new file mode 100644
index 0000000..aec6255
--- /dev/null
+++ b/media/libmedia/IMediaSource.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "BpMediaSource"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <media/IMediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+enum {
+    START = IBinder::FIRST_CALL_TRANSACTION,
+    STOP,
+    PAUSE,
+    GETFORMAT,
+    READ
+};
+
+class BpMediaSource : public BpInterface<IMediaSource> {
+public:
+    BpMediaSource(const sp<IBinder>& impl)
+        : BpInterface<IMediaSource>(impl)
+    {
+    }
+
+    virtual status_t start(MetaData *params) {
+        ALOGV("start");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        if (params) {
+            params->writeToParcel(data);
+        }
+        status_t ret = remote()->transact(START, data, &reply);
+        if (ret == NO_ERROR && params) {
+            ALOGW("ignoring potentially modified MetaData from start");
+            ALOGW("input:");
+            params->dumpToLog();
+            sp<MetaData> meta = MetaData::createFromParcel(reply);
+            ALOGW("output:");
+            meta->dumpToLog();
+        }
+        return ret;
+    }
+
+    virtual status_t stop() {
+        ALOGV("stop");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        return remote()->transact(STOP, data, &reply);
+    }
+
+    virtual sp<MetaData> getFormat() {
+        ALOGV("getFormat");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        status_t ret = remote()->transact(GETFORMAT, data, &reply);
+        if (ret == NO_ERROR) {
+            mMetaData = MetaData::createFromParcel(reply);
+            return mMetaData;
+        }
+        return NULL;
+    }
+
+    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options) {
+        ALOGV("read");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        if (options) {
+            data.writeByteArray(sizeof(*options), (uint8_t*) options);
+        }
+        status_t ret = remote()->transact(READ, data, &reply);
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+        // wrap the returned data in a MediaBuffer
+        // XXX use a group, and use shared memory for transfer
+        ret = reply.readInt32();
+        int32_t len = reply.readInt32();
+        if (len < 0) {
+            ALOGV("got status %d and len %d, returning NULL buffer", ret, len);
+            *buffer = NULL;
+        } else {
+            ALOGV("got status %d and len %d", ret, len);
+            *buffer = new MediaBuffer(len);
+            reply.read((*buffer)->data(), len);
+            (*buffer)->meta_data()->updateFromParcel(reply);
+        }
+        return ret;
+    }
+
+    virtual status_t pause() {
+        ALOGV("pause");
+        Parcel data, reply;
+        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
+        return remote()->transact(PAUSE, data, &reply);
+    }
+
+    virtual status_t setBuffers(const Vector<MediaBuffer *> & buffers __unused) {
+        ALOGV("setBuffers NOT IMPLEMENTED");
+        return ERROR_UNSUPPORTED; // default
+    }
+
+private:
+    // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
+    // XXX: could we use this for caching, or does metadata change on the fly?
+    sp<MetaData> mMetaData;
+
+};
+
+IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
+
+#undef LOG_TAG
+#define LOG_TAG "BnMediaSource"
+
+status_t BnMediaSource::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case START: {
+            ALOGV("start");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            sp<MetaData> meta;
+            if (data.dataAvail()) {
+                meta = MetaData::createFromParcel(data);
+            }
+            status_t ret = start(meta.get());
+            if (ret == NO_ERROR && meta != NULL) {
+                meta->writeToParcel(*reply);
+            }
+            return ret;
+        }
+        case STOP: {
+            ALOGV("stop");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            return stop();
+        }
+        case PAUSE: {
+            ALOGV("pause");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            return pause();
+        }
+        case GETFORMAT: {
+            ALOGV("getFormat");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            sp<MetaData> meta = getFormat();
+            if (meta != NULL) {
+                meta->writeToParcel(*reply);
+                return NO_ERROR;
+            }
+            return UNKNOWN_ERROR;
+        }
+        case READ: {
+            ALOGV("read");
+            CHECK_INTERFACE(IMediaSource, data, reply);
+            status_t ret;
+            MediaBuffer *buf = NULL;
+            ReadOptions opts;
+            uint32_t len;
+            if (data.readUint32(&len) == NO_ERROR &&
+                    len == sizeof(opts) && data.read((void*)&opts, len) == NO_ERROR) {
+                ret = read(&buf, &opts);
+            } else {
+                ret = read(&buf, NULL);
+            }
+            // return data inside binder for now
+            // XXX return data using shared memory
+            reply->writeInt32(ret);
+            if (buf != NULL) {
+                ALOGV("ret %d, buflen %zu", ret, buf->range_length());
+                reply->writeByteArray(buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
+                buf->meta_data()->writeToParcel(*reply);
+                buf->release();
+            } else {
+                ALOGV("ret %d, buf %p", ret, buf);
+                reply->writeInt32(-1);
+            }
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+IMediaSource::ReadOptions::ReadOptions() {
+    reset();
+}
+
+void IMediaSource::ReadOptions::reset() {
+    mOptions = 0;
+    mSeekTimeUs = 0;
+    mLatenessUs = 0;
+    mNonBlocking = false;
+}
+
+void IMediaSource::ReadOptions::setNonBlocking() {
+    mNonBlocking = true;
+}
+
+void IMediaSource::ReadOptions::clearNonBlocking() {
+    mNonBlocking = false;
+}
+
+bool IMediaSource::ReadOptions::getNonBlocking() const {
+    return mNonBlocking;
+}
+
+void IMediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
+    mOptions |= kSeekTo_Option;
+    mSeekTimeUs = time_us;
+    mSeekMode = mode;
+}
+
+void IMediaSource::ReadOptions::clearSeekTo() {
+    mOptions &= ~kSeekTo_Option;
+    mSeekTimeUs = 0;
+    mSeekMode = SEEK_CLOSEST_SYNC;
+}
+
+bool IMediaSource::ReadOptions::getSeekTo(
+        int64_t *time_us, SeekMode *mode) const {
+    *time_us = mSeekTimeUs;
+    *mode = mSeekMode;
+    return (mOptions & kSeekTo_Option) != 0;
+}
+
+void IMediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
+    mLatenessUs = lateness_us;
+}
+
+int64_t IMediaSource::ReadOptions::getLateBy() const {
+    return mLatenessUs;
+}
+
+
+}  // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 92e3d2e..4d3ccd2 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -135,7 +135,7 @@
 }
 
 status_t NuPlayer::GenericSource::initFromDataSource() {
-    sp<MediaExtractor> extractor;
+    sp<IMediaExtractor> extractor;
     String8 mimeType;
     float confidence;
     sp<AMessage> dummy;
@@ -210,7 +210,7 @@
     }
 
     for (size_t i = 0; i < numtracks; ++i) {
-        sp<MediaSource> track = extractor->getTrack(i);
+        sp<IMediaSource> track = extractor->getTrack(i);
         if (track == NULL) {
             continue;
         }
@@ -791,7 +791,7 @@
       {
           int32_t trackIndex;
           CHECK(msg->findInt32("trackIndex", &trackIndex));
-          const sp<MediaSource> source = mSources.itemAt(trackIndex);
+          const sp<IMediaSource> source = mSources.itemAt(trackIndex);
 
           Track* track;
           const char *mime;
@@ -1034,7 +1034,7 @@
 }
 
 sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const {
-    sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
+    sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
 
     if (source == NULL) {
         return NULL;
@@ -1282,7 +1282,7 @@
         return OK;
     }
 
-    const sp<MediaSource> source = mSources.itemAt(trackIndex);
+    const sp<IMediaSource> source = mSources.itemAt(trackIndex);
     sp<MetaData> meta = source->getFormat();
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 035cc1f..2db5557 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -107,11 +107,11 @@
 
     struct Track {
         size_t mIndex;
-        sp<MediaSource> mSource;
+        sp<IMediaSource> mSource;
         sp<AnotherPacketSource> mPackets;
     };
 
-    Vector<sp<MediaSource> > mSources;
+    Vector<sp<IMediaSource> > mSources;
     Track mAudioTrack;
     int64_t mAudioTimeUs;
     int64_t mAudioLastDequeueTimeUs;
diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp
index 45e8a30..19efc53 100644
--- a/media/libstagefright/AACExtractor.cpp
+++ b/media/libstagefright/AACExtractor.cpp
@@ -211,7 +211,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> AACExtractor::getTrack(size_t index) {
+sp<IMediaSource> AACExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 9d90dbd..8b1e1c3 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -67,7 +67,7 @@
 }
 
 
-status_t AACWriter::addSource(const sp<MediaSource> &source) {
+status_t AACWriter::addSource(const sp<IMediaSource> &source) {
     if (mInitCheck != OK) {
         return mInitCheck;
     }
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 4a66d66..1458802 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -180,7 +180,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> AMRExtractor::getTrack(size_t index) {
+sp<IMediaSource> AMRExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index f53d7f0..961b57f 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -54,7 +54,7 @@
     return mInitCheck;
 }
 
-status_t AMRWriter::addSource(const sp<MediaSource> &source) {
+status_t AMRWriter::addSource(const sp<IMediaSource> &source) {
     if (mInitCheck != OK) {
         return mInitCheck;
     }
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 1c44285..ec06711 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -31,7 +31,6 @@
         MPEG4Extractor.cpp                \
         MPEG4Writer.cpp                   \
         MediaAdapter.cpp                  \
-        MediaBuffer.cpp                   \
         MediaBufferGroup.cpp              \
         MediaClock.cpp                    \
         MediaCodec.cpp                    \
@@ -45,7 +44,6 @@
         http/MediaHTTP.cpp                \
         MediaMuxer.cpp                    \
         MediaSource.cpp                   \
-        MetaData.cpp                      \
         NuCachedSource2.cpp               \
         NuMediaExtractor.cpp              \
         OMXClient.cpp                     \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index dd9d393..c977958 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -71,7 +71,7 @@
     }
 }
 
-void AudioPlayer::setSource(const sp<MediaSource> &source) {
+void AudioPlayer::setSource(const sp<IMediaSource> &source) {
     CHECK(mSource == NULL);
     mSource = source;
 }
@@ -358,7 +358,7 @@
     // When offloading, the OMX component is not used so this hack
     // is not needed
     if (!useOffload()) {
-        wp<MediaSource> tmp = mSource;
+        wp<IMediaSource> tmp = mSource;
         mSource.clear();
         while (tmp.promote() != NULL) {
             usleep(1000);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b0efebc..f5e9def 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -370,7 +370,7 @@
 
 status_t AwesomePlayer::setDataSource_l(
         const sp<DataSource> &dataSource) {
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
 
     if (extractor == NULL) {
         return UNKNOWN_ERROR;
@@ -393,7 +393,7 @@
     }
 }
 
-status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
+status_t AwesomePlayer::setDataSource_l(const sp<IMediaExtractor> &extractor) {
     // Attempt to approximate overall stream bitrate by summing all
     // tracks' individual bitrates, if not all of them advertise bitrate,
     // we have to fail.
@@ -1354,7 +1354,7 @@
     // The following hack is necessary to ensure that the OMX
     // component is completely released by the time we may try
     // to instantiate it again.
-    wp<MediaSource> tmp = mVideoSource;
+    wp<IMediaSource> tmp = mVideoSource;
     mVideoSource.clear();
     while (tmp.promote() != NULL) {
         usleep(1000);
@@ -1518,13 +1518,13 @@
     }
 }
 
-void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
+void AwesomePlayer::setAudioSource(sp<IMediaSource> source) {
     CHECK(source != NULL);
 
     mAudioTrack = source;
 }
 
-void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
+void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<IMediaSource>& source) {
     CHECK(source != NULL);
 
     if (mTextDriver == NULL) {
@@ -1610,7 +1610,7 @@
     return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
 }
 
-void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
+void AwesomePlayer::setVideoSource(sp<IMediaSource> source) {
     CHECK(source != NULL);
 
     mVideoTrack = source;
@@ -2393,7 +2393,7 @@
         return UNKNOWN_ERROR;
     }
 
-    sp<MediaExtractor> extractor;
+    sp<IMediaExtractor> extractor;
 
     if (isWidevineStreaming) {
         String8 mimeType;
@@ -2696,7 +2696,7 @@
 }
 
 status_t AwesomePlayer::selectAudioTrack_l(
-        const sp<MediaSource>& source, size_t trackIndex) {
+        const sp<IMediaSource>& source, size_t trackIndex) {
 
     ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags);
 
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
index 9cb6e86..255dcd0 100644
--- a/media/libstagefright/DRMExtractor.cpp
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -35,7 +35,7 @@
 
 class DRMSource : public MediaSource {
 public:
-    DRMSource(const sp<MediaSource> &mediaSource,
+    DRMSource(const sp<IMediaSource> &mediaSource,
             const sp<DecryptHandle> &decryptHandle,
             DrmManagerClient *managerClient,
             int32_t trackId, DrmBuffer *ipmpBox);
@@ -50,7 +50,7 @@
     virtual ~DRMSource();
 
 private:
-    sp<MediaSource> mOriginalMediaSource;
+    sp<IMediaSource> mOriginalMediaSource;
     sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
     size_t mTrackId;
@@ -64,7 +64,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
+DRMSource::DRMSource(const sp<IMediaSource> &mediaSource,
         const sp<DecryptHandle> &decryptHandle,
         DrmManagerClient *managerClient,
         int32_t trackId, DrmBuffer *ipmpBox)
@@ -247,8 +247,8 @@
     return mOriginalExtractor->countTracks();
 }
 
-sp<MediaSource> DRMExtractor::getTrack(size_t index) {
-    sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index);
+sp<IMediaSource> DRMExtractor::getTrack(size_t index) {
+    sp<IMediaSource> originalMediaSource = mOriginalExtractor->getTrack(index);
     originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1);
 
     int32_t trackID;
@@ -258,8 +258,9 @@
     ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length));
     CHECK(ipmpBox.length > 0);
 
-    return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
-            trackID, &ipmpBox);
+    return interface_cast<IMediaSource>(
+            new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
+            trackID, &ipmpBox));
 }
 
 sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
index 89a91f7..6e99d02 100644
--- a/media/libstagefright/FLACExtractor.cpp
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -807,7 +807,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> FLACExtractor::getTrack(size_t index)
+sp<IMediaSource> FLACExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 2e54e8c..7240e1a 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -400,7 +400,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-sp<MediaSource> MP3Extractor::getTrack(size_t index) {
+sp<IMediaSource> MP3Extractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index ef07aa0..a9e8846 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -35,7 +35,7 @@
 namespace android {
 
 struct MPEG2TSWriter::SourceInfo : public AHandler {
-    SourceInfo(const sp<MediaSource> &source);
+    SourceInfo(const sp<IMediaSource> &source);
 
     void start(const sp<AMessage> &notify);
     void stop();
@@ -69,7 +69,7 @@
         kWhatRead  = 'read',
     };
 
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     sp<ALooper> mLooper;
     sp<AMessage> mNotify;
 
@@ -93,7 +93,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
 };
 
-MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
+MPEG2TSWriter::SourceInfo::SourceInfo(const sp<IMediaSource> &source)
     : mSource(source),
       mLooper(new ALooper),
       mEOSReceived(false),
@@ -523,7 +523,7 @@
     }
 }
 
-status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
+status_t MPEG2TSWriter::addSource(const sp<IMediaSource> &source) {
     CHECK(!mStarted);
 
     sp<MetaData> meta = source->getFormat();
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index affd830..a6275ba 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2835,7 +2835,7 @@
     }
 }
 
-sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
+sp<IMediaSource> MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 78d4fb1..ea4a7ac 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -75,7 +75,7 @@
 
 class MPEG4Writer::Track {
 public:
-    Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
+    Track(MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId);
 
     ~Track();
 
@@ -228,7 +228,7 @@
 
     MPEG4Writer *mOwner;
     sp<MetaData> mMeta;
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     volatile bool mDone;
     volatile bool mPaused;
     volatile bool mResumed;
@@ -470,7 +470,7 @@
     return NULL;
 }
 
-status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
+status_t MPEG4Writer::addSource(const sp<IMediaSource> &source) {
     Mutex::Autolock l(mLock);
     if (mStarted) {
         ALOGE("Attempt to add source AFTER recording is started");
@@ -1436,7 +1436,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
-        MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
+        MPEG4Writer *owner, const sp<IMediaSource> &source, size_t trackId)
     : mOwner(owner),
       mMeta(source->getFormat()),
       mSource(source),
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index e21fe6e..53319eb 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaExtractor"
 #include <utils/Log.h>
+#include <pwd.h>
 
 #include "include/AMRExtractor.h"
 #include "include/MP3Extractor.h"
@@ -33,15 +34,34 @@
 
 #include "matroska/MatroskaExtractor.h"
 
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MetaData.h>
+#include <media/IMediaExtractorService.h>
+#include <cutils/properties.h>
 #include <utils/String8.h>
+#include <private/android_filesystem_config.h>
+
 
 namespace android {
 
+MediaExtractor::MediaExtractor():
+    mIsDrm(false) {
+    if (!LOG_NDEBUG) {
+        uid_t uid = getuid();
+        struct passwd *pw = getpwuid(uid);
+        ALOGI("extractor created in uid: %d (%s)", getuid(), pw->pw_name);
+    }
+
+}
+
+
 sp<MetaData> MediaExtractor::getMetaData() {
     return new MetaData;
 }
@@ -50,9 +70,91 @@
     return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
 }
 
+
+
+class RemoteDataSource : public BnDataSource {
+public:
+    enum {
+        kBufferSize = 64 * 1024,
+    };
+
+    static sp<IDataSource> wrap(const sp<DataSource> &source);
+    virtual ~RemoteDataSource();
+
+    virtual sp<IMemory> getIMemory();
+    virtual ssize_t readAt(off64_t offset, size_t size);
+    virtual status_t getSize(off64_t* size);
+    virtual void close();
+
+private:
+    sp<IMemory> mMemory;
+    sp<DataSource> mSource;
+    RemoteDataSource(const sp<DataSource> &source);
+    DISALLOW_EVIL_CONSTRUCTORS(RemoteDataSource);
+};
+
+
+sp<IDataSource> RemoteDataSource::wrap(const sp<DataSource> &source) {
+    return new RemoteDataSource(source);
+}
+RemoteDataSource::RemoteDataSource(const sp<DataSource> &source) {
+    mSource = source;
+    sp<MemoryDealer> memoryDealer = new MemoryDealer(kBufferSize, "RemoteDataSource");
+    mMemory = memoryDealer->allocate(kBufferSize);
+    if (mMemory == NULL) {
+        ALOGE("Failed to allocate memory!");
+    }
+}
+RemoteDataSource::~RemoteDataSource() {
+    close();
+}
+sp<IMemory> RemoteDataSource::getIMemory() {
+    return mMemory;
+}
+ssize_t RemoteDataSource::readAt(off64_t offset, size_t size) {
+    ALOGV("readAt(%lld, %d)", offset, size);
+    return mSource->readAt(offset, mMemory->pointer(), size);
+}
+status_t RemoteDataSource::getSize(off64_t* size) {
+    return mSource->getSize(size);
+}
+void RemoteDataSource::close() {
+    mSource = NULL;
+}
+
 // static
-sp<MediaExtractor> MediaExtractor::Create(
+sp<IMediaExtractor> MediaExtractor::Create(
         const sp<DataSource> &source, const char *mime) {
+    ALOGV("MediaExtractor::Create %s", mime);
+
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.extractremote", value, NULL)
+            && (!strcmp("0", value) || !strcasecmp("false", value))) {
+        // local extractor
+        ALOGW("creating media extractor in calling process");
+        return CreateFromService(source, mime);
+    } else {
+        // remote extractor
+        ALOGV("get service manager");
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+        if (binder != 0) {
+            sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
+            sp<IMediaExtractor> ex = mediaExService->makeExtractor(RemoteDataSource::wrap(source), mime);
+            return ex;
+        } else {
+            ALOGE("extractor service not running");
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+sp<MediaExtractor> MediaExtractor::CreateFromService(
+        const sp<DataSource> &source, const char *mime) {
+
+    ALOGV("MediaExtractor::CreateFromService %s", mime);
+    DataSource::RegisterDefaultSniffers();
+
     sp<AMessage> meta;
 
     String8 tmp;
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index 576471a..a17757a 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -22,56 +22,4 @@
 
 MediaSource::~MediaSource() {}
 
-////////////////////////////////////////////////////////////////////////////////
-
-MediaSource::ReadOptions::ReadOptions() {
-    reset();
-}
-
-void MediaSource::ReadOptions::reset() {
-    mOptions = 0;
-    mSeekTimeUs = 0;
-    mLatenessUs = 0;
-    mNonBlocking = false;
-}
-
-void MediaSource::ReadOptions::setNonBlocking() {
-    mNonBlocking = true;
-}
-
-void MediaSource::ReadOptions::clearNonBlocking() {
-    mNonBlocking = false;
-}
-
-bool MediaSource::ReadOptions::getNonBlocking() const {
-    return mNonBlocking;
-}
-
-void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
-    mOptions |= kSeekTo_Option;
-    mSeekTimeUs = time_us;
-    mSeekMode = mode;
-}
-
-void MediaSource::ReadOptions::clearSeekTo() {
-    mOptions &= ~kSeekTo_Option;
-    mSeekTimeUs = 0;
-    mSeekMode = SEEK_CLOSEST_SYNC;
-}
-
-bool MediaSource::ReadOptions::getSeekTo(
-        int64_t *time_us, SeekMode *mode) const {
-    *time_us = mSeekTimeUs;
-    *mode = mSeekMode;
-    return (mOptions & kSeekTo_Option) != 0;
-}
-
-void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
-    mLatenessUs = lateness_us;
-}
-
-int64_t MediaSource::ReadOptions::getLateBy() const {
-    return mLatenessUs;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/MidiExtractor.cpp b/media/libstagefright/MidiExtractor.cpp
index f6b8c84..7525f57 100644
--- a/media/libstagefright/MidiExtractor.cpp
+++ b/media/libstagefright/MidiExtractor.cpp
@@ -281,7 +281,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> MidiExtractor::getTrack(size_t index)
+sp<IMediaSource> MidiExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f67b80e..67d9921 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -285,7 +285,7 @@
         }
     }
 
-    sp<MediaSource> source = mImpl->getTrack(index);
+    sp<IMediaSource> source = mImpl->getTrack(index);
 
     CHECK_EQ((status_t)OK, source->start());
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 6938b3c..41fbf75 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -70,7 +70,7 @@
 const static uint32_t kMaxColorFormatSupported = 1000;
 
 #define FACTORY_CREATE_ENCODER(name) \
-static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
+static sp<IMediaSource> Make##name(const sp<IMediaSource> &source, const sp<MetaData> &meta) { \
     return new name(source, meta); \
 }
 
@@ -78,12 +78,12 @@
 
 FACTORY_CREATE_ENCODER(AACEncoder)
 
-static sp<MediaSource> InstantiateSoftwareEncoder(
-        const char *name, const sp<MediaSource> &source,
+static sp<IMediaSource> InstantiateSoftwareEncoder(
+        const char *name, const sp<IMediaSource> &source,
         const sp<MetaData> &meta) {
     struct FactoryInfo {
         const char *name;
-        sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
+        sp<IMediaSource> (*CreateFunc)(const sp<IMediaSource> &, const sp<MetaData> &);
     };
 
     static const FactoryInfo kFactoryInfo[] = {
@@ -289,10 +289,10 @@
 }
 
 // static
-sp<MediaSource> OMXCodec::Create(
+sp<IMediaSource> OMXCodec::Create(
         const sp<IOMX> &omx,
         const sp<MetaData> &meta, bool createEncoder,
-        const sp<MediaSource> &source,
+        const sp<IMediaSource> &source,
         const char *matchComponentName,
         uint32_t flags,
         const sp<ANativeWindow> &nativeWindow) {
@@ -337,7 +337,7 @@
         }
 
         if (createEncoder) {
-            sp<MediaSource> softwareCodec =
+            sp<IMediaSource> softwareCodec =
                 InstantiateSoftwareEncoder(componentName, source, meta);
 
             if (softwareCodec != NULL) {
@@ -1426,7 +1426,7 @@
         bool isEncoder,
         const char *mime,
         const char *componentName,
-        const sp<MediaSource> &source,
+        const sp<IMediaSource> &source,
         const sp<ANativeWindow> &nativeWindow)
     : mOMX(omx),
       mOMXLivesLocally(omx->livesLocally(node, getpid())),
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index c216b53..9162f80 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -1325,7 +1325,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-sp<MediaSource> OggExtractor::getTrack(size_t index) {
+sp<IMediaSource> OggExtractor::getTrack(size_t index) {
     if (index >= 1) {
         return NULL;
     }
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 5eff50f..055b659 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -139,7 +139,7 @@
 static VideoFrame *extractVideoFrame(
         const char *componentName,
         const sp<MetaData> &trackMeta,
-        const sp<MediaSource> &source,
+        const sp<IMediaSource> &source,
         int64_t frameTimeUs,
         int seekMode) {
 
@@ -459,7 +459,7 @@
     sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
             i, MediaExtractor::kIncludeExtensiveMetaData);
 
-    sp<MediaSource> source = mExtractor->getTrack(i);
+    sp<IMediaSource> source = mExtractor->getTrack(i);
 
     if (source.get() == NULL) {
         ALOGV("unable to instantiate video track.");
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index b30376d..bc6df79 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -116,7 +116,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> WAVExtractor::getTrack(size_t index) {
+sp<IMediaSource> WAVExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index > 0) {
         return NULL;
     }
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index bc48272..d1b2f54 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -95,7 +95,7 @@
     return (mImpl != NULL) ? mImpl->countTracks() : 0;
 }
 
-sp<MediaSource> WVMExtractor::getTrack(size_t index) {
+sp<IMediaSource> WVMExtractor::getTrack(size_t index) {
     if (mImpl == NULL) {
         return NULL;
     }
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index bebb9dc..9e596ff 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -30,7 +30,7 @@
 
 namespace android {
 
-AACEncoder::AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
+AACEncoder::AACEncoder(const sp<IMediaSource> &source, const sp<MetaData> &meta)
     : mSource(source),
       mMeta(meta),
       mStarted(false),
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 7a7535c..e17534f 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -15,6 +15,8 @@
     AString.cpp                   \
     AStringUtils.cpp              \
     AWakeLock.cpp                 \
+    MediaBuffer.cpp               \
+    MetaData.cpp                  \
     ParsedMessage.cpp             \
     base64.cpp                    \
     hexdump.cpp
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
similarity index 100%
rename from media/libstagefright/MediaBuffer.cpp
rename to media/libstagefright/foundation/MediaBuffer.cpp
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
similarity index 85%
rename from media/libstagefright/MetaData.cpp
rename to media/libstagefright/foundation/MetaData.cpp
index 7a8bd98..b847eed 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/foundation/MetaData.cpp
@@ -377,5 +377,57 @@
     }
 }
 
+status_t MetaData::writeToParcel(Parcel &parcel) {
+    size_t numItems = mItems.size();
+    parcel.writeUint32(uint32_t(numItems));
+    for (size_t i = 0; i < numItems; i++) {
+        int32_t key = mItems.keyAt(i);
+        const typed_data &item = mItems.valueAt(i);
+        uint32_t type;
+        const void *data;
+        size_t size;
+        item.getData(&type, &data, &size);
+        parcel.writeInt32(key);
+        parcel.writeUint32(type);
+        parcel.writeByteArray(size, (uint8_t*)data);
+    }
+    return OK;
+}
+
+status_t MetaData::updateFromParcel(const Parcel &parcel) {
+    uint32_t numItems;
+    if (parcel.readUint32(&numItems) == OK) {
+
+        for (size_t i = 0; i < numItems; i++) {
+            int32_t key;
+            uint32_t type;
+            uint32_t size;
+            status_t ret = parcel.readInt32(&key);
+            ret |= parcel.readUint32(&type);
+            ret |= parcel.readUint32(&size);
+            if (ret != OK) {
+                break;
+            }
+            // copy data directly from Parcel storage, then advance position
+            setData(key, type, parcel.readInplace(size), size);
+         }
+
+        return OK;
+    }
+    ALOGW("no metadata in parcel");
+    return UNKNOWN_ERROR;
+}
+
+
+/* static */
+sp<MetaData> MetaData::createFromParcel(const Parcel &parcel) {
+
+    sp<MetaData> meta = new MetaData();
+    meta->updateFromParcel(parcel);
+    return meta;
+}
+
+
+
 }  // namespace android
 
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
index 52beb0e..462e905 100644
--- a/media/libstagefright/include/AACEncoder.h
+++ b/media/libstagefright/include/AACEncoder.h
@@ -27,9 +27,9 @@
 
 class MediaBufferGroup;
 
-class AACEncoder: public MediaSource {
+class AACEncoder: public BnMediaSource {
     public:
-        AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
+        AACEncoder(const sp<IMediaSource> &source, const sp<MetaData> &meta);
 
         virtual status_t start(MetaData *params);
         virtual status_t stop();
@@ -42,7 +42,7 @@
         virtual ~AACEncoder();
 
     private:
-        sp<MediaSource>   mSource;
+        sp<IMediaSource>   mSource;
         sp<MetaData>      mMeta;
         bool              mStarted;
         MediaBufferGroup *mBufferGroup;
diff --git a/media/libstagefright/include/AACExtractor.h b/media/libstagefright/include/AACExtractor.h
index e98ca82..e231e62 100644
--- a/media/libstagefright/include/AACExtractor.h
+++ b/media/libstagefright/include/AACExtractor.h
@@ -32,7 +32,7 @@
     AACExtractor(const sp<DataSource> &source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index 4a1c827..0770397 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -32,7 +32,7 @@
     AMRExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 32b4f47..1204ee8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -23,6 +23,7 @@
 
 #include <media/AudioResamplerPublic.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/IMediaExtractor.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/TimeSource.h>
@@ -36,8 +37,6 @@
 struct ClockEstimator;
 class IDataSource;
 class MediaBuffer;
-struct MediaExtractor;
-struct MediaSource;
 struct NuCachedSource2;
 class IGraphicBufferProducer;
 
@@ -170,8 +169,8 @@
 
     sp<DataSource> mFileSource;
 
-    sp<MediaSource> mVideoTrack;
-    sp<MediaSource> mVideoSource;
+    sp<IMediaSource> mVideoTrack;
+    sp<IMediaSource> mVideoSource;
     sp<AwesomeRenderer> mVideoRenderer;
     bool mVideoRenderingStarted;
     bool mVideoRendererIsPreview;
@@ -179,9 +178,9 @@
     int32_t mStartGeneration;
 
     ssize_t mActiveAudioTrackIndex;
-    sp<MediaSource> mAudioTrack;
-    sp<MediaSource> mOmxSource;
-    sp<MediaSource> mAudioSource;
+    sp<IMediaSource> mAudioTrack;
+    sp<IMediaSource> mOmxSource;
+    sp<IMediaSource> mAudioSource;
     AudioPlayer *mAudioPlayer;
     AudioPlaybackRate mPlaybackSettings;
     int64_t mDurationUs;
@@ -253,7 +252,7 @@
     int32_t mSelectedTimedTextTrack;
 
     sp<WVMExtractor> mWVMExtractor;
-    sp<MediaExtractor> mExtractor;
+    sp<IMediaExtractor> mExtractor;
 
     status_t setDataSource_l(
             const sp<IMediaHTTPService> &httpService,
@@ -261,7 +260,7 @@
             const KeyedVector<String8, String8> *headers = NULL);
 
     status_t setDataSource_l(const sp<DataSource> &dataSource);
-    status_t setDataSource_l(const sp<MediaExtractor> &extractor);
+    status_t setDataSource_l(const sp<IMediaExtractor> &extractor);
     void reset_l();
     status_t seekTo_l(int64_t timeUs);
     status_t pause_l(bool at_eos = false);
@@ -271,14 +270,14 @@
 
     void cancelPlayerEvents(bool keepNotifications = false);
 
-    void setAudioSource(sp<MediaSource> source);
+    void setAudioSource(sp<IMediaSource> source);
     status_t initAudioDecoder();
 
 
-    void setVideoSource(sp<MediaSource> source);
+    void setVideoSource(sp<IMediaSource> source);
     status_t initVideoDecoder(uint32_t flags = 0);
 
-    void addTextSource_l(size_t trackIndex, const sp<MediaSource>& source);
+    void addTextSource_l(size_t trackIndex, const sp<IMediaSource>& source);
 
     void onStreamDone();
 
@@ -360,7 +359,7 @@
     status_t setVideoScalingMode_l(int32_t mode);
     status_t getTrackInfo(Parcel* reply) const;
 
-    status_t selectAudioTrack_l(const sp<MediaSource>& source, size_t trackIndex);
+    status_t selectAudioTrack_l(const sp<IMediaSource>& source, size_t trackIndex);
 
     // when select is true, the given track is selected.
     // otherwise, the given track is unselected.
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index b4e4afb..a035d8c 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -18,6 +18,7 @@
 
 #define DRM_EXTRACTOR_H_
 
+#include <media/IMediaSource.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <drm/DrmManagerClient.h>
 
@@ -34,7 +35,7 @@
     DRMExtractor(const sp<DataSource> &source, const char *mime);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
     virtual sp<MetaData> getMetaData();
 
@@ -44,7 +45,7 @@
 private:
     sp<DataSource> mDataSource;
 
-    sp<MediaExtractor> mOriginalExtractor;
+    sp<IMediaExtractor> mOriginalExtractor;
     sp<DecryptHandle> mDecryptHandle;
     DrmManagerClient* mDrmManagerClient;
 
diff --git a/media/libstagefright/include/FLACExtractor.h b/media/libstagefright/include/FLACExtractor.h
index ded91c2..a6e6c1d 100644
--- a/media/libstagefright/include/FLACExtractor.h
+++ b/media/libstagefright/include/FLACExtractor.h
@@ -32,7 +32,7 @@
     FLACExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index c83d9e8..2fd04f2 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -34,10 +34,11 @@
     MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
+    virtual const char * name() { return "MP3Extractor"; }
 
 private:
     status_t mInitCheck;
diff --git a/media/libstagefright/include/MPEG2PSExtractor.h b/media/libstagefright/include/MPEG2PSExtractor.h
index 22cb02d..e815f0e 100644
--- a/media/libstagefright/include/MPEG2PSExtractor.h
+++ b/media/libstagefright/include/MPEG2PSExtractor.h
@@ -34,7 +34,7 @@
     MPEG2PSExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index 8eb8f6c..9907572 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -38,7 +38,7 @@
     MPEG2TSExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 3067c3d..cff976d 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -53,7 +53,7 @@
     MPEG4Extractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/MidiExtractor.h b/media/libstagefright/include/MidiExtractor.h
index 9a2abc0..333277b 100644
--- a/media/libstagefright/include/MidiExtractor.h
+++ b/media/libstagefright/include/MidiExtractor.h
@@ -56,7 +56,7 @@
     MidiExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/libstagefright/include/OggExtractor.h b/media/libstagefright/include/OggExtractor.h
index c647cbb..592c264 100644
--- a/media/libstagefright/include/OggExtractor.h
+++ b/media/libstagefright/include/OggExtractor.h
@@ -34,10 +34,11 @@
     OggExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
+    virtual const char * name() { return "OggExtractor"; }
 
 protected:
     virtual ~OggExtractor();
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index fd739d0..6684e1f 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -18,6 +18,7 @@
 
 #define STAGEFRIGHT_METADATA_RETRIEVER_H_
 
+#include <media/IMediaExtractor.h>
 #include <media/MediaMetadataRetrieverInterface.h>
 
 #include <media/stagefright/OMXClient.h>
@@ -47,7 +48,7 @@
 private:
     OMXClient mClient;
     sp<DataSource> mSource;
-    sp<MediaExtractor> mExtractor;
+    sp<IMediaExtractor> mExtractor;
 
     bool mParsedMetaData;
     KeyedVector<int, String8> mMetaData;
diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h
index c567ccd..91ee870 100644
--- a/media/libstagefright/include/WAVExtractor.h
+++ b/media/libstagefright/include/WAVExtractor.h
@@ -33,10 +33,11 @@
     WAVExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
+    virtual const char * name() { return "WAVExtractor"; }
 
 protected:
     virtual ~WAVExtractor();
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index ab7e8b8..5b91072 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -46,7 +46,7 @@
     WVMExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
     virtual sp<MetaData> getMetaData();
     virtual void setUID(uid_t uid);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index ecc2573..a00ad4b 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -761,7 +761,7 @@
     return mTracks.size();
 }
 
-sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
+sp<IMediaSource> MatroskaExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index db36bf8..120ef82 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -37,7 +37,7 @@
 
     virtual size_t countTracks();
 
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<IMediaSource> getTrack(size_t index);
 
     virtual sp<MetaData> getTrackMetaData(
             size_t index, uint32_t flags);
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index 0f18fac..078a5f0 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -125,7 +125,7 @@
     return mTracks.size();
 }
 
-sp<MediaSource> MPEG2PSExtractor::getTrack(size_t index) {
+sp<IMediaSource> MPEG2PSExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index cbe9673..0b456c3 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -120,7 +120,7 @@
     return mSourceImpls.size();
 }
 
-sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
+sp<IMediaSource> MPEG2TSExtractor::getTrack(size_t index) {
     if (index >= mSourceImpls.size()) {
         return NULL;
     }
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 644b6ed..5159de3 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -244,7 +244,7 @@
     NodeReaper &operator=(const NodeReaper &);
 };
 
-static sp<MediaExtractor> CreateExtractorFromURI(const char *uri) {
+static sp<IMediaExtractor> CreateExtractorFromURI(const char *uri) {
     sp<DataSource> source =
         DataSource::CreateFromURI(NULL /* httpService */, uri);
 
@@ -492,14 +492,14 @@
     return NULL;
 }
 
-static sp<MediaSource> CreateSourceForMime(const char *mime) {
+static sp<IMediaSource> CreateSourceForMime(const char *mime) {
     const char *url = GetURLForMime(mime);
 
     if (url == NULL) {
         return NULL;
     }
 
-    sp<MediaExtractor> extractor = CreateExtractorFromURI(url);
+    sp<IMediaExtractor> extractor = CreateExtractorFromURI(url);
 
     if (extractor == NULL) {
         return NULL;
@@ -559,7 +559,7 @@
         return OK;
     }
 
-    sp<MediaSource> source = CreateSourceForMime(mime);
+    sp<IMediaSource> source = CreateSourceForMime(mime);
 
     if (source == NULL) {
         printf("  * Unable to open test content for type '%s', "
@@ -569,14 +569,14 @@
         return OK;
     }
 
-    sp<MediaSource> seekSource = CreateSourceForMime(mime);
+    sp<IMediaSource> seekSource = CreateSourceForMime(mime);
     if (source == NULL || seekSource == NULL) {
         return UNKNOWN_ERROR;
     }
 
     CHECK_EQ(seekSource->start(), (status_t)OK);
 
-    sp<MediaSource> codec = OMXCodec::Create(
+    sp<IMediaSource> codec = OMXCodec::Create(
             mOMX, source->getFormat(), false /* createEncoder */,
             source, componentName);
 
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 56c4aa6..1f6b6f7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -104,7 +104,7 @@
     mFd = -1;
 }
 
-status_t ARTPWriter::addSource(const sp<MediaSource> &source) {
+status_t ARTPWriter::addSource(const sp<IMediaSource> &source) {
     mSource = source;
     return OK;
 }
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
index be8bc13..62abd0a 100644
--- a/media/libstagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -37,7 +37,7 @@
 struct ARTPWriter : public MediaWriter {
     ARTPWriter(int fd);
 
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
     virtual bool reachedEOS();
     virtual status_t start(MetaData *params);
     virtual status_t stop();
@@ -72,7 +72,7 @@
     int mRTCPFd;
 #endif
 
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
     sp<ALooper> mLooper;
     sp<AHandlerReflector<ARTPWriter> > mReflector;
 
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.cpp b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
index 4854121..0c8fb79 100644
--- a/media/libstagefright/timedtext/TimedText3GPPSource.cpp
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
@@ -31,7 +31,7 @@
 
 namespace android {
 
-TimedText3GPPSource::TimedText3GPPSource(const sp<MediaSource>& mediaSource)
+TimedText3GPPSource::TimedText3GPPSource(const sp<IMediaSource>& mediaSource)
     : mSource(mediaSource) {
 }
 
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.h b/media/libstagefright/timedtext/TimedText3GPPSource.h
index 4170940..fdc79ca 100644
--- a/media/libstagefright/timedtext/TimedText3GPPSource.h
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.h
@@ -29,7 +29,7 @@
 
 class TimedText3GPPSource : public TimedTextSource {
 public:
-    TimedText3GPPSource(const sp<MediaSource>& mediaSource);
+    TimedText3GPPSource(const sp<IMediaSource>& mediaSource);
     virtual status_t start() { return mSource->start(); }
     virtual status_t stop() { return mSource->stop(); }
     virtual status_t read(
@@ -44,7 +44,7 @@
     virtual ~TimedText3GPPSource();
 
 private:
-    sp<MediaSource> mSource;
+    sp<IMediaSource> mSource;
 
     status_t extractAndAppendLocalDescriptions(
             int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel);
diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp
index 55a9803..fd0eebb 100644
--- a/media/libstagefright/timedtext/TimedTextDriver.cpp
+++ b/media/libstagefright/timedtext/TimedTextDriver.cpp
@@ -188,7 +188,7 @@
 }
 
 status_t TimedTextDriver::addInBandTextSource(
-        size_t trackIndex, const sp<MediaSource>& mediaSource) {
+        size_t trackIndex, const sp<IMediaSource>& mediaSource) {
     sp<TimedTextSource> source =
             TimedTextSource::CreateTimedTextSource(mediaSource);
     if (source == NULL) {
diff --git a/media/libstagefright/timedtext/TimedTextSource.cpp b/media/libstagefright/timedtext/TimedTextSource.cpp
index 953f7b5..e5aa382 100644
--- a/media/libstagefright/timedtext/TimedTextSource.cpp
+++ b/media/libstagefright/timedtext/TimedTextSource.cpp
@@ -33,7 +33,7 @@
 
 // static
 sp<TimedTextSource> TimedTextSource::CreateTimedTextSource(
-        const sp<MediaSource>& mediaSource) {
+        const sp<IMediaSource>& mediaSource) {
     const char *mime;
     CHECK(mediaSource->getFormat()->findCString(kKeyMIMEType, &mime));
     if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) {
diff --git a/media/libstagefright/timedtext/TimedTextSource.h b/media/libstagefright/timedtext/TimedTextSource.h
index 8c1c1cd..9946721 100644
--- a/media/libstagefright/timedtext/TimedTextSource.h
+++ b/media/libstagefright/timedtext/TimedTextSource.h
@@ -35,7 +35,7 @@
       OUT_OF_BAND_FILE_SMI = 2,
   };
   static sp<TimedTextSource> CreateTimedTextSource(
-      const sp<MediaSource>& source);
+      const sp<IMediaSource>& source);
   static sp<TimedTextSource> CreateTimedTextSource(
       const sp<DataSource>& source, FileType filetype);
   TimedTextSource() {}
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index a4b8a42..7eb4745 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -246,7 +246,7 @@
 }
 
 WebmFrameMediaSourceThread::WebmFrameMediaSourceThread(
-        const sp<MediaSource>& source,
+        const sp<IMediaSource>& source,
         int type,
         LinkedBlockingQueue<const sp<WebmFrame> >& sink,
         uint64_t timeCodeScale,
diff --git a/media/libstagefright/webm/WebmFrameThread.h b/media/libstagefright/webm/WebmFrameThread.h
index d65d9b7..528984f 100644
--- a/media/libstagefright/webm/WebmFrameThread.h
+++ b/media/libstagefright/webm/WebmFrameThread.h
@@ -123,7 +123,7 @@
 class WebmFrameMediaSourceThread: public WebmFrameSourceThread {
 public:
     WebmFrameMediaSourceThread(
-            const sp<MediaSource>& source,
+            const sp<IMediaSource>& source,
             int type,
             LinkedBlockingQueue<const sp<WebmFrame> >& sink,
             uint64_t timeCodeScale,
@@ -142,7 +142,7 @@
     }
 
 private:
-    const sp<MediaSource> mSource;
+    const sp<IMediaSource> mSource;
     const uint64_t mTimeCodeScale;
     uint64_t mStartTimeUs;
 
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index 737f144..7f6ba01 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -328,7 +328,7 @@
     return err;
 }
 
-status_t WebmWriter::addSource(const sp<MediaSource> &source) {
+status_t WebmWriter::addSource(const sp<IMediaSource> &source) {
     Mutex::Autolock l(mLock);
     if (mStarted) {
         ALOGE("Attempt to add source AFTER recording is started");
diff --git a/media/libstagefright/webm/WebmWriter.h b/media/libstagefright/webm/WebmWriter.h
index 4ad770e..4a7f506 100644
--- a/media/libstagefright/webm/WebmWriter.h
+++ b/media/libstagefright/webm/WebmWriter.h
@@ -40,7 +40,7 @@
     ~WebmWriter() { reset(); }
 
 
-    virtual status_t addSource(const sp<MediaSource> &source);
+    virtual status_t addSource(const sp<IMediaSource> &source);
     virtual status_t start(MetaData *param = NULL);
     virtual status_t stop();
     virtual status_t pause();
@@ -85,7 +85,7 @@
         const char *mName;
         sp<WebmElement> (*mMakeTrack)(const sp<MetaData>&);
 
-        sp<MediaSource> mSource;
+        sp<IMediaSource> mSource;
         sp<WebmElement> mTrackEntry;
         sp<WebmFrameSourceThread> mThread;
         LinkedBlockingQueue<const sp<WebmFrame> > mSink;
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
new file mode 100644
index 0000000..e08f45e
--- /dev/null
+++ b/services/mediaextractor/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+
+# service library
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MediaExtractorService.cpp
+LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
+LOCAL_MODULE:= libmediaextractorservice
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_SHARED_LIBRARY)
+
+
+# service executable
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := main_extractorservice.cpp
+LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils liblog libicuuc
+LOCAL_STATIC_LIBRARIES := libicuandroid_utils
+LOCAL_MODULE:= mediaextractor
+LOCAL_32_BIT_ONLY := true
+LOCAL_INIT_RC := mediaextractor.rc
+include $(BUILD_EXECUTABLE)
+
+
diff --git a/services/mediaextractor/MODULE_LICENSE_APACHE2 b/services/mediaextractor/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/mediaextractor/MODULE_LICENSE_APACHE2
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
new file mode 100644
index 0000000..afe7b67
--- /dev/null
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MediaExtractorService"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaExtractor.h>
+#include "MediaExtractorService.h"
+
+namespace android {
+
+status_t MediaExtractorService::hello()
+{
+    ALOGI("@@@ MediaExtractorService::hello");
+    return NO_ERROR;
+}
+
+sp<IMediaExtractor> MediaExtractorService::makeExtractor(
+        const sp<IDataSource> &remoteSource, const char *mime) {
+    ALOGI("@@@ MediaExtractorService::makeExtractor for %s", mime);
+
+    sp<DataSource> localSource = DataSource::CreateFromIDataSource(remoteSource);
+
+    sp<MediaExtractor> ret = MediaExtractor::CreateFromService(localSource, mime);
+
+    ALOGI("extractor service created %p (%s)",
+            ret.get(),
+            ret == NULL ? "" : ret->name());
+
+    return ret;
+}
+
+
+status_t MediaExtractorService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags)
+{
+    return BnMediaExtractorService::onTransact(code, data, reply, flags);
+}
+
+}   // namespace android
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
new file mode 100644
index 0000000..c4e924e
--- /dev/null
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_EXTRACTOR_SERVICE_H
+#define ANDROID_MEDIA_EXTRACTOR_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <media/IMediaExtractorService.h>
+#include <media/IMediaExtractor.h>
+
+namespace android {
+
+class MediaExtractorService : public BinderService<MediaExtractorService>, public BnMediaExtractorService
+{
+    friend class BinderService<MediaExtractorService>;    // for MediaExtractorService()
+public:
+    MediaExtractorService() : BnMediaExtractorService() { }
+    virtual ~MediaExtractorService() { }
+    virtual void onFirstRef() { }
+
+    static const char*  getServiceName() { return "media.extractor"; }
+
+    virtual status_t    hello();
+    virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime);
+
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags);
+
+private:
+    Mutex               mLock;
+};
+
+}   // namespace android
+
+#endif  // ANDROID_MEDIA_EXTRACTOR_SERVICE_H
diff --git a/services/mediaextractor/NOTICE b/services/mediaextractor/NOTICE
new file mode 100644
index 0000000..34bdaf1
--- /dev/null
+++ b/services/mediaextractor/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2015, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
new file mode 100644
index 0000000..482364f
--- /dev/null
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -0,0 +1,47 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "mediaextractor"
+//#define LOG_NDEBUG 0
+
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+// from LOCAL_C_INCLUDES
+#include "IcuUtils.h"
+#include "MediaExtractorService.h"
+
+using namespace android;
+
+int main(int argc __unused, char** argv)
+{
+    signal(SIGPIPE, SIG_IGN);
+
+    InitializeIcuOrDie();
+
+    strcpy(argv[0], "media.extractor");
+    sp<ProcessState> proc(ProcessState::self());
+    sp<IServiceManager> sm = defaultServiceManager();
+    MediaExtractorService::instantiate();
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/services/mediaextractor/mediaextractor.rc b/services/mediaextractor/mediaextractor.rc
new file mode 100644
index 0000000..f733a2b
--- /dev/null
+++ b/services/mediaextractor/mediaextractor.rc
@@ -0,0 +1,5 @@
+service mediaextractor /system/bin/mediaextractor
+    class main
+    user mediaex
+    group drmrpc mediadrm
+    ioprio rt 4