Remove RefBase from the extractor API

- Add MetaDataBase base class that MetaData derives from, but which
  does not derive from RefBase.
- MediaBuffer::meta_data() now returns a MetaDataBase& rather than an
  sp<MetaData>
- Rename MediaSourceBase to MediaTrack.
- MediaSource no longer derives from MediaSourceBase (or MediaTrack)
- MediaTrack::getFormat(), MediaExtractor::getTrackMetaData() and
  MediaExtractor::getMetaData() all take a MetaDataBase& parameter that
  they fill out, rather than returning a MetaData directly (the
  corresponding methods on MediaSource and RemoteMediaExtractor continue
  to return MetaData)

Bug: 67908544
Test: CTS MediaPlayerTest, DecoderTest, EncodeDecodeTest, manually record video

Change-Id: Ib531ab309061290be33d40d6100c9a8127e22083
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index f6c8664..bbc1ff8 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -20,7 +20,7 @@
 
 #include "AACExtractor.h"
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -33,17 +33,18 @@
 
 namespace android {
 
-class AACSource : public MediaSourceBase {
+class AACSource : public MediaTrack {
 public:
-    AACSource(DataSourceBase *source,
-              const sp<MetaData> &meta,
-              const Vector<uint64_t> &offset_vector,
-              int64_t frame_duration_us);
+    AACSource(
+            DataSourceBase *source,
+            MetaDataBase &meta,
+            const Vector<uint64_t> &offset_vector,
+            int64_t frame_duration_us);
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase&);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -54,7 +55,7 @@
 private:
     static const size_t kMaxFrameSize;
     DataSourceBase *mDataSource;
-    sp<MetaData> mMeta;
+    MetaDataBase mMeta;
 
     off64_t mOffset;
     int64_t mCurrentTimeUs;
@@ -132,19 +133,10 @@
 }
 
 AACExtractor::AACExtractor(
-        DataSourceBase *source, const sp<AMessage> &_meta)
+        DataSourceBase *source, off64_t offset)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mFrameDurationUs(0) {
-    sp<AMessage> meta = _meta;
-
-    if (meta == NULL) {
-        ALOGE("no metadata specified");
-        return;
-    }
-
-    int64_t offset;
-    CHECK(meta->findInt64("offset", &offset));
 
     uint8_t profile, sf_index, channel, header[2];
     if (mDataSource->readAt(offset + 2, &header, 2) < 2) {
@@ -159,7 +151,7 @@
     }
     channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
 
-    mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
+    MakeAACCodecSpecificData(mMeta, profile, sf_index, channel);
 
     off64_t streamSize, numFrames = 0;
     size_t frameSize = 0;
@@ -182,7 +174,7 @@
         // Round up and get the duration
         mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
         duration = numFrames * mFrameDurationUs;
-        mMeta->setInt64(kKeyDuration, duration);
+        mMeta.setInt64(kKeyDuration, duration);
     }
 
     mInitCheck = OK;
@@ -191,23 +183,20 @@
 AACExtractor::~AACExtractor() {
 }
 
-sp<MetaData> AACExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-
-    if (mInitCheck != OK) {
-        return meta;
+status_t AACExtractor::getMetaData(MetaDataBase &meta) {
+    meta.clear();
+    if (mInitCheck == OK) {
+        meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
     }
 
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
-
-    return meta;
+    return OK;
 }
 
 size_t AACExtractor::countTracks() {
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaSourceBase *AACExtractor::getTrack(size_t index) {
+MediaTrack *AACExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -215,12 +204,13 @@
     return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs);
 }
 
-sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
+status_t AACExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) {
     if (mInitCheck != OK || index != 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
-    return mMeta;
+    meta = mMeta;
+    return OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -229,7 +219,8 @@
 const size_t AACSource::kMaxFrameSize = 8192;
 
 AACSource::AACSource(
-        DataSourceBase *source, const sp<MetaData> &meta,
+        DataSourceBase *source,
+        MetaDataBase &meta,
         const Vector<uint64_t> &offset_vector,
         int64_t frame_duration_us)
     : mDataSource(source),
@@ -248,7 +239,7 @@
     }
 }
 
-status_t AACSource::start(MetaData * /* params */) {
+status_t AACSource::start(MetaDataBase * /* params */) {
     CHECK(!mStarted);
 
     if (mOffsetVector.empty()) {
@@ -275,8 +266,9 @@
     return OK;
 }
 
-sp<MetaData> AACSource::getFormat() {
-    return mMeta;
+status_t AACSource::getFormat(MetaDataBase &meta) {
+    meta = mMeta;
+    return OK;
 }
 
 status_t AACSource::read(
@@ -319,8 +311,8 @@
     }
 
     buffer->set_range(0, frameSizeWithoutHeader);
-    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += mFrameDurationUs;
@@ -334,14 +326,8 @@
 static MediaExtractor* CreateExtractor(
         DataSourceBase *source,
         void *meta) {
-    sp<AMessage> metaData = static_cast<AMessage *>(meta);
-    return new AACExtractor(source, metaData);
-}
-
-static void FreeMeta(void *meta) {
-    if (meta != nullptr) {
-        static_cast<AMessage *>(meta)->decStrong(nullptr);
-    }
+    off64_t offset = *static_cast<off64_t*>(meta);
+    return new AACExtractor(source, offset);
 }
 
 static MediaExtractor::CreatorFunc Sniff(
@@ -386,12 +372,9 @@
     if ((header[0] == 0xff) && ((header[1] & 0xf6) == 0xf0)) {
         *confidence = 0.2;
 
-        AMessage *msg = new AMessage;
-        msg->setInt64("offset", pos);
-        *meta = msg;
-        *freeMeta = &FreeMeta;
-        // ref count will be decreased in FreeMeta.
-        msg->incStrong(nullptr);
+        off64_t *offPtr = (off64_t*) malloc(sizeof(off64_t));
+        *meta = offPtr;
+        *freeMeta = ::free;
 
         return CreateExtractor;
     }
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index e99699c..9dadbed 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -19,6 +19,7 @@
 #define AAC_EXTRACTOR_H_
 
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 
 #include <utils/Vector.h>
 
@@ -29,13 +30,13 @@
 
 class AACExtractor : public MediaExtractor {
 public:
-    AACExtractor(DataSourceBase *source, const sp<AMessage> &meta);
+    AACExtractor(DataSourceBase *source, off64_t offset);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "AACExtractor"; }
 
 protected:
@@ -43,7 +44,7 @@
 
 private:
     DataSourceBase *mDataSource;
-    sp<MetaData> mMeta;
+    MetaDataBase mMeta;
     status_t mInitCheck;
 
     Vector<uint64_t> mOffsetVector;
@@ -54,8 +55,7 @@
 };
 
 bool SniffAAC(
-        DataSourceBase *source, String8 *mimeType, float *confidence,
-        sp<AMessage> *);
+        DataSourceBase *source, String8 *mimeType, float *confidence, off64_t *offset);
 
 }  // namespace android
 
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 59d9ef1..f56d5ef 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -21,7 +21,7 @@
 #include "AMRExtractor.h"
 
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -31,18 +31,19 @@
 
 namespace android {
 
-class AMRSource : public MediaSourceBase {
+class AMRSource : public MediaTrack {
 public:
-    AMRSource(DataSourceBase *source,
-              const sp<MetaData> &meta,
-              bool isWide,
-              const off64_t *offset_table,
-              size_t offset_table_length);
+    AMRSource(
+            DataSourceBase *source,
+            MetaDataBase &meta,
+            bool isWide,
+            const off64_t *offset_table,
+            size_t offset_table_length);
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -52,7 +53,7 @@
 
 private:
     DataSourceBase *mDataSource;
-    sp<MetaData> mMeta;
+    MetaDataBase mMeta;
     bool mIsWide;
 
     off64_t mOffset;
@@ -116,25 +117,48 @@
     return OK;
 }
 
+static bool SniffAMR(
+        DataSourceBase *source, bool *isWide, float *confidence) {
+    char header[9];
+
+    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
+        return false;
+    }
+
+    if (!memcmp(header, "#!AMR\n", 6)) {
+        if (isWide != nullptr) {
+            *isWide = false;
+        }
+        *confidence = 0.5;
+
+        return true;
+    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
+        if (isWide != nullptr) {
+            *isWide = true;
+        }
+        *confidence = 0.5;
+
+        return true;
+    }
+
+    return false;
+}
+
 AMRExtractor::AMRExtractor(DataSourceBase *source)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mOffsetTableLength(0) {
-    String8 mimeType;
     float confidence;
-    if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+    if (!SniffAMR(mDataSource, &mIsWide, &confidence)) {
         return;
     }
 
-    mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
-
-    mMeta = new MetaData;
-    mMeta->setCString(
+    mMeta.setCString(
             kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
                                   : MEDIA_MIMETYPE_AUDIO_AMR_NB);
 
-    mMeta->setInt32(kKeyChannelCount, 1);
-    mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
+    mMeta.setInt32(kKeyChannelCount, 1);
+    mMeta.setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
 
     off64_t offset = mIsWide ? 9 : 6;
     off64_t streamSize;
@@ -161,7 +185,7 @@
             numFrames ++;
         }
 
-        mMeta->setInt64(kKeyDuration, duration);
+        mMeta.setInt64(kKeyDuration, duration);
     }
 
     mInitCheck = OK;
@@ -170,23 +194,21 @@
 AMRExtractor::~AMRExtractor() {
 }
 
-sp<MetaData> AMRExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
+status_t AMRExtractor::getMetaData(MetaDataBase &meta) {
+    meta.clear();
 
-    if (mInitCheck != OK) {
-        return meta;
+    if (mInitCheck == OK) {
+        meta.setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
     }
 
-    meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
-
-    return meta;
+    return OK;
 }
 
 size_t AMRExtractor::countTracks() {
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaSourceBase *AMRExtractor::getTrack(size_t index) {
+MediaTrack *AMRExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -195,18 +217,19 @@
             mOffsetTable, mOffsetTableLength);
 }
 
-sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t /* flags */) {
+status_t AMRExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t /* flags */) {
     if (mInitCheck != OK || index != 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
-    return mMeta;
+    meta = mMeta;
+    return OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 AMRSource::AMRSource(
-        DataSourceBase *source, const sp<MetaData> &meta,
+        DataSourceBase *source, MetaDataBase &meta,
         bool isWide, const off64_t *offset_table, size_t offset_table_length)
     : mDataSource(source),
       mMeta(meta),
@@ -227,7 +250,7 @@
     }
 }
 
-status_t AMRSource::start(MetaData * /* params */) {
+status_t AMRSource::start(MetaDataBase * /* params */) {
     CHECK(!mStarted);
 
     mOffset = mIsWide ? 9 : 6;
@@ -249,8 +272,9 @@
     return OK;
 }
 
-sp<MetaData> AMRSource::getFormat() {
-    return mMeta;
+status_t AMRSource::getFormat(MetaDataBase &meta) {
+    meta = mMeta;
+    return OK;
 }
 
 status_t AMRSource::read(
@@ -325,8 +349,8 @@
     }
 
     buffer->set_range(0, frameSize);
-    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += 20000;  // Each frame is 20ms
@@ -338,33 +362,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool SniffAMR(
-        DataSourceBase *source, String8 *mimeType, float *confidence) {
-    char header[9];
-
-    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
-        return false;
-    }
-
-    if (!memcmp(header, "#!AMR\n", 6)) {
-        if (mimeType != nullptr) {
-            *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
-        }
-        *confidence = 0.5;
-
-        return true;
-    } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
-        if (mimeType != nullptr) {
-            *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
-        }
-        *confidence = 0.5;
-
-        return true;
-    }
-
-    return false;
-}
-
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index b8b44ea..c90b325 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -20,6 +20,7 @@
 
 #include <utils/Errors.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 
 namespace android {
 
@@ -32,10 +33,10 @@
     explicit AMRExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "AMRExtractor"; }
 
 protected:
@@ -43,7 +44,7 @@
 
 private:
     DataSourceBase *mDataSource;
-    sp<MetaData> mMeta;
+    MetaDataBase mMeta;
     status_t mInitCheck;
     bool mIsWide;
 
@@ -54,9 +55,6 @@
     AMRExtractor &operator=(const AMRExtractor &);
 };
 
-bool SniffAMR(
-        DataSourceBase *source, String8 *mimeType, float *confidence);
-
 }  // namespace android
 
 #endif  // AMR_EXTRACTOR_H_
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index e5bbe31..bd8a00c 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -10,7 +10,6 @@
         "liblog",
         "libmediaextractor",
         "libstagefright_foundation",
-        "libutils",
     ],
 
     name: "libamrextractor",
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 84ba6d3..0160ca4 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -11,7 +11,6 @@
         "liblog",
         "libmediaextractor",
         "libstagefright_foundation",
-        "libutils",
     ],
 
     static_libs: [
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 2c5e43e..e3da259 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -23,11 +23,11 @@
 #include "FLAC/stream_decoder.h"
 
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/VorbisComment.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/base64.h>
-#include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
@@ -35,142 +35,18 @@
 
 namespace android {
 
-// also exists in OggExtractor, candidate for moving to utility/support library?
-static void extractAlbumArt(
-        const sp<MetaData> &fileMeta, const void *data, size_t size) {
-    ALOGV("extractAlbumArt from '%s'", (const char *)data);
-
-    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
-    if (flacBuffer == NULL) {
-        ALOGE("malformed base64 encoded data.");
-        return;
-    }
-
-    size_t flacSize = flacBuffer->size();
-    uint8_t *flac = flacBuffer->data();
-    ALOGV("got flac of size %zu", flacSize);
-
-    uint32_t picType;
-    uint32_t typeLen;
-    uint32_t descLen;
-    uint32_t dataLen;
-    char type[128];
-
-    if (flacSize < 8) {
-        return;
-    }
-
-    picType = U32_AT(flac);
-
-    if (picType != 3) {
-        // This is not a front cover.
-        return;
-    }
-
-    typeLen = U32_AT(&flac[4]);
-    if (typeLen > sizeof(type) - 1) {
-        return;
-    }
-
-    // we've already checked above that flacSize >= 8
-    if (flacSize - 8 < typeLen) {
-        return;
-    }
-
-    memcpy(type, &flac[8], typeLen);
-    type[typeLen] = '\0';
-
-    ALOGV("picType = %d, type = '%s'", picType, type);
-
-    if (!strcmp(type, "-->")) {
-        // This is not inline cover art, but an external url instead.
-        return;
-    }
-
-    if (flacSize < 32 || flacSize - 32 < typeLen) {
-        return;
-    }
-
-    descLen = U32_AT(&flac[8 + typeLen]);
-    if (flacSize - 32 - typeLen < descLen) {
-        return;
-    }
-
-    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
-
-    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
-    if (flacSize - 32 - typeLen - descLen < dataLen) {
-        return;
-    }
-
-    ALOGV("got image data, %zu trailing bytes",
-         flacSize - 32 - typeLen - descLen - dataLen);
-
-    fileMeta->setData(
-            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
-
-    fileMeta->setCString(kKeyAlbumArtMIME, type);
-}
-
-// also exists in OggExtractor, candidate for moving to utility/support library?
-static void parseVorbisComment(
-        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
-{
-    struct {
-        const char *const mTag;
-        uint32_t mKey;
-    } kMap[] = {
-        { "TITLE", kKeyTitle },
-        { "ARTIST", kKeyArtist },
-        { "ALBUMARTIST", kKeyAlbumArtist },
-        { "ALBUM ARTIST", kKeyAlbumArtist },
-        { "COMPILATION", kKeyCompilation },
-        { "ALBUM", kKeyAlbum },
-        { "COMPOSER", kKeyComposer },
-        { "GENRE", kKeyGenre },
-        { "AUTHOR", kKeyAuthor },
-        { "TRACKNUMBER", kKeyCDTrackNumber },
-        { "DISCNUMBER", kKeyDiscNumber },
-        { "DATE", kKeyDate },
-        { "YEAR", kKeyYear },
-        { "LYRICIST", kKeyWriter },
-        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
-        { "ANDROID_LOOP", kKeyAutoLoop },
-    };
-
-        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
-            size_t tagLen = strlen(kMap[j].mTag);
-            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
-                    && comment[tagLen] == '=') {
-                if (kMap[j].mKey == kKeyAlbumArt) {
-                    extractAlbumArt(
-                            fileMeta,
-                            &comment[tagLen + 1],
-                            commentLength - tagLen - 1);
-                } else if (kMap[j].mKey == kKeyAutoLoop) {
-                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
-                        fileMeta->setInt32(kKeyAutoLoop, true);
-                    }
-                } else {
-                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
-                }
-            }
-        }
-
-}
-
 class FLACParser;
 
-class FLACSource : public MediaSourceBase {
+class FLACSource : public MediaTrack {
 
 public:
     FLACSource(
             DataSourceBase *dataSource,
-            const sp<MetaData> &trackMetadata);
+            MetaDataBase &meta);
 
-    virtual status_t start(MetaData *params);
+    virtual status_t start(MetaDataBase *params);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &meta);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -180,13 +56,11 @@
 
 private:
     DataSourceBase *mDataSource;
-    sp<MetaData> mTrackMetadata;
-    sp<FLACParser> mParser;
+    MetaDataBase mTrackMetadata;
+    FLACParser *mParser;
     bool mInitCheck;
     bool mStarted;
 
-    status_t init();
-
     // no copy constructor or assignment
     FLACSource(const FLACSource &);
     FLACSource &operator=(const FLACSource &);
@@ -195,7 +69,7 @@
 
 // FLACParser wraps a C libFLAC parser aka stream decoder
 
-class FLACParser : public RefBase {
+class FLACParser {
 
 public:
     enum {
@@ -205,8 +79,10 @@
     explicit FLACParser(
         DataSourceBase *dataSource,
         // If metadata pointers aren't provided, we don't fill them
-        const sp<MetaData> &fileMetadata = 0,
-        const sp<MetaData> &trackMetadata = 0);
+        MetaDataBase *fileMetadata = 0,
+        MetaDataBase *trackMetadata = 0);
+
+    virtual ~FLACParser();
 
     status_t initCheck() const {
         return mInitCheck;
@@ -239,13 +115,10 @@
         return readBuffer(true, sample);
     }
 
-protected:
-    virtual ~FLACParser();
-
 private:
     DataSourceBase *mDataSource;
-    sp<MetaData> mFileMetadata;
-    sp<MetaData> mTrackMetadata;
+    MetaDataBase *mFileMetadata;
+    MetaDataBase *mTrackMetadata;
     bool mInitCheck;
 
     // media buffers
@@ -613,8 +486,8 @@
 
 FLACParser::FLACParser(
         DataSourceBase *dataSource,
-        const sp<MetaData> &fileMetadata,
-        const sp<MetaData> &trackMetadata)
+        MetaDataBase *fileMetadata,
+        MetaDataBase *trackMetadata)
     : mDataSource(dataSource),
       mFileMetadata(fileMetadata),
       mTrackMetadata(trackMetadata),
@@ -825,8 +698,8 @@
     CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
     FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number;
     int64_t timeUs = (1000000LL * sampleNumber) / getSampleRate();
-    buffer->meta_data()->setInt64(kKeyTime, timeUs);
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    buffer->meta_data().setInt64(kKeyTime, timeUs);
+    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
     return buffer;
 }
 
@@ -834,7 +707,7 @@
 
 FLACSource::FLACSource(
         DataSourceBase *dataSource,
-        const sp<MetaData> &trackMetadata)
+        MetaDataBase &trackMetadata)
     : mDataSource(dataSource),
       mTrackMetadata(trackMetadata),
       mParser(0),
@@ -842,7 +715,9 @@
       mStarted(false)
 {
     ALOGV("FLACSource::FLACSource");
-    mInitCheck = init();
+    // re-use the same track metadata passed into constructor from FLACExtractor
+    mParser = new FLACParser(mDataSource);
+    mInitCheck  = mParser->initCheck();
 }
 
 FLACSource::~FLACSource()
@@ -851,9 +726,10 @@
     if (mStarted) {
         stop();
     }
+    delete mParser;
 }
 
-status_t FLACSource::start(MetaData * /* params */)
+status_t FLACSource::start(MetaDataBase * /* params */)
 {
     ALOGV("FLACSource::start");
 
@@ -875,9 +751,10 @@
     return OK;
 }
 
-sp<MetaData> FLACSource::getFormat()
+status_t FLACSource::getFormat(MetaDataBase &meta)
 {
-    return mTrackMetadata;
+    meta = mTrackMetadata;
+    return OK;
 }
 
 status_t FLACSource::read(
@@ -907,28 +784,24 @@
     return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
 }
 
-status_t FLACSource::init()
-{
-    ALOGV("FLACSource::init");
-    // re-use the same track metadata passed into constructor from FLACExtractor
-    mParser = new FLACParser(mDataSource);
-    return mParser->initCheck();
-}
-
 // FLACExtractor
 
 FLACExtractor::FLACExtractor(
         DataSourceBase *dataSource)
     : mDataSource(dataSource),
+      mParser(nullptr),
       mInitCheck(false)
 {
     ALOGV("FLACExtractor::FLACExtractor");
-    mInitCheck = init();
+    // FLACParser will fill in the metadata for us
+    mParser = new FLACParser(mDataSource, &mFileMetadata, &mTrackMetadata);
+    mInitCheck = mParser->initCheck();
 }
 
 FLACExtractor::~FLACExtractor()
 {
     ALOGV("~FLACExtractor::FLACExtractor");
+    delete mParser;
 }
 
 size_t FLACExtractor::countTracks()
@@ -936,7 +809,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaSourceBase *FLACExtractor::getTrack(size_t index)
+MediaTrack *FLACExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
@@ -944,26 +817,20 @@
     return new FLACSource(mDataSource, mTrackMetadata);
 }
 
-sp<MetaData> FLACExtractor::getTrackMetaData(
+status_t FLACExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     if (mInitCheck != OK || index > 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
-    return mTrackMetadata;
+    meta = mTrackMetadata;
+    return OK;
 }
 
-status_t FLACExtractor::init()
+status_t FLACExtractor::getMetaData(MetaDataBase &meta)
 {
-    mFileMetadata = new MetaData;
-    mTrackMetadata = new MetaData;
-    // FLACParser will fill in the metadata for us
-    mParser = new FLACParser(mDataSource, mFileMetadata, mTrackMetadata);
-    return mParser->initCheck();
-}
-
-sp<MetaData> FLACExtractor::getMetaData()
-{
-    return mFileMetadata;
+    meta = mFileMetadata;
+    return OK;
 }
 
 // Sniffer
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index f41d878..7fb6ec6 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -19,6 +19,7 @@
 
 #include <media/DataSourceBase.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -31,10 +32,10 @@
     explicit FLACExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "FLACExtractor"; }
 
 protected:
@@ -42,14 +43,12 @@
 
 private:
     DataSourceBase *mDataSource;
-    sp<FLACParser> mParser;
+    FLACParser *mParser;
     status_t mInitCheck;
-    sp<MetaData> mFileMetadata;
+    MetaDataBase mFileMetadata;
 
     // There is only one track
-    sp<MetaData> mTrackMetadata;
-
-    status_t init();
+    MetaDataBase mTrackMetadata;
 
     FLACExtractor(const FLACExtractor &);
     FLACExtractor &operator=(const FLACExtractor &);
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 9af128e..5412e99 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -9,8 +9,7 @@
     shared_libs: [
         "liblog",
         "libmediaextractor",
-        "libstagefright_foundation",
-        "libutils",
+        "libstagefright_foundation"
     ],
 
     static_libs: [
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index cf446db..949fbe0 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -25,7 +25,7 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <libsonivox/eas_reverb.h>
 
 namespace android {
@@ -33,16 +33,16 @@
 // how many Sonivox output buffers to aggregate into one MediaBufferBase
 static const int NUM_COMBINE_BUFFERS = 4;
 
-class MidiSource : public MediaSourceBase {
+class MidiSource : public MediaTrack {
 
 public:
     MidiSource(
-            const sp<MidiEngine> &engine,
-            const sp<MetaData> &trackMetadata);
+            MidiEngine &engine,
+            MetaDataBase &trackMetadata);
 
-    virtual status_t start(MetaData *params);
+    virtual status_t start(MetaDataBase *params);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase&);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -51,8 +51,8 @@
     virtual ~MidiSource();
 
 private:
-    sp<MidiEngine> mEngine;
-    sp<MetaData> mTrackMetadata;
+    MidiEngine &mEngine;
+    MetaDataBase &mTrackMetadata;
     bool mInitCheck;
     bool mStarted;
 
@@ -68,8 +68,8 @@
 // Midisource
 
 MidiSource::MidiSource(
-        const sp<MidiEngine> &engine,
-        const sp<MetaData> &trackMetadata)
+        MidiEngine &engine,
+        MetaDataBase &trackMetadata)
     : mEngine(engine),
       mTrackMetadata(trackMetadata),
       mInitCheck(false),
@@ -87,13 +87,13 @@
     }
 }
 
-status_t MidiSource::start(MetaData * /* params */)
+status_t MidiSource::start(MetaDataBase * /* params */)
 {
     ALOGV("MidiSource::start");
 
     CHECK(!mStarted);
     mStarted = true;
-    mEngine->allocateBuffers();
+    mEngine.allocateBuffers();
     return OK;
 }
 
@@ -103,14 +103,15 @@
 
     CHECK(mStarted);
     mStarted = false;
-    mEngine->releaseBuffers();
+    mEngine.releaseBuffers();
 
     return OK;
 }
 
-sp<MetaData> MidiSource::getFormat()
+status_t MidiSource::getFormat(MetaDataBase &meta)
 {
-    return mTrackMetadata;
+    meta = mTrackMetadata;
+    return OK;
 }
 
 status_t MidiSource::read(
@@ -125,9 +126,9 @@
         if (seekTimeUs <= 0LL) {
             seekTimeUs = 0LL;
         }
-        mEngine->seekTo(seekTimeUs);
+        mEngine.seekTo(seekTimeUs);
     }
-    buffer = mEngine->readBuffer();
+    buffer = mEngine.readBuffer();
     *outBuffer = buffer;
     ALOGV("MidiSource::read %p done", this);
     return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
@@ -142,8 +143,8 @@
 // MidiEngine
 
 MidiEngine::MidiEngine(DataSourceBase *dataSource,
-        const sp<MetaData> &fileMetadata,
-        const sp<MetaData> &trackMetadata) :
+        MetaDataBase *fileMetadata,
+        MetaDataBase *trackMetadata) :
             mGroup(NULL),
             mEasData(NULL),
             mEasHandle(NULL),
@@ -191,7 +192,7 @@
         EAS_Shutdown(mEasData);
     }
     delete mGroup;
-
+    delete mIoWrapper;
 }
 
 status_t MidiEngine::initCheck() {
@@ -238,7 +239,7 @@
     EAS_I32 timeMs;
     EAS_GetLocation(mEasData, mEasHandle, &timeMs);
     int64_t timeUs = 1000ll * timeMs;
-    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+    buffer->meta_data().setInt64(kKeyTime, timeUs);
 
     EAS_PCM* p = (EAS_PCM*) buffer->data();
     int numBytesOutput = 0;
@@ -266,9 +267,7 @@
       mInitCheck(false)
 {
     ALOGV("MidiExtractor ctor");
-    mFileMetadata = new MetaData;
-    mTrackMetadata = new MetaData;
-    mEngine = new MidiEngine(mDataSource, mFileMetadata, mTrackMetadata);
+    mEngine = new MidiEngine(mDataSource, &mFileMetadata, &mTrackMetadata);
     mInitCheck = mEngine->initCheck();
 }
 
@@ -282,35 +281,38 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaSourceBase *MidiExtractor::getTrack(size_t index)
+MediaTrack *MidiExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
     }
-    return new MidiSource(mEngine, mTrackMetadata);
+    return new MidiSource(*mEngine, mTrackMetadata);
 }
 
-sp<MetaData> MidiExtractor::getTrackMetaData(
+status_t MidiExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     ALOGV("MidiExtractor::getTrackMetaData");
     if (mInitCheck != OK || index > 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
-    return mTrackMetadata;
+    meta = mTrackMetadata;
+    return OK;
 }
 
-sp<MetaData> MidiExtractor::getMetaData()
+status_t MidiExtractor::getMetaData(MetaDataBase &meta)
 {
     ALOGV("MidiExtractor::getMetaData");
-    return mFileMetadata;
+    meta = mFileMetadata;
+    return OK;
 }
 
 // Sniffer
 
 bool SniffMidi(DataSourceBase *source, float *confidence)
 {
-    sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
-    if (p->initCheck() == OK) {
+    MidiEngine p(source, NULL, NULL);
+    if (p.initCheck() == OK) {
         *confidence = 0.8;
         ALOGV("SniffMidi: yes");
         return true;
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 4274513..244dd0f 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -21,17 +21,18 @@
 #include <media/MediaExtractor.h>
 #include <media/stagefright/MediaBufferBase.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <media/MidiIoWrapper.h>
 #include <utils/String8.h>
 #include <libsonivox/eas.h>
 
 namespace android {
 
-class MidiEngine : public RefBase {
+class MidiEngine {
 public:
-    MidiEngine(DataSourceBase *dataSource,
-            const sp<MetaData> &fileMetadata,
-            const sp<MetaData> &trackMetadata);
+    explicit MidiEngine(DataSourceBase *dataSource,
+            MetaDataBase *fileMetadata,
+            MetaDataBase *trackMetadata);
     ~MidiEngine();
 
     status_t initCheck();
@@ -41,7 +42,7 @@
     status_t seekTo(int64_t positionUs);
     MediaBufferBase* readBuffer();
 private:
-    sp<MidiIoWrapper> mIoWrapper;
+    MidiIoWrapper *mIoWrapper;
     MediaBufferGroup *mGroup;
     EAS_DATA_HANDLE mEasData;
     EAS_HANDLE mEasHandle;
@@ -55,10 +56,10 @@
     explicit MidiExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "MidiExtractor"; }
 
 protected:
@@ -67,12 +68,12 @@
 private:
     DataSourceBase *mDataSource;
     status_t mInitCheck;
-    sp<MetaData> mFileMetadata;
+    MetaDataBase mFileMetadata;
 
     // There is only one track
-    sp<MetaData> mTrackMetadata;
+    MetaDataBase mTrackMetadata;
 
-    sp<MidiEngine> mEngine;
+    MidiEngine *mEngine;
 
     EAS_DATA_HANDLE     mEasData;
     EAS_HANDLE          mEasHandle;
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 65988d3..5592a88 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -22,7 +22,7 @@
 #include "MatroskaExtractor.h"
 
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -121,13 +121,13 @@
     BlockIterator &operator=(const BlockIterator &);
 };
 
-struct MatroskaSource : public MediaSourceBase {
+struct MatroskaSource : public MediaTrack {
     MatroskaSource(MatroskaExtractor *extractor, size_t index);
 
-    virtual status_t start(MetaData *params);
+    virtual status_t start(MetaDataBase *params);
     virtual status_t stop();
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options);
@@ -219,10 +219,10 @@
                  mExtractor->mTracks.itemAt(index).mTrackNum,
                  index),
       mNALSizeLen(-1) {
-    sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
+    MetaDataBase &meta = mExtractor->mTracks.editItemAt(index).mMeta;
 
     const char *mime;
-    CHECK(meta->findCString(kKeyMIMEType, &mime));
+    CHECK(meta.findCString(kKeyMIMEType, &mime));
 
     mIsAudio = !strncasecmp("audio/", mime, 6);
 
@@ -233,11 +233,11 @@
         const uint8_t *avcc;
         size_t avccSize;
         int32_t nalSizeLen = 0;
-        if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) {
+        if (meta.findInt32(kKeyNalLengthSize, &nalSizeLen)) {
             if (nalSizeLen >= 0 && nalSizeLen <= 4) {
                 mNALSizeLen = nalSizeLen;
             }
-        } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
+        } else if (meta.findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
                 && avccSize >= 5u) {
             mNALSizeLen = 1 + (avcc[4] & 3);
             ALOGV("mNALSizeLen = %zd", mNALSizeLen);
@@ -250,7 +250,7 @@
         uint32_t dummy;
         const uint8_t *hvcc;
         size_t hvccSize;
-        if (meta->findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
+        if (meta.findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
                 && hvccSize >= 22u) {
             mNALSizeLen = 1 + (hvcc[14+7] & 3);
             ALOGV("mNALSizeLen = %zu", mNALSizeLen);
@@ -266,7 +266,7 @@
     clearPendingFrames();
 }
 
-status_t MatroskaSource::start(MetaData * /* params */) {
+status_t MatroskaSource::start(MetaDataBase * /* params */) {
     if (mType == AVC && mNALSizeLen < 0) {
         return ERROR_MALFORMED;
     }
@@ -282,8 +282,9 @@
     return OK;
 }
 
-sp<MetaData> MatroskaSource::getFormat() {
-    return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+status_t MatroskaSource::getFormat(MetaDataBase &meta) {
+    meta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+    return OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -589,7 +590,7 @@
         return ERROR_MALFORMED;
     }
 
-    sp<MetaData> meta = mbuf->meta_data();
+    MetaDataBase &meta = mbuf->meta_data();
     if (blockEncrypted) {
         /*
          *  0                   1                   2                   3
@@ -612,13 +613,13 @@
         uint32_t type;
         const uint8_t *keyId;
         size_t keyIdSize;
-        sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
-        CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
-        meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize);
+        const MetaDataBase &trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+        CHECK(trackMeta.findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
+        meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
         memcpy(ctrCounter, data + 1, 8);
-        meta->setData(kKeyCryptoIV, 0, ctrCounter, 16);
-        meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
-        meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+        meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
+        meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+        meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
         mbuf->set_range(9, mbuf->range_length() - 9);
     } else {
         /*
@@ -634,8 +635,8 @@
          */
         int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
         int32_t encryptedSizes[] = { 0 };
-        meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
-        meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+        meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
+        meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
         mbuf->set_range(1, mbuf->range_length() - 1);
     }
 
@@ -668,8 +669,8 @@
             memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
         }
 
-        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
-        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
+        mbuf->meta_data().setInt64(kKeyTime, timeUs);
+        mbuf->meta_data().setInt32(kKeyIsSyncFrame, block->IsKey());
 
         status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
         if (err == OK
@@ -736,7 +737,7 @@
 
     if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
         if (targetSampleTimeUs >= 0ll) {
-            frame->meta_data()->setInt64(
+            frame->meta_data().setInt64(
                     kKeyTargetTime, targetSampleTimeUs);
         }
 
@@ -824,12 +825,12 @@
             }
 
             int64_t timeUs;
-            CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
+            CHECK(frame->meta_data().findInt64(kKeyTime, &timeUs));
             int32_t isSync;
-            CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
+            CHECK(frame->meta_data().findInt32(kKeyIsSyncFrame, &isSync));
 
-            buffer->meta_data()->setInt64(kKeyTime, timeUs);
-            buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+            buffer->meta_data().setInt64(kKeyTime, timeUs);
+            buffer->meta_data().setInt32(kKeyIsSyncFrame, isSync);
 
             dstPtr = (uint8_t *)buffer->data();
         }
@@ -841,7 +842,7 @@
     }
 
     if (targetSampleTimeUs >= 0ll) {
-        buffer->meta_data()->setInt64(
+        buffer->meta_data().setInt64(
                 kKeyTargetTime, targetSampleTimeUs);
     }
 
@@ -927,7 +928,7 @@
     return mTracks.size();
 }
 
-MediaSourceBase *MatroskaExtractor::getTrack(size_t index) {
+MediaTrack *MatroskaExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
@@ -935,10 +936,11 @@
     return new MatroskaSource(this, index);
 }
 
-sp<MetaData> MatroskaExtractor::getTrackMetaData(
+status_t MatroskaExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t flags) {
     if (index >= mTracks.size()) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
     if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
@@ -947,7 +949,8 @@
         mExtractedThumbnails = true;
     }
 
-    return mTracks.itemAt(index).mMeta;
+    meta = mTracks.itemAt(index).mMeta;
+    return OK;
 }
 
 bool MatroskaExtractor::isLiveStreaming() const {
@@ -982,7 +985,7 @@
 }
 
 static void addESDSFromCodecPrivate(
-        const sp<MetaData> &meta,
+        MetaDataBase &meta,
         bool isAudio, const void *priv, size_t privSize) {
 
     int privSizeBytesRequired = bytesForSize(privSize);
@@ -1010,14 +1013,14 @@
     storeSize(esds, idx, privSize);
     memcpy(esds + idx, priv, privSize);
 
-    meta->setData(kKeyESDS, 0, esds, esdsSize);
+    meta.setData(kKeyESDS, 0, esds, esdsSize);
 
     delete[] esds;
     esds = NULL;
 }
 
 status_t addVorbisCodecInfo(
-        const sp<MetaData> &meta,
+        MetaDataBase &meta,
         const void *_codecPrivate, size_t codecPrivateSize) {
     // hexdump(_codecPrivate, codecPrivateSize);
 
@@ -1075,7 +1078,7 @@
     if (codecPrivate[offset] != 0x01) {
         return ERROR_MALFORMED;
     }
-    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
+    meta.setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
 
     offset += len1;
     if (codecPrivate[offset] != 0x03) {
@@ -1087,7 +1090,7 @@
         return ERROR_MALFORMED;
     }
 
-    meta->setData(
+    meta.setData(
             kKeyVorbisBooks, 0, &codecPrivate[offset],
             codecPrivateSize - offset);
 
@@ -1095,11 +1098,11 @@
 }
 
 static status_t addFlacMetadata(
-        const sp<MetaData> &meta,
+        MetaDataBase &meta,
         const void *codecPrivate, size_t codecPrivateSize) {
     // hexdump(codecPrivate, codecPrivateSize);
 
-    meta->setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
+    meta.setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
 
     int32_t maxInputSize = 64 << 10;
     sp<FLACDecoder> flacDecoder = FLACDecoder::Create();
@@ -1120,7 +1123,7 @@
                 * streamInfo.max_blocksize * streamInfo.channels;
         }
     }
-    meta->setInt32(kKeyMaxInputSize, maxInputSize);
+    meta.setInt32(kKeyMaxInputSize, maxInputSize);
 
     return OK;
 }
@@ -1143,14 +1146,12 @@
         return ERROR_MALFORMED;
     }
 
-    sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf);
-    if (avcMeta == NULL) {
+    if (!MakeAVCCodecSpecificData(trackInfo->mMeta, abuf)) {
         return ERROR_MALFORMED;
     }
 
     // Override the synthesized nal length size, which is arbitrary
-    avcMeta->setInt32(kKeyNalLengthSize, 0);
-    trackInfo->mMeta = avcMeta;
+    trackInfo->mMeta.setInt32(kKeyNalLengthSize, 0);
     return OK;
 }
 
@@ -1172,7 +1173,7 @@
 }
 
 void MatroskaExtractor::getColorInformation(
-        const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) {
+        const mkvparser::VideoTrack *vtrack, MetaDataBase &meta) {
     const mkvparser::Colour *color = vtrack->GetColour();
     if (color == NULL) {
         return;
@@ -1206,10 +1207,10 @@
         ColorAspects aspects;
         ColorUtils::convertIsoColorAspectsToCodecAspects(
                 primaries, transfer, coeffs, fullRange, aspects);
-        meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
-        meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
-        meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
-        meta->setInt32(
+        meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+        meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
+        meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+        meta.setInt32(
                 kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
     }
 
@@ -1254,13 +1255,13 @@
         // Only advertise static info if at least one of the groups have been specified.
         if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
             info.mID = HDRStaticInfo::kType1;
-            meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
+            meta.setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
         }
     }
 }
 
 status_t MatroskaExtractor::initTrackInfo(
-        const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo) {
+        const mkvparser::Track *track, MetaDataBase &meta, TrackInfo *trackInfo) {
     trackInfo->mTrackNum = track->GetNumber();
     trackInfo->mMeta = meta;
     trackInfo->mExtractor = this;
@@ -1273,7 +1274,7 @@
         for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
             const mkvparser::ContentEncoding::ContentEncryption *encryption;
             encryption = encoding->GetEncryptionByIndex(j);
-            trackInfo->mMeta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
+            trackInfo->mMeta.setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
             trackInfo->mEncrypted = true;
             break;
         }
@@ -1322,7 +1323,7 @@
 
         enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
 
-        sp<MetaData> meta = new MetaData;
+        MetaDataBase meta;
 
         status_t err = OK;
 
@@ -1333,19 +1334,19 @@
                     static_cast<const mkvparser::VideoTrack *>(track);
 
                 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+                    meta.setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
                 } else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
                     if (codecPrivateSize > 0) {
-                        meta->setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
+                        meta.setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
                     } else {
                         ALOGW("HEVC is detected, but does not have configuration.");
                         continue;
                     }
                 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
                     if (codecPrivateSize > 0) {
-                        meta->setCString(
+                        meta.setCString(
                                 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
                         addESDSFromCodecPrivate(
                                 meta, false, codecPrivate, codecPrivateSize);
@@ -1355,13 +1356,13 @@
                         continue;
                     }
                 } else if (!strcmp("V_VP8", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
                 } else if (!strcmp("V_VP9", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
                     if (codecPrivateSize > 0) {
                       // 'csd-0' for VP9 is the Blob of Codec Private data as
                       // specified in http://www.webmproject.org/vp9/profiles/.
-                      meta->setData(
+                        meta.setData(
                               kKeyVp9CodecPrivate, 0, codecPrivate,
                               codecPrivateSize);
                     }
@@ -1380,8 +1381,8 @@
                     ALOGW("track height exceeds int32_t, %lld", height);
                     continue;
                 }
-                meta->setInt32(kKeyWidth, (int32_t)width);
-                meta->setInt32(kKeyHeight, (int32_t)height);
+                meta.setInt32(kKeyWidth, (int32_t)width);
+                meta.setInt32(kKeyHeight, (int32_t)height);
 
                 // setting display width/height is optional
                 const long long displayUnit = vtrack->GetDisplayUnit();
@@ -1391,8 +1392,8 @@
                         && displayHeight > 0 && displayHeight <= INT32_MAX) {
                     switch (displayUnit) {
                     case 0: // pixels
-                        meta->setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
-                        meta->setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
+                        meta.setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
+                        meta.setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
                         break;
                     case 1: // centimeters
                     case 2: // inches
@@ -1406,8 +1407,8 @@
                         const long long computedHeight =
                                 std::max(height, width * displayHeight / displayWidth);
                         if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
-                            meta->setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
-                            meta->setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
+                            meta.setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
+                            meta.setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
                         }
                         break;
                     }
@@ -1427,34 +1428,34 @@
                     static_cast<const mkvparser::AudioTrack *>(track);
 
                 if (!strcmp("A_AAC", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
                     CHECK(codecPrivateSize >= 2);
 
                     addESDSFromCodecPrivate(
                             meta, true, codecPrivate, codecPrivateSize);
                 } else if (!strcmp("A_VORBIS", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
 
                     err = addVorbisCodecInfo(
                             meta, codecPrivate, codecPrivateSize);
                 } else if (!strcmp("A_OPUS", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
-                    meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
-                    meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
-                    meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+                    meta.setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
+                    meta.setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
+                    meta.setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
                     mSeekPreRollNs = track->GetSeekPreRoll();
                 } else if (!strcmp("A_MPEG/L3", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
                 } else if (!strcmp("A_FLAC", codecID)) {
-                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
                     err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
                 } else {
                     ALOGW("%s is not supported.", codecID);
                     continue;
                 }
 
-                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
-                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
+                meta.setInt32(kKeySampleRate, atrack->GetSamplingRate());
+                meta.setInt32(kKeyChannelCount, atrack->GetChannels());
                 break;
             }
 
@@ -1467,7 +1468,7 @@
            char lang[4];
            strncpy(lang, language, 3);
            lang[3] = '\0';
-           meta->setCString(kKeyMediaLanguage, lang);
+           meta.setCString(kKeyMediaLanguage, lang);
         }
 
         if (err != OK) {
@@ -1476,7 +1477,7 @@
         }
 
         long long durationNs = mSegment->GetDuration();
-        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
+        meta.setInt64(kKeyDuration, (durationNs + 500) / 1000);
 
         mTracks.push();
         size_t n = mTracks.size() - 1;
@@ -1498,7 +1499,7 @@
         TrackInfo *info = &mTracks.editItemAt(i);
 
         const char *mime;
-        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
+        CHECK(info->mMeta.findCString(kKeyMIMEType, &mime));
 
         if (strncasecmp(mime, "video/", 6)) {
             continue;
@@ -1524,18 +1525,16 @@
             }
             iter.advance();
         }
-        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+        info->mMeta.setInt64(kKeyThumbnailTime, thumbnailTimeUs);
     }
 }
 
-sp<MetaData> MatroskaExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-
-    meta->setCString(
+status_t MatroskaExtractor::getMetaData(MetaDataBase &meta) {
+    meta.setCString(
             kKeyMIMEType,
             mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
 
-    return meta;
+    return OK;
 }
 
 uint32_t MatroskaExtractor::flags() const {
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 095452b..3568ea1 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -21,6 +21,7 @@
 #include "mkvparser/mkvparser.h"
 
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
 
@@ -38,12 +39,11 @@
 
     virtual size_t countTracks();
 
-    virtual MediaSourceBase *getTrack(size_t index);
+    virtual MediaTrack *getTrack(size_t index);
 
-    virtual sp<MetaData> getTrackMetaData(
-            size_t index, uint32_t flags);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
 
     virtual uint32_t flags() const;
 
@@ -59,7 +59,7 @@
     struct TrackInfo {
         unsigned long mTrackNum;
         bool mEncrypted;
-        sp<MetaData> mMeta;
+        MetaDataBase mMeta;
         const MatroskaExtractor *mExtractor;
         Vector<const mkvparser::CuePoint*> mCuePoints;
 
@@ -85,20 +85,21 @@
     int64_t mSeekPreRollNs;
 
     status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
-    status_t initTrackInfo(const mkvparser::Track *track, const sp<MetaData> &meta, TrackInfo *trackInfo);
+    status_t initTrackInfo(
+            const mkvparser::Track *track,
+            MetaDataBase &meta,
+            TrackInfo *trackInfo);
     void addTracks();
     void findThumbnails();
-    void getColorInformation(const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta);
+    void getColorInformation(
+            const mkvparser::VideoTrack *vtrack,
+            MetaDataBase &meta);
     bool isLiveStreaming() const;
 
     MatroskaExtractor(const MatroskaExtractor &);
     MatroskaExtractor &operator=(const MatroskaExtractor &);
 };
 
-bool SniffMatroska(
-        DataSourceBase *source, String8 *mimeType, float *confidence,
-        sp<AMessage> *);
-
 }  // namespace android
 
 #endif  // MATROSKA_EXTRACTOR_H_
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 90ee653..33cff96 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -25,7 +25,7 @@
 #include "XINGSeeker.h"
 
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/avc_utils.h>
@@ -209,17 +209,17 @@
     return valid;
 }
 
-class MP3Source : public MediaSourceBase {
+class MP3Source : public MediaTrack {
 public:
     MP3Source(
-            const sp<MetaData> &meta, DataSourceBase *source,
+            MetaDataBase &meta, DataSourceBase *source,
             off64_t first_frame_pos, uint32_t fixed_header,
-            const sp<MP3Seeker> &seeker);
+            MP3Seeker *seeker);
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &meta);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -229,14 +229,14 @@
 
 private:
     static const size_t kMaxFrameSize;
-    sp<MetaData> mMeta;
+    MetaDataBase &mMeta;
     DataSourceBase *mDataSource;
     off64_t mFirstFramePos;
     uint32_t mFixedHeader;
     off64_t mCurrentPos;
     int64_t mCurrentTimeUs;
     bool mStarted;
-    sp<MP3Seeker> mSeeker;
+    MP3Seeker *mSeeker;
     MediaBufferGroup *mGroup;
 
     int64_t mBasisTimeUs;
@@ -246,31 +246,31 @@
     MP3Source &operator=(const MP3Source &);
 };
 
+struct Mp3Meta {
+    off64_t pos;
+    off64_t post_id3_pos;
+    uint32_t header;
+};
+
 MP3Extractor::MP3Extractor(
-        DataSourceBase *source, const sp<AMessage> &meta)
+        DataSourceBase *source, Mp3Meta *meta)
     : mInitCheck(NO_INIT),
       mDataSource(source),
       mFirstFramePos(-1),
-      mFixedHeader(0) {
+      mFixedHeader(0),
+      mSeeker(NULL) {
 
     off64_t pos = 0;
     off64_t post_id3_pos;
     uint32_t header;
     bool success;
 
-    int64_t meta_offset;
-    uint32_t meta_header;
-    int64_t meta_post_id3_offset;
-    if (meta != NULL
-            && meta->findInt64("offset", &meta_offset)
-            && meta->findInt32("header", (int32_t *)&meta_header)
-            && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) {
+    if (meta != NULL) {
         // The sniffer has already done all the hard work for us, simply
         // accept its judgement.
-        pos = (off64_t)meta_offset;
-        header = meta_header;
-        post_id3_pos = (off64_t)meta_post_id3_offset;
-
+        pos = meta->pos;
+        header = meta->header;
+        post_id3_pos = meta->post_id3_pos;
         success = true;
     } else {
         success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header);
@@ -283,8 +283,7 @@
 
     mFirstFramePos = pos;
     mFixedHeader = header;
-    mMeta = new MetaData;
-    sp<XINGSeeker> seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
+    XINGSeeker *seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
 
     if (seeker == NULL) {
         mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
@@ -293,8 +292,8 @@
         int encd = seeker->getEncoderDelay();
         int encp = seeker->getEncoderPadding();
         if (encd != 0 || encp != 0) {
-            mMeta->setInt32(kKeyEncoderDelay, encd);
-            mMeta->setInt32(kKeyEncoderPadding, encp);
+            mMeta.setInt32(kKeyEncoderDelay, encd);
+            mMeta.setInt32(kKeyEncoderPadding, encp);
         }
     }
 
@@ -330,21 +329,21 @@
 
     switch (layer) {
         case 1:
-            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
+            mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
             break;
         case 2:
-            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+            mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
             break;
         case 3:
-            mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+            mMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
             break;
         default:
             TRESPASS();
     }
 
-    mMeta->setInt32(kKeySampleRate, sample_rate);
-    mMeta->setInt32(kKeyBitRate, bitrate * 1000);
-    mMeta->setInt32(kKeyChannelCount, num_channels);
+    mMeta.setInt32(kKeySampleRate, sample_rate);
+    mMeta.setInt32(kKeyBitRate, bitrate * 1000);
+    mMeta.setInt32(kKeyChannelCount, num_channels);
 
     int64_t durationUs;
 
@@ -364,7 +363,7 @@
     }
 
     if (durationUs >= 0) {
-        mMeta->setInt64(kKeyDuration, durationUs);
+        mMeta.setInt64(kKeyDuration, durationUs);
     }
 
     mInitCheck = OK;
@@ -391,8 +390,8 @@
 
                 int32_t delay, padding;
                 if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
-                    mMeta->setInt32(kKeyEncoderDelay, delay);
-                    mMeta->setInt32(kKeyEncoderPadding, padding);
+                    mMeta.setInt32(kKeyEncoderDelay, delay);
+                    mMeta.setInt32(kKeyEncoderPadding, padding);
                 }
                 break;
             }
@@ -403,11 +402,15 @@
     }
 }
 
+MP3Extractor::~MP3Extractor() {
+    delete mSeeker;
+}
+
 size_t MP3Extractor::countTracks() {
     return mInitCheck != OK ? 0 : 1;
 }
 
-MediaSourceBase *MP3Extractor::getTrack(size_t index) {
+MediaTrack *MP3Extractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -417,13 +420,14 @@
             mSeeker);
 }
 
-sp<MetaData> MP3Extractor::getTrackMetaData(
+status_t MP3Extractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     if (mInitCheck != OK || index != 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
-
-    return mMeta;
+    meta = mMeta;
+    return OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -436,9 +440,9 @@
 // Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
 const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
 MP3Source::MP3Source(
-        const sp<MetaData> &meta, DataSourceBase *source,
+        MetaDataBase &meta, DataSourceBase *source,
         off64_t first_frame_pos, uint32_t fixed_header,
-        const sp<MP3Seeker> &seeker)
+        MP3Seeker *seeker)
     : mMeta(meta),
       mDataSource(source),
       mFirstFramePos(first_frame_pos),
@@ -458,7 +462,7 @@
     }
 }
 
-status_t MP3Source::start(MetaData *) {
+status_t MP3Source::start(MetaDataBase *) {
     CHECK(!mStarted);
 
     mGroup = new MediaBufferGroup;
@@ -487,8 +491,9 @@
     return OK;
 }
 
-sp<MetaData> MP3Source::getFormat() {
-    return mMeta;
+status_t MP3Source::getFormat(MetaDataBase &meta) {
+    meta = mMeta;
+    return OK;
 }
 
 status_t MP3Source::read(
@@ -504,7 +509,7 @@
         if (mSeeker == NULL
                 || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
             int32_t bitrate;
-            if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
+            if (!mMeta.findInt32(kKeyBitRate, &bitrate)) {
                 // bitrate is in bits/sec.
                 ALOGI("no bitrate");
 
@@ -587,8 +592,8 @@
 
     buffer->set_range(0, frame_size);
 
-    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
+    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
 
     mCurrentPos += frame_size;
 
@@ -600,19 +605,17 @@
     return OK;
 }
 
-sp<MetaData> MP3Extractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-
+status_t MP3Extractor::getMetaData(MetaDataBase &meta) {
+    meta.clear();
     if (mInitCheck != OK) {
-        return meta;
+        return UNKNOWN_ERROR;
     }
-
-    meta->setCString(kKeyMIMEType, "audio/mpeg");
+    meta.setCString(kKeyMIMEType, "audio/mpeg");
 
     ID3 id3(mDataSource);
 
     if (!id3.isValid()) {
-        return meta;
+        return OK;
     }
 
     struct Map {
@@ -651,7 +654,7 @@
         it->getString(&s);
         delete it;
 
-        meta->setCString(kMap[i].key, s);
+        meta.setCString(kMap[i].key, s);
     }
 
     size_t dataSize;
@@ -659,26 +662,20 @@
     const void *data = id3.getAlbumArt(&dataSize, &mime);
 
     if (data) {
-        meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
-        meta->setCString(kKeyAlbumArtMIME, mime.string());
+        meta.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+        meta.setCString(kKeyAlbumArtMIME, mime.string());
     }
 
-    return meta;
+    return OK;
 }
 
 static MediaExtractor* CreateExtractor(
         DataSourceBase *source,
         void *meta) {
-    sp<AMessage> metaData = static_cast<AMessage *>(meta);
+    Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
     return new MP3Extractor(source, metaData);
 }
 
-static void FreeMeta(void *meta) {
-    if (meta != nullptr) {
-        static_cast<AMessage *>(meta)->decStrong(nullptr);
-    }
-}
-
 static MediaExtractor::CreatorFunc Sniff(
         DataSourceBase *source, float *confidence, void **meta,
         MediaExtractor::FreeMetaFunc *freeMeta) {
@@ -698,14 +695,12 @@
         return NULL;
     }
 
-    AMessage *msg = new AMessage;
-    msg->setInt64("offset", pos);
-    msg->setInt32("header", header);
-    msg->setInt64("post-id3-offset", post_id3_pos);
-    *meta = msg;
-    *freeMeta = &FreeMeta;
-    // ref count will be decreased in FreeMeta.
-    msg->incStrong(nullptr);
+    Mp3Meta *mp3Meta = new Mp3Meta;
+    mp3Meta->pos = pos;
+    mp3Meta->header = header;
+    mp3Meta->post_id3_pos = post_id3_pos;
+    *meta = mp3Meta;
+    *freeMeta = ::free;
 
     *confidence = 0.2f;
 
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 6257112..485b0ca 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -20,6 +20,7 @@
 
 #include <utils/Errors.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 
 namespace android {
 
@@ -27,16 +28,18 @@
 class DataSourceBase;
 struct MP3Seeker;
 class String8;
+struct Mp3Meta;
 
 class MP3Extractor : public MediaExtractor {
 public:
-    MP3Extractor(DataSourceBase *source, const sp<AMessage> &meta);
+    MP3Extractor(DataSourceBase *source, Mp3Meta *meta);
+    ~MP3Extractor();
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "MP3Extractor"; }
 
 private:
@@ -44,18 +47,14 @@
 
     DataSourceBase *mDataSource;
     off64_t mFirstFramePos;
-    sp<MetaData> mMeta;
+    MetaDataBase mMeta;
     uint32_t mFixedHeader;
-    sp<MP3Seeker> mSeeker;
+    MP3Seeker *mSeeker;
 
     MP3Extractor(const MP3Extractor &);
     MP3Extractor &operator=(const MP3Extractor &);
 };
 
-bool SniffMP3(
-        DataSourceBase *source, String8 *mimeType, float *confidence,
-        sp<AMessage> *meta);
-
 }  // namespace android
 
 #endif  // MP3_EXTRACTOR_H_
diff --git a/media/extractors/mp3/MP3Seeker.h b/media/extractors/mp3/MP3Seeker.h
index 599542e..0e3af25 100644
--- a/media/extractors/mp3/MP3Seeker.h
+++ b/media/extractors/mp3/MP3Seeker.h
@@ -23,7 +23,7 @@
 
 namespace android {
 
-struct MP3Seeker : public RefBase {
+struct MP3Seeker {
     MP3Seeker() {}
 
     virtual bool getDuration(int64_t *durationUs) = 0;
@@ -33,7 +33,6 @@
     // the actual time that seekpoint represents.
     virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos) = 0;
 
-protected:
     virtual ~MP3Seeker() {}
 
 private:
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 51c5d1f..523f14c 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -36,7 +36,7 @@
 }
 
 // static
-sp<VBRISeeker> VBRISeeker::CreateFromSource(
+VBRISeeker *VBRISeeker::CreateFromSource(
         DataSourceBase *source, off64_t post_id3_pos) {
     off64_t pos = post_id3_pos;
 
@@ -87,7 +87,7 @@
         return NULL;
     }
 
-    sp<VBRISeeker> seeker = new (std::nothrow) VBRISeeker;
+    VBRISeeker *seeker = new (std::nothrow) VBRISeeker;
     if (seeker == NULL) {
         ALOGW("Couldn't allocate VBRISeeker");
         return NULL;
@@ -97,6 +97,7 @@
     uint8_t *buffer = new (std::nothrow) uint8_t[totalEntrySize];
     if (!buffer) {
         ALOGW("Couldn't allocate %zu bytes", totalEntrySize);
+        delete seeker;
         return NULL;
     }
 
@@ -104,7 +105,7 @@
     if (n < (ssize_t)totalEntrySize) {
         delete[] buffer;
         buffer = NULL;
-
+        delete seeker;
         return NULL;
     }
 
diff --git a/media/extractors/mp3/VBRISeeker.h b/media/extractors/mp3/VBRISeeker.h
index e46af36..9213f6e 100644
--- a/media/extractors/mp3/VBRISeeker.h
+++ b/media/extractors/mp3/VBRISeeker.h
@@ -27,7 +27,7 @@
 class DataSourceBase;
 
 struct VBRISeeker : public MP3Seeker {
-    static sp<VBRISeeker> CreateFromSource(
+    static VBRISeeker *CreateFromSource(
             DataSourceBase *source, off64_t post_id3_pos);
 
     virtual bool getDuration(int64_t *durationUs);
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/extractors/mp3/XINGSeeker.cpp
index adfa8d2..95ca556 100644
--- a/media/extractors/mp3/XINGSeeker.cpp
+++ b/media/extractors/mp3/XINGSeeker.cpp
@@ -76,11 +76,8 @@
 }
 
 // static
-sp<XINGSeeker> XINGSeeker::CreateFromSource(
+XINGSeeker *XINGSeeker::CreateFromSource(
         DataSourceBase *source, off64_t first_frame_pos) {
-    sp<XINGSeeker> seeker = new XINGSeeker;
-
-    seeker->mFirstFramePos = first_frame_pos;
 
     uint8_t buffer[4];
     int offset = first_frame_pos;
@@ -98,8 +95,6 @@
                                NULL, &samples_per_frame)) {
         return NULL;
     }
-    seeker->mFirstFramePos += xingframesize;
-
     uint8_t version = (buffer[1] >> 3) & 3;
 
     // determine offset of XING header
@@ -132,9 +127,13 @@
     offset += 4;
     uint32_t flags = U32_AT(buffer);
 
+    XINGSeeker *seeker = new XINGSeeker;
+    seeker->mFirstFramePos = first_frame_pos + xingframesize;
+
     if (flags & 0x0001) {  // Frames field is present
         if (source->readAt(offset, buffer, 4) < 4) {
-             return NULL;
+            delete seeker;
+            return NULL;
         }
         int32_t frames = U32_AT(buffer);
         // only update mDurationUs if the calculated duration is valid (non zero)
@@ -148,6 +147,7 @@
     }
     if (flags & 0x0002) {  // Bytes field is present
         if (source->readAt(offset, buffer, 4) < 4) {
+            delete seeker;
             return NULL;
         }
         seeker->mSizeBytes = U32_AT(buffer);
@@ -155,6 +155,7 @@
     }
     if (flags & 0x0004) {  // TOC field is present
         if (source->readAt(offset + 1, seeker->mTOC, 99) < 99) {
+            delete seeker;
             return NULL;
         }
         seeker->mTOCValid = true;
@@ -164,6 +165,7 @@
 #if 0
     if (flags & 0x0008) {  // Quality indicator field is present
         if (source->readAt(offset, buffer, 4) < 4) {
+            delete seeker;
             return NULL;
         }
         // do something with the quality indicator
@@ -171,6 +173,7 @@
     }
 
     if (source->readAt(xingbase + 0xaf - 0x24, &buffer, 1) < 1) { // encoding flags
+        delete seeker;
         return false;
     }
 
diff --git a/media/extractors/mp3/XINGSeeker.h b/media/extractors/mp3/XINGSeeker.h
index db847bc..5867eae 100644
--- a/media/extractors/mp3/XINGSeeker.h
+++ b/media/extractors/mp3/XINGSeeker.h
@@ -25,7 +25,7 @@
 class DataSourceBase;
 
 struct XINGSeeker : public MP3Seeker {
-    static sp<XINGSeeker> CreateFromSource(
+    static XINGSeeker *CreateFromSource(
             DataSourceBase *source, off64_t first_frame_pos);
 
     virtual bool getDuration(int64_t *durationUs);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 40c84a5..78d2ac6 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -31,7 +31,7 @@
 #include "ItemTable.h"
 #include "include/ESDS.h"
 
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -65,10 +65,10 @@
     kMaxAtomSize = 64 * 1024 * 1024,
 };
 
-class MPEG4Source : public MediaSourceBase {
+class MPEG4Source : public MediaTrack {
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
-    MPEG4Source(const sp<MetaData> &format,
+    MPEG4Source(MetaDataBase &format,
                 DataSourceBase *dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
@@ -78,10 +78,10 @@
                 const sp<ItemTable> &itemTable);
     virtual status_t init();
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
     virtual bool supportNonblockingRead() { return true; }
@@ -92,7 +92,7 @@
 private:
     Mutex mLock;
 
-    sp<MetaData> mFormat;
+    MetaDataBase &mFormat;
     DataSourceBase *mDataSource;
     int32_t mTimescale;
     sp<SampleTable> mSampleTable;
@@ -353,8 +353,7 @@
       mHasMoovBox(false),
       mPreferHeif(mime != NULL && !strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_HEIF)),
       mFirstTrack(NULL),
-      mLastTrack(NULL),
-      mFileMetaData(new MetaData) {
+      mLastTrack(NULL) {
     ALOGV("mime=%s, mPreferHeif=%d", mime, mPreferHeif);
 }
 
@@ -382,13 +381,13 @@
                     (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
 }
 
-sp<MetaData> MPEG4Extractor::getMetaData() {
+status_t MPEG4Extractor::getMetaData(MetaDataBase &meta) {
     status_t err;
     if ((err = readMetaData()) != OK) {
-        return new MetaData;
+        return UNKNOWN_ERROR;
     }
-
-    return mFileMetaData;
+    meta = mFileMetaData;
+    return OK;
 }
 
 size_t MPEG4Extractor::countTracks() {
@@ -409,17 +408,18 @@
     return n;
 }
 
-sp<MetaData> MPEG4Extractor::getTrackMetaData(
+status_t MPEG4Extractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t flags) {
     status_t err;
     if ((err = readMetaData()) != OK) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
     Track *track = mFirstTrack;
     while (index > 0) {
         if (track == NULL) {
-            return NULL;
+            return UNKNOWN_ERROR;
         }
 
         track = track->next;
@@ -427,15 +427,15 @@
     }
 
     if (track == NULL) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
     [=] {
         int64_t duration;
         int32_t samplerate;
         if (track->has_elst && mHeaderTimescale != 0 &&
-                track->meta->findInt64(kKeyDuration, &duration) &&
-                track->meta->findInt32(kKeySampleRate, &samplerate)) {
+                track->meta.findInt64(kKeyDuration, &duration) &&
+                track->meta.findInt32(kKeySampleRate, &samplerate)) {
 
             track->has_elst = false;
 
@@ -462,7 +462,7 @@
                 return;
             }
             ALOGV("delay = %" PRId64, delay);
-            track->meta->setInt32(kKeyEncoderDelay, delay);
+            track->meta.setInt32(kKeyEncoderDelay, delay);
 
             int64_t scaled_duration;
             // scaled_duration = duration * mHeaderTimescale;
@@ -502,7 +502,7 @@
                 return;
             }
             ALOGV("paddingsamples = %" PRId64, paddingsamples);
-            track->meta->setInt32(kKeyEncoderPadding, paddingsamples);
+            track->meta.setInt32(kKeyEncoderPadding, paddingsamples);
         }
     }();
 
@@ -511,7 +511,7 @@
         track->includes_expensive_metadata = true;
 
         const char *mime;
-        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+        CHECK(track->meta.findCString(kKeyMIMEType, &mime));
         if (!strncasecmp("video/", mime, 6)) {
             // MPEG2 tracks do not provide CSD, so read the stream header
             if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)) {
@@ -524,16 +524,16 @@
                     }
                     uint8_t header[kMaxTrackHeaderSize];
                     if (mDataSource->readAt(offset, &header, size) == (ssize_t)size) {
-                        track->meta->setData(kKeyStreamHeader, 'mdat', header, size);
+                        track->meta.setData(kKeyStreamHeader, 'mdat', header, size);
                     }
                 }
             }
 
             if (mMoofOffset > 0) {
                 int64_t duration;
-                if (track->meta->findInt64(kKeyDuration, &duration)) {
+                if (track->meta.findInt64(kKeyDuration, &duration)) {
                     // nothing fancy, just pick a frame near 1/4th of the duration
-                    track->meta->setInt64(
+                    track->meta.setInt64(
                             kKeyThumbnailTime, duration / 4);
                 }
             } else {
@@ -544,7 +544,7 @@
                         && track->sampleTable->getMetaDataForSample(
                             sampleIndex, NULL /* offset */, NULL /* size */,
                             &sampleTime) == OK) {
-                    track->meta->setInt64(
+                    track->meta.setInt64(
                             kKeyThumbnailTime,
                             ((int64_t)sampleTime * 1000000) / track->timescale);
                 }
@@ -552,7 +552,8 @@
         }
     }
 
-    return track->meta;
+    meta = track->meta;
+    return OK;
 }
 
 status_t MPEG4Extractor::readMetaData() {
@@ -610,8 +611,8 @@
             }
             mLastTrack = track;
 
-            track->meta = meta;
-            track->meta->setInt32(kKeyTrackID, imageIndex);
+            track->meta = *(meta.get());
+            track->meta.setInt32(kKeyTrackID, imageIndex);
             track->includes_expensive_metadata = false;
             track->skipTrack = false;
             track->timescale = 0;
@@ -620,16 +621,16 @@
 
     if (mInitCheck == OK) {
         if (findTrackByMimePrefix("video/") != NULL) {
-            mFileMetaData->setCString(
+            mFileMetaData.setCString(
                     kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
         } else if (findTrackByMimePrefix("audio/") != NULL) {
-            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
+            mFileMetaData.setCString(kKeyMIMEType, "audio/mp4");
         } else if (findTrackByMimePrefix(
                 MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC) != NULL) {
-            mFileMetaData->setCString(
+            mFileMetaData.setCString(
                     kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_HEIF);
         } else {
-            mFileMetaData->setCString(kKeyMIMEType, "application/octet-stream");
+            mFileMetaData.setCString(kKeyMIMEType, "application/octet-stream");
         }
     } else {
         mInitCheck = err;
@@ -654,7 +655,7 @@
             memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
             ptr += (20 + mPssh[i].datalen);
         }
-        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
+        mFileMetaData.setData(kKeyPssh, 'pssh', buf, psshsize);
         free(buf);
     }
 
@@ -902,11 +903,10 @@
                 }
                 mLastTrack = track;
 
-                track->meta = new MetaData;
                 track->includes_expensive_metadata = false;
                 track->skipTrack = false;
                 track->timescale = 0;
-                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
+                track->meta.setCString(kKeyMIMEType, "application/octet-stream");
                 track->has_elst = false;
             }
 
@@ -930,7 +930,7 @@
             if (isTrack) {
                 int32_t trackId;
                 // There must be exact one track header per track.
-                if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+                if (!mLastTrack->meta.findInt32(kKeyTrackID, &trackId)) {
                     mLastTrack->skipTrack = true;
                 }
 
@@ -1037,12 +1037,12 @@
                 return ERROR_MALFORMED;
             }
 
-            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+            mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
             uint32_t num_channels = 0;
             uint32_t sample_rate = 0;
             if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
-                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
-                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+                mLastTrack->meta.setInt32(kKeyChannelCount, num_channels);
+                mLastTrack->meta.setInt32(kKeySampleRate, sample_rate);
             }
             break;
         }
@@ -1095,9 +1095,9 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
-            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
-            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
+            mLastTrack->meta.setInt32(kKeyCryptoMode, defaultAlgorithmId);
+            mLastTrack->meta.setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
+            mLastTrack->meta.setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
             break;
         }
 
@@ -1231,7 +1231,7 @@
                 }
             }
             if (duration != 0 && mLastTrack->timescale != 0) {
-                mLastTrack->meta->setInt64(
+                mLastTrack->meta.setInt64(
                         kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
             }
 
@@ -1259,7 +1259,7 @@
             lang_code[2] = (lang[1] & 0x1f) + 0x60;
             lang_code[3] = '\0';
 
-            mLastTrack->meta->setCString(
+            mLastTrack->meta.setCString(
                     kKeyMediaLanguage, lang_code);
 
             break;
@@ -1294,7 +1294,7 @@
                 if (mLastTrack == NULL)
                     return ERROR_MALFORMED;
 
-                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+                CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
                 if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
                         strcasecmp(mime, "application/octet-stream")) {
                     // For now we only support a single type of media per track.
@@ -1335,7 +1335,7 @@
             }
 
             String8 mimeFormat((const char *)(buffer->data()), chunk_data_size);
-            mLastTrack->meta->setCString(kKeyMIMEType, mimeFormat.string());
+            mLastTrack->meta.setCString(kKeyMIMEType, mimeFormat.string());
 
             break;
         }
@@ -1411,13 +1411,13 @@
 
             if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
                 // if the chunk type is enca, we'll get the type from the frma box later
-                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+                mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
             }
             ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
                    chunk, num_channels, sample_size, sample_rate);
-            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
-            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+            mLastTrack->meta.setInt32(kKeyChannelCount, num_channels);
+            mLastTrack->meta.setInt32(kKeySampleRate, sample_rate);
 
             while (*offset < stop_offset) {
                 status_t err = parseChunk(offset, depth + 1);
@@ -1471,10 +1471,10 @@
 
             if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
                 // if the chunk type is encv, we'll get the type from the frma box later
-                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+                mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
             }
-            mLastTrack->meta->setInt32(kKeyWidth, width);
-            mLastTrack->meta->setInt32(kKeyHeight, height);
+            mLastTrack->meta.setInt32(kKeyWidth, width);
+            mLastTrack->meta.setInt32(kKeyHeight, height);
 
             off64_t stop_offset = *offset + chunk_size;
             *offset = data_offset + sizeof(buffer);
@@ -1562,12 +1562,12 @@
                     ALOGE("max sample size too big: %zu", max_size);
                     return ERROR_MALFORMED;
                 }
-                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
+                mLastTrack->meta.setInt32(kKeyMaxInputSize, max_size + 10 * 2);
             } else {
                 // No size was specified. Pick a conservatively large size.
                 uint32_t width, height;
-                if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
-                    !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
+                if (!mLastTrack->meta.findInt32(kKeyWidth, (int32_t*)&width) ||
+                    !mLastTrack->meta.findInt32(kKeyHeight,(int32_t*) &height)) {
                     ALOGE("No width or height, assuming worst case 1080p");
                     width = 1920;
                     height = 1080;
@@ -1582,7 +1582,7 @@
                 }
 
                 const char *mime;
-                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+                CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
                 if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
                         || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
                     // AVC & HEVC requires compression ratio of at least 2, and uses
@@ -1596,26 +1596,26 @@
                 // HACK: allow 10% overhead
                 // TODO: read sample size from traf atom for fragmented MPEG4.
                 max_size += max_size / 10;
-                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
+                mLastTrack->meta.setInt32(kKeyMaxInputSize, max_size);
             }
 
             // NOTE: setting another piece of metadata invalidates any pointers (such as the
             // mimetype) previously obtained, so don't cache them.
             const char *mime;
-            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+            CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
             // Calculate average frame rate.
             if (!strncasecmp("video/", mime, 6)) {
                 size_t nSamples = mLastTrack->sampleTable->countSamples();
                 if (nSamples == 0) {
                     int32_t trackId;
-                    if (mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
+                    if (mLastTrack->meta.findInt32(kKeyTrackID, &trackId)) {
                         for (size_t i = 0; i < mTrex.size(); i++) {
                             Trex *t = &mTrex.editItemAt(i);
                             if (t->track_ID == (uint32_t) trackId) {
                                 if (t->default_sample_duration > 0) {
                                     int32_t frameRate =
                                             mLastTrack->timescale / t->default_sample_duration;
-                                    mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
+                                    mLastTrack->meta.setInt32(kKeyFrameRate, frameRate);
                                 }
                                 break;
                             }
@@ -1623,15 +1623,15 @@
                     }
                 } else {
                     int64_t durationUs;
-                    if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
+                    if (mLastTrack->meta.findInt64(kKeyDuration, &durationUs)) {
                         if (durationUs > 0) {
                             int32_t frameRate = (nSamples * 1000000LL +
                                         (durationUs >> 1)) / durationUs;
-                            mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
+                            mLastTrack->meta.setInt32(kKeyFrameRate, frameRate);
                         }
                     }
                     ALOGV("setting frame count %zu", nSamples);
-                    mLastTrack->meta->setInt32(kKeyFrameCount, nSamples);
+                    mLastTrack->meta.setInt32(kKeyFrameCount, nSamples);
                 }
             }
 
@@ -1739,7 +1739,7 @@
             if (buffer[len - 1] != '/') {
                 buffer[len] = '/';
             }
-            mFileMetaData->setCString(kKeyLocation, &buffer[0]);
+            mFileMetaData.setCString(kKeyLocation, &buffer[0]);
             break;
         }
 
@@ -1769,7 +1769,7 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta->setData(
+            mLastTrack->meta.setData(
                     kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
 
             if (mPath.size() >= 2
@@ -1794,7 +1794,7 @@
                 uint8_t objectTypeIndication;
                 if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
                     if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
-                        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
+                        mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
                     }
                 }
             }
@@ -1821,10 +1821,10 @@
             uint32_t maxBitrate = U32_AT(&buffer[4]);
             uint32_t avgBitrate = U32_AT(&buffer[8]);
             if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
-                mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+                mLastTrack->meta.setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
             }
             if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
-                mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
+                mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
             }
             break;
         }
@@ -1848,7 +1848,7 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta->setData(
+            mLastTrack->meta.setData(
                     kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
 
             break;
@@ -1870,7 +1870,7 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta->setData(
+            mLastTrack->meta.setData(
                     kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
 
             *offset += chunk_size;
@@ -1906,7 +1906,7 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
+            mLastTrack->meta.setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
 
             break;
         }
@@ -2034,12 +2034,12 @@
                 duration = d32;
             }
             if (duration != 0 && mHeaderTimescale != 0 && duration < UINT64_MAX / 1000000) {
-                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+                mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
             }
 
             String8 s;
             if (convertTimeToDate(creationTime, &s)) {
-                mFileMetaData->setCString(kKeyDate, s.string());
+                mFileMetaData.setCString(kKeyDate, s.string());
             }
 
 
@@ -2084,7 +2084,7 @@
             }
 
             if (duration != 0 && mHeaderTimescale != 0) {
-                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+                mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
             }
 
             break;
@@ -2118,7 +2118,7 @@
             // for a practical reason as various MPEG4 containers use it.
             if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
                 if (mLastTrack != NULL) {
-                    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+                    mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
                 }
             }
 
@@ -2165,7 +2165,7 @@
             uint32_t type;
             const void *data;
             size_t size = 0;
-            if (!mLastTrack->meta->findData(
+            if (!mLastTrack->meta.findData(
                     kKeyTextFormatData, &type, &data, &size)) {
                 size = 0;
             }
@@ -2193,7 +2193,7 @@
                 return ERROR_IO;
             }
 
-            mLastTrack->meta->setData(
+            mLastTrack->meta.setData(
                     kKeyTextFormatData, 0, buffer, size + chunk_size);
 
             delete[] buffer;
@@ -2206,31 +2206,29 @@
         {
             *offset += chunk_size;
 
-            if (mFileMetaData != NULL) {
-                ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
-                      chunk_data_size, data_offset);
+            ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
+                  chunk_data_size, data_offset);
 
-                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
-                    return ERROR_MALFORMED;
-                }
-                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
-                if (buffer->data() == NULL) {
-                    ALOGE("b/28471206");
-                    return NO_MEMORY;
-                }
-                if (mDataSource->readAt(
-                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
-                    return ERROR_IO;
-                }
-                const int kSkipBytesOfDataBox = 16;
-                if (chunk_data_size <= kSkipBytesOfDataBox) {
-                    return ERROR_MALFORMED;
-                }
-
-                mFileMetaData->setData(
-                    kKeyAlbumArt, MetaData::TYPE_NONE,
-                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
+            if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
+                return ERROR_MALFORMED;
             }
+            sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
+            if (buffer->data() == NULL) {
+                ALOGE("b/28471206");
+                return NO_MEMORY;
+            }
+            if (mDataSource->readAt(
+                data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
+                return ERROR_IO;
+            }
+            const int kSkipBytesOfDataBox = 16;
+            if (chunk_data_size <= kSkipBytesOfDataBox) {
+                return ERROR_MALFORMED;
+            }
+
+            mFileMetaData.setData(
+                kKeyAlbumArt, MetaData::TYPE_NONE,
+                buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
 
             break;
         }
@@ -2462,9 +2460,9 @@
     if (mLastTrack == NULL) {
         return ERROR_MALFORMED;
     }
-    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
-    mLastTrack->meta->setInt32(kKeyChannelCount, channelCount);
-    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+    mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
+    mLastTrack->meta.setInt32(kKeyChannelCount, channelCount);
+    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
     return OK;
 }
 
@@ -2584,8 +2582,8 @@
         return ERROR_MALFORMED;
 
     int64_t metaDuration;
-    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
-        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
+    if (!mLastTrack->meta.findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
+        mLastTrack->meta.setInt64(kKeyDuration, sidxDuration);
     }
     return OK;
 }
@@ -2683,7 +2681,7 @@
             return ERROR_MALFORMED;
         }
         if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
-            mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val);
+            mFileMetaData.setFloat(kKeyCaptureFramerate, *(float *)&val);
         }
     } else if (dataType == 67 && dataSize >= 4) {
         // BE signed int32
@@ -2692,7 +2690,7 @@
             return ERROR_MALFORMED;
         }
         if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.video.temporal_layers_count")) {
-            mFileMetaData->setInt32(kKeyTemporalLayerCount, val);
+            mFileMetaData.setInt32(kKeyTemporalLayerCount, val);
         }
     } else {
         // add more keys if needed
@@ -2746,7 +2744,7 @@
     if (mLastTrack == NULL)
         return ERROR_MALFORMED;
 
-    mLastTrack->meta->setInt32(kKeyTrackID, id);
+    mLastTrack->meta.setInt32(kKeyTrackID, id);
 
     size_t matrixOffset = dynSize + 16;
     int32_t a00 = U32_AT(&buffer[matrixOffset]);
@@ -2782,15 +2780,15 @@
     }
 
     if (rotationDegrees != 0) {
-        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
+        mLastTrack->meta.setInt32(kKeyRotation, rotationDegrees);
     }
 
     // Handle presentation display size, which could be different
     // from the image size indicated by kKeyWidth and kKeyHeight.
     uint32_t width = U32_AT(&buffer[dynSize + 52]);
     uint32_t height = U32_AT(&buffer[dynSize + 56]);
-    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
-    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
+    mLastTrack->meta.setInt32(kKeyDisplayWidth, width >> 16);
+    mLastTrack->meta.setInt32(kKeyDisplayHeight, height >> 16);
 
     return OK;
 }
@@ -2875,7 +2873,7 @@
                 sprintf(tmp, "%d",
                         (int)buffer[size - 1]);
 
-                mFileMetaData->setCString(kKeyCompilation, tmp);
+                mFileMetaData.setCString(kKeyCompilation, tmp);
             }
             break;
         }
@@ -2887,7 +2885,7 @@
                 uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
                 sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
 
-                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
+                mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
             }
             break;
         }
@@ -2899,7 +2897,7 @@
                 uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
                 sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
 
-                mFileMetaData->setCString(kKeyDiscNumber, tmp);
+                mFileMetaData.setCString(kKeyDiscNumber, tmp);
             }
             break;
         }
@@ -2943,8 +2941,8 @@
                             return ERROR_MALFORMED;
                         }
 
-                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
-                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
+                        mLastTrack->meta.setInt32(kKeyEncoderDelay, delay);
+                        mLastTrack->meta.setInt32(kKeyEncoderPadding, padding);
                     }
                 }
 
@@ -2959,9 +2957,9 @@
             break;
     }
 
-    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
+    if (size >= 8 && metadataKey && !mFileMetaData.hasData(metadataKey)) {
         if (metadataKey == kKeyAlbumArt) {
-            mFileMetaData->setData(
+            mFileMetaData.setData(
                     kKeyAlbumArt, MetaData::TYPE_NONE,
                     buffer + 8, size - 8);
         } else if (metadataKey == kKeyGenre) {
@@ -2978,18 +2976,18 @@
                 char genre[10];
                 sprintf(genre, "%d", genrecode);
 
-                mFileMetaData->setCString(metadataKey, genre);
+                mFileMetaData.setCString(metadataKey, genre);
             } else if (flags == 1) {
                 // custom genre string
                 buffer[size] = '\0';
 
-                mFileMetaData->setCString(
+                mFileMetaData.setCString(
                         metadataKey, (const char *)buffer + 8);
             }
         } else {
             buffer[size] = '\0';
 
-            mFileMetaData->setCString(
+            mFileMetaData.setCString(
                     metadataKey, (const char *)buffer + 8);
         }
     }
@@ -3029,11 +3027,11 @@
                 primaries, transfer, coeffs, fullRange, aspects);
 
         // only store the first color specification
-        if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
-            mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
-            mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
-            mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
-            mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
+        if (!mLastTrack->meta.hasData(kKeyColorPrimaries)) {
+            mLastTrack->meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+            mLastTrack->meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
+            mLastTrack->meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+            mLastTrack->meta.setInt32(kKeyColorRange, aspects.mRange);
         }
     }
 
@@ -3088,7 +3086,7 @@
               char tmp[4];
               sprintf(tmp, "%u", buffer[size - 1]);
 
-              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
+              mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
             }
 
             metadataKey = kKeyAlbum;
@@ -3109,7 +3107,7 @@
             if (year < 10000) {
                 sprintf(tmp, "%u", year);
 
-                mFileMetaData->setCString(kKeyYear, tmp);
+                mFileMetaData.setCString(kKeyYear, tmp);
             }
             break;
         }
@@ -3154,11 +3152,11 @@
 
         if (isUTF8) {
             buffer[size] = 0;
-            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
+            mFileMetaData.setCString(metadataKey, (const char *)buffer + 6);
         } else {
             // Convert from UTF-16 string to UTF-8 string.
             String8 tmpUTF8str(framedata, len16);
-            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
+            mFileMetaData.setCString(metadataKey, tmpUTF8str.string());
         }
     }
 
@@ -3193,7 +3191,7 @@
         static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
 
         for (size_t i = 0; i < kNumMapEntries; ++i) {
-            if (!mFileMetaData->hasData(kMap[i].key)) {
+            if (!mFileMetaData.hasData(kMap[i].key)) {
                 ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
                 if (it->done()) {
                     delete it;
@@ -3209,7 +3207,7 @@
                 it->getString(&s);
                 delete it;
 
-                mFileMetaData->setCString(kMap[i].key, s);
+                mFileMetaData.setCString(kMap[i].key, s);
             }
         }
 
@@ -3218,13 +3216,13 @@
         const void *data = id3.getAlbumArt(&dataSize, &mime);
 
         if (data) {
-            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
-            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
+            mFileMetaData.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+            mFileMetaData.setCString(kKeyAlbumArtMIME, mime.string());
         }
     }
 }
 
-MediaSourceBase *MPEG4Extractor::getTrack(size_t index) {
+MediaTrack *MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
@@ -3247,7 +3245,7 @@
 
     Trex *trex = NULL;
     int32_t trackId;
-    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
+    if (track->meta.findInt32(kKeyTrackID, &trackId)) {
         for (size_t i = 0; i < mTrex.size(); i++) {
             Trex *t = &mTrex.editItemAt(i);
             if (t->track_ID == (uint32_t) trackId) {
@@ -3263,7 +3261,7 @@
     ALOGV("getTrack called, pssh: %zu", mPssh.size());
 
     const char *mime;
-    if (!track->meta->findCString(kKeyMIMEType, &mime)) {
+    if (!track->meta.findCString(kKeyMIMEType, &mime)) {
         return NULL;
     }
 
@@ -3272,7 +3270,7 @@
         uint32_t type;
         const void *data;
         size_t size;
-        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)) {
+        if (!track->meta.findData(kKeyAVCC, &type, &data, &size)) {
             return NULL;
         }
 
@@ -3286,7 +3284,7 @@
         uint32_t type;
         const void *data;
         size_t size;
-        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)) {
+        if (!track->meta.findData(kKeyHVCC, &type, &data, &size)) {
             return NULL;
         }
 
@@ -3313,25 +3311,25 @@
 // static
 status_t MPEG4Extractor::verifyTrack(Track *track) {
     const char *mime;
-    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+    CHECK(track->meta.findCString(kKeyMIMEType, &mime));
 
     uint32_t type;
     const void *data;
     size_t size;
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
-        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
+        if (!track->meta.findData(kKeyAVCC, &type, &data, &size)
                 || type != kTypeAVCC) {
             return ERROR_MALFORMED;
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
-        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
+        if (!track->meta.findData(kKeyHVCC, &type, &data, &size)
                     || type != kTypeHVCC) {
             return ERROR_MALFORMED;
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
             || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)
             || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
-        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
+        if (!track->meta.findData(kKeyESDS, &type, &data, &size)
                 || type != kTypeESDS) {
             return ERROR_MALFORMED;
         }
@@ -3417,7 +3415,7 @@
         if (mLastTrack == NULL)
             return ERROR_MALFORMED;
 
-        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
+        mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
         return OK;
     }
 
@@ -3434,10 +3432,10 @@
         uint32_t avgBitrate = 0;
         esds.getBitRate(&maxBitrate, &avgBitrate);
         if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
-            mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+            mLastTrack->meta.setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
         }
         if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
-            mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
+            mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
         }
     }
 
@@ -3481,7 +3479,7 @@
         return ERROR_MALFORMED;
 
     //keep AOT type
-    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
+    mLastTrack->meta.setInt32(kKeyAACAOT, objectType);
 
     uint32_t freqIndex = br.getBits(4);
 
@@ -3519,7 +3517,7 @@
             extSampleRate = kSamplingRate[extFreqIndex];
         }
         //TODO: save the extension sampling rate value in meta data =>
-        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
+        //      mLastTrack->meta.setInt32(kKeyExtSampleRate, extSampleRate);
     }
 
     switch (numChannels) {
@@ -3672,24 +3670,24 @@
         return ERROR_MALFORMED;
 
     int32_t prevSampleRate;
-    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
+    CHECK(mLastTrack->meta.findInt32(kKeySampleRate, &prevSampleRate));
 
     if (prevSampleRate != sampleRate) {
         ALOGV("mpeg4 audio sample rate different from previous setting. "
              "was: %d, now: %d", prevSampleRate, sampleRate);
     }
 
-    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
 
     int32_t prevChannelCount;
-    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
+    CHECK(mLastTrack->meta.findInt32(kKeyChannelCount, &prevChannelCount));
 
     if (prevChannelCount != numChannels) {
         ALOGV("mpeg4 audio channel count different from previous setting. "
              "was: %d, now: %d", prevChannelCount, numChannels);
     }
 
-    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
+    mLastTrack->meta.setInt32(kKeyChannelCount, numChannels);
 
     return OK;
 }
@@ -3697,7 +3695,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Source::MPEG4Source(
-        const sp<MetaData> &format,
+        MetaDataBase &format,
         DataSourceBase *dataSource,
         int32_t timeScale,
         const sp<SampleTable> &sampleTable,
@@ -3734,20 +3732,20 @@
 
     memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
 
-    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
+    mFormat.findInt32(kKeyCryptoMode, &mCryptoMode);
     mDefaultIVSize = 0;
-    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
+    mFormat.findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
     uint32_t keytype;
     const void *key;
     size_t keysize;
-    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
+    if (mFormat.findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
         CHECK(keysize <= 16);
         memset(mCryptoKey, 0, 16);
         memcpy(mCryptoKey, key, keysize);
     }
 
     const char *mime;
-    bool success = mFormat->findCString(kKeyMIMEType, &mime);
+    bool success = mFormat.findCString(kKeyMIMEType, &mime);
     CHECK(success);
 
     mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -3758,7 +3756,7 @@
         uint32_t type;
         const void *data;
         size_t size;
-        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
+        CHECK(format.findData(kKeyAVCC, &type, &data, &size));
 
         const uint8_t *ptr = (const uint8_t *)data;
 
@@ -3771,7 +3769,7 @@
         uint32_t type;
         const void *data;
         size_t size;
-        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
+        CHECK(format.findData(kKeyHVCC, &type, &data, &size));
 
         const uint8_t *ptr = (const uint8_t *)data;
 
@@ -3781,7 +3779,7 @@
         mNALLengthSize = 1 + (ptr[14 + 7] & 3);
     }
 
-    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
+    CHECK(format.findInt32(kKeyTrackID, &mTrackId));
 
 }
 
@@ -3801,7 +3799,7 @@
     free(mCurrentSampleInfoOffsets);
 }
 
-status_t MPEG4Source::start(MetaData *params) {
+status_t MPEG4Source::start(MetaDataBase *params) {
     Mutex::Autolock autoLock(mLock);
 
     CHECK(!mStarted);
@@ -3815,7 +3813,7 @@
     }
 
     int32_t tmp;
-    CHECK(mFormat->findInt32(kKeyMaxInputSize, &tmp));
+    CHECK(mFormat.findInt32(kKeyMaxInputSize, &tmp));
     size_t max_size = tmp;
 
     // A somewhat arbitrary limit that should be sufficient for 8k video frames
@@ -4142,7 +4140,7 @@
 
     drmoffset += mCurrentMoofOffset;
     int ivlength;
-    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
+    CHECK(mFormat.findInt32(kKeyCryptoDefaultIVSize, &ivlength));
 
     // only 0, 8 and 16 byte initialization vectors are supported
     if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
@@ -4459,10 +4457,10 @@
     return OK;
 }
 
-sp<MetaData> MPEG4Source::getFormat() {
+status_t MPEG4Source::getFormat(MetaDataBase &meta) {
     Mutex::Autolock autoLock(mLock);
-
-    return mFormat;
+    meta = mFormat;
+    return OK;
 }
 
 size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
@@ -4510,7 +4508,7 @@
             CHECK(mSampleTable == NULL);
             CHECK(mItemTable != NULL);
             int32_t imageIndex;
-            if (!mFormat->findInt32(kKeyTrackID, &imageIndex)) {
+            if (!mFormat.findInt32(kKeyTrackID, &imageIndex)) {
                 return ERROR_MALFORMED;
             }
 
@@ -4664,19 +4662,19 @@
 
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
-            mBuffer->meta_data()->clear();
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().clear();
+            mBuffer->meta_data().setInt64(
                     kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().setInt64(
                     kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
-                mBuffer->meta_data()->setInt64(
+                mBuffer->meta_data().setInt64(
                         kKeyTargetTime, targetSampleTimeUs);
             }
 
             if (isSyncSample) {
-                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+                mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
             }
 
             ++mCurrentSampleIndex;
@@ -4732,7 +4730,7 @@
         // the start code (0x00 00 00 01).
         ssize_t num_bytes_read = 0;
         int32_t drm = 0;
-        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+        bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
         if (usesDRM) {
             num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
@@ -4799,25 +4797,25 @@
             mBuffer->set_range(0, dstOffset);
         }
 
-        mBuffer->meta_data()->clear();
-        mBuffer->meta_data()->setInt64(
+        mBuffer->meta_data().clear();
+        mBuffer->meta_data().setInt64(
                 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-        mBuffer->meta_data()->setInt64(
+        mBuffer->meta_data().setInt64(
                 kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().setInt64(
                     kKeyTargetTime, targetSampleTimeUs);
         }
 
         if (mIsAVC) {
             uint32_t layerId = FindAVCLayerId(
                     (const uint8_t *)mBuffer->data(), mBuffer->range_length());
-            mBuffer->meta_data()->setInt32(kKeyTemporalLayerId, layerId);
+            mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
         }
 
         if (isSyncSample) {
-            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+            mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
         }
 
         ++mCurrentSampleIndex;
@@ -4945,18 +4943,18 @@
     }
 
     const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
-    const sp<MetaData> bufmeta = mBuffer->meta_data();
-    bufmeta->clear();
+    MetaDataBase &bufmeta = mBuffer->meta_data();
+    bufmeta.clear();
     if (smpl->encryptedsizes.size()) {
         // store clear/encrypted lengths in metadata
-        bufmeta->setData(kKeyPlainSizes, 0,
+        bufmeta.setData(kKeyPlainSizes, 0,
                 smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
-        bufmeta->setData(kKeyEncryptedSizes, 0,
+        bufmeta.setData(kKeyEncryptedSizes, 0,
                 smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
-        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
-        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
-        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
-        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
+        bufmeta.setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
+        bufmeta.setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
+        bufmeta.setInt32(kKeyCryptoMode, mCryptoMode);
+        bufmeta.setData(kKeyCryptoKey, 0, mCryptoKey, 16);
     }
 
     if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
@@ -4982,24 +4980,24 @@
 
             CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().setInt64(
                     kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().setInt64(
                     kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
 
             if (targetSampleTimeUs >= 0) {
-                mBuffer->meta_data()->setInt64(
+                mBuffer->meta_data().setInt64(
                         kKeyTargetTime, targetSampleTimeUs);
             }
 
             if (mIsAVC) {
                 uint32_t layerId = FindAVCLayerId(
                         (const uint8_t *)mBuffer->data(), mBuffer->range_length());
-                mBuffer->meta_data()->setInt32(kKeyTemporalLayerId, layerId);
+                mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
             }
 
             if (isSyncSample) {
-                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+                mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
             }
 
             ++mCurrentSampleIndex;
@@ -5057,7 +5055,7 @@
         // the start code (0x00 00 00 01).
         ssize_t num_bytes_read = 0;
         int32_t drm = 0;
-        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+        bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
         void *data = NULL;
         bool isMalFormed = false;
         if (usesDRM) {
@@ -5068,8 +5066,7 @@
             }
         } else {
             int32_t max_size;
-            if (mFormat == NULL
-                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
+            if (!mFormat.findInt32(kKeyMaxInputSize, &max_size)
                     || !isInRange((size_t)0u, (size_t)max_size, size)) {
                 isMalFormed = true;
             } else {
@@ -5149,18 +5146,18 @@
             mBuffer->set_range(0, dstOffset);
         }
 
-        mBuffer->meta_data()->setInt64(
+        mBuffer->meta_data().setInt64(
                 kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-        mBuffer->meta_data()->setInt64(
+        mBuffer->meta_data().setInt64(
                 kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
 
         if (targetSampleTimeUs >= 0) {
-            mBuffer->meta_data()->setInt64(
+            mBuffer->meta_data().setInt64(
                     kKeyTargetTime, targetSampleTimeUs);
         }
 
         if (isSyncSample) {
-            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+            mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
         }
 
         ++mCurrentSampleIndex;
@@ -5176,8 +5173,7 @@
         const char *mimePrefix) {
     for (Track *track = mFirstTrack; track != NULL; track = track->next) {
         const char *mime;
-        if (track->meta != NULL
-                && track->meta->findCString(kKeyMIMEType, &mime)
+        if (track->meta.findCString(kKeyMIMEType, &mime)
                 && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
             return track;
         }
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 5c86345..9a9f0d1 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -22,6 +22,7 @@
 
 #include <media/DataSourceBase.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <media/stagefright/foundation/AString.h>
 #include <utils/List.h>
 #include <utils/Vector.h>
@@ -56,10 +57,10 @@
     explicit MPEG4Extractor(DataSourceBase *source, const char *mime = NULL);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG4Extractor"; }
 
@@ -75,7 +76,7 @@
     };
     struct Track {
         Track *next;
-        sp<MetaData> meta;
+        MetaDataBase meta;
         uint32_t timescale;
         sp<SampleTable> sampleTable;
         bool includes_expensive_metadata;
@@ -105,7 +106,7 @@
 
     Track *mFirstTrack, *mLastTrack;
 
-    sp<MetaData> mFileMetaData;
+    MetaDataBase mFileMetaData;
 
     Vector<uint32_t> mPath;
     String8 mLastCommentMean;
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index c2de6e7..6980b82 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -24,7 +24,7 @@
 #include "mpeg2ts/ESQueue.h"
 
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -40,13 +40,13 @@
 
 namespace android {
 
-struct MPEG2PSExtractor::Track : public MediaSourceBase, public RefBase {
+struct MPEG2PSExtractor::Track : public MediaTrack, public RefBase {
     Track(MPEG2PSExtractor *extractor,
           unsigned stream_id, unsigned stream_type);
 
-    virtual status_t start(MetaData *params);
+    virtual status_t start(MetaDataBase *params);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options);
@@ -72,12 +72,12 @@
     DISALLOW_EVIL_CONSTRUCTORS(Track);
 };
 
-struct MPEG2PSExtractor::WrappedTrack : public MediaSourceBase {
+struct MPEG2PSExtractor::WrappedTrack : public MediaTrack {
     WrappedTrack(MPEG2PSExtractor *extractor, const sp<Track> &track);
 
-    virtual status_t start(MetaData *params);
+    virtual status_t start(MetaDataBase *params);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options);
@@ -108,9 +108,10 @@
     }
 
     // Remove all tracks that were unable to determine their format.
+    MetaDataBase meta;
     for (size_t i = mTracks.size(); i > 0;) {
         i--;
-        if (mTracks.valueAt(i)->getFormat() == NULL) {
+        if (mTracks.valueAt(i)->getFormat(meta) != OK) {
             mTracks.removeItemsAt(i);
         }
     }
@@ -125,7 +126,7 @@
     return mTracks.size();
 }
 
-MediaSourceBase *MPEG2PSExtractor::getTrack(size_t index) {
+MediaTrack *MPEG2PSExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
@@ -133,20 +134,20 @@
     return new WrappedTrack(this, mTracks.valueAt(index));
 }
 
-sp<MetaData> MPEG2PSExtractor::getTrackMetaData(
+status_t MPEG2PSExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     if (index >= mTracks.size()) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
-    return mTracks.valueAt(index)->getFormat();
+    return mTracks.valueAt(index)->getFormat(meta);
 }
 
-sp<MetaData> MPEG2PSExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
+status_t MPEG2PSExtractor::getMetaData(MetaDataBase &meta) {
+    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
 
-    return meta;
+    return OK;
 }
 
 uint32_t MPEG2PSExtractor::flags() const {
@@ -634,12 +635,12 @@
     mQueue = NULL;
 }
 
-status_t MPEG2PSExtractor::Track::start(MetaData *params) {
+status_t MPEG2PSExtractor::Track::start(MetaDataBase *) {
     if (mSource == NULL) {
         return NO_INIT;
     }
 
-    return mSource->start(params);
+    return mSource->start(NULL); // AnotherPacketSource::start doesn't use its argument
 }
 
 status_t MPEG2PSExtractor::Track::stop() {
@@ -650,12 +651,14 @@
     return mSource->stop();
 }
 
-sp<MetaData> MPEG2PSExtractor::Track::getFormat() {
+status_t MPEG2PSExtractor::Track::getFormat(MetaDataBase &meta) {
     if (mSource == NULL) {
-        return NULL;
+        return NO_INIT;
     }
 
-    return mSource->getFormat();
+    sp<MetaData> sourceMeta = mSource->getFormat();
+    meta = *sourceMeta;
+    return OK;
 }
 
 status_t MPEG2PSExtractor::Track::read(
@@ -731,7 +734,7 @@
 MPEG2PSExtractor::WrappedTrack::~WrappedTrack() {
 }
 
-status_t MPEG2PSExtractor::WrappedTrack::start(MetaData *params) {
+status_t MPEG2PSExtractor::WrappedTrack::start(MetaDataBase *params) {
     return mTrack->start(params);
 }
 
@@ -739,8 +742,8 @@
     return mTrack->stop();
 }
 
-sp<MetaData> MPEG2PSExtractor::WrappedTrack::getFormat() {
-    return mTrack->getFormat();
+status_t MPEG2PSExtractor::WrappedTrack::getFormat(MetaDataBase &meta) {
+    return mTrack->getFormat(meta);
 }
 
 status_t MPEG2PSExtractor::WrappedTrack::read(
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index 2541f4d..8b9dad9 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -20,6 +20,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 
@@ -34,10 +35,10 @@
     explicit MPEG2PSExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
 
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2PSExtractor"; }
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 7887a7c..c83f7ce 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -24,7 +24,7 @@
 
 #include <media/DataSourceBase.h>
 #include <media/IStreamSource.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -49,16 +49,16 @@
 static const int kMaxDurationReadSize = 250000LL;
 static const int kMaxDurationRetry = 6;
 
-struct MPEG2TSSource : public MediaSourceBase {
+struct MPEG2TSSource : public MediaTrack {
     MPEG2TSSource(
             MPEG2TSExtractor *extractor,
             const sp<AnotherPacketSource> &impl,
             bool doesSeek);
     virtual ~MPEG2TSSource();
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -86,16 +86,18 @@
 MPEG2TSSource::~MPEG2TSSource() {
 }
 
-status_t MPEG2TSSource::start(MetaData *params) {
-    return mImpl->start(params);
+status_t MPEG2TSSource::start(MetaDataBase *) {
+    return mImpl->start(NULL); // AnotherPacketSource::start() doesn't use its argument
 }
 
 status_t MPEG2TSSource::stop() {
     return mImpl->stop();
 }
 
-sp<MetaData> MPEG2TSSource::getFormat() {
-    return mImpl->getFormat();
+status_t MPEG2TSSource::getFormat(MetaDataBase &meta) {
+    sp<MetaData> implMeta = mImpl->getFormat();
+    meta = *implMeta;
+    return OK;
 }
 
 status_t MPEG2TSSource::read(
@@ -133,7 +135,7 @@
     return mSourceImpls.size();
 }
 
-MediaSourceBase *MPEG2TSExtractor::getTrack(size_t index) {
+MediaTrack *MPEG2TSExtractor::getTrack(size_t index) {
     if (index >= mSourceImpls.size()) {
         return NULL;
     }
@@ -144,23 +146,28 @@
             (mSeekSyncPoints == &mSyncPoints.editItemAt(index)));
 }
 
-sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
+status_t MPEG2TSExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
-    return index < mSourceImpls.size()
+    sp<MetaData> implMeta = index < mSourceImpls.size()
         ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
+    if (implMeta == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    meta = *implMeta;
+    return OK;
 }
 
-sp<MetaData> MPEG2TSExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+status_t MPEG2TSExtractor::getMetaData(MetaDataBase &meta) {
+    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
 
-    return meta;
+    return OK;
 }
 
 //static
-bool MPEG2TSExtractor::isScrambledFormat(const sp<MetaData> &format) {
+bool MPEG2TSExtractor::isScrambledFormat(MetaDataBase &format) {
     const char *mime;
-    return format->findCString(kKeyMIMEType, &mime)
+    return format.findCString(kKeyMIMEType, &mime)
             && (!strcasecmp(MEDIA_MIMETYPE_VIDEO_SCRAMBLED, mime)
                     || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
 }
@@ -213,7 +220,7 @@
                 if (format != NULL) {
                     haveVideo = true;
                     addSource(impl);
-                    if (!isScrambledFormat(format)) {
+                    if (!isScrambledFormat(*(format.get()))) {
                         mSyncPoints.push();
                         mSeekSyncPoints = &mSyncPoints.editTop();
                     }
@@ -229,7 +236,7 @@
                 if (format != NULL) {
                     haveAudio = true;
                     addSource(impl);
-                    if (!isScrambledFormat(format)) {
+                    if (!isScrambledFormat(*(format.get()))) {
                         mSyncPoints.push();
                         if (!haveVideo) {
                             mSeekSyncPoints = &mSyncPoints.editTop();
@@ -470,7 +477,7 @@
 }
 
 status_t MPEG2TSExtractor::seek(int64_t seekTimeUs,
-        const MediaSourceBase::ReadOptions::SeekMode &seekMode) {
+        const MediaTrack::ReadOptions::SeekMode &seekMode) {
     if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) {
         ALOGW("No sync point to seek to.");
         // ... and therefore we have nothing useful to do here.
@@ -491,18 +498,18 @@
     }
 
     switch (seekMode) {
-        case MediaSourceBase::ReadOptions::SEEK_NEXT_SYNC:
+        case MediaTrack::ReadOptions::SEEK_NEXT_SYNC:
             if (index == mSeekSyncPoints->size()) {
                 ALOGW("Next sync not found; starting from the latest sync.");
                 --index;
             }
             break;
-        case MediaSourceBase::ReadOptions::SEEK_CLOSEST_SYNC:
-        case MediaSourceBase::ReadOptions::SEEK_CLOSEST:
+        case MediaTrack::ReadOptions::SEEK_CLOSEST_SYNC:
+        case MediaTrack::ReadOptions::SEEK_CLOSEST:
             ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC",
                     seekMode);
             // fall-through
-        case MediaSourceBase::ReadOptions::SEEK_PREVIOUS_SYNC:
+        case MediaTrack::ReadOptions::SEEK_PREVIOUS_SYNC:
             if (index == 0) {
                 ALOGW("Previous sync not found; starting from the earliest "
                         "sync.");
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index df07fac..cbdd3cb 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -1,4 +1,5 @@
 /*
+
  * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +21,8 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/MediaExtractor.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 #include <utils/Vector.h>
@@ -40,10 +42,10 @@
     explicit MPEG2TSExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase &meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
 
     virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
 
@@ -72,7 +74,7 @@
 
     off64_t mOffset;
 
-    static bool isScrambledFormat(const sp<MetaData> &format);
+    static bool isScrambledFormat(MetaDataBase &format);
 
     void init();
     void addSource(const sp<AnotherPacketSource> &impl);
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 6d7576f..4d49013 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -22,7 +22,8 @@
 
 #include <cutils/properties.h>
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
+#include <media/VorbisComment.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/base64.h>
@@ -31,7 +32,7 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MetaDataBase.h>
 #include <utils/String8.h>
 
 extern "C" {
@@ -45,12 +46,12 @@
 
 namespace android {
 
-struct OggSource : public MediaSourceBase {
+struct OggSource : public MediaTrack {
     explicit OggSource(OggExtractor *extractor);
 
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &);
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
 
     virtual status_t read(
@@ -75,7 +76,7 @@
             int64_t seekPreRollUs);
     virtual ~MyOggExtractor();
 
-    sp<MetaData> getFormat() const;
+    status_t getFormat(MetaDataBase &) const;
 
     // Returns an approximate bitrate in bits per second.
     virtual uint64_t approxBitrate() const = 0;
@@ -86,7 +87,10 @@
 
     status_t init();
 
-    sp<MetaData> getFileMetaData() { return mFileMeta; }
+    status_t getFileMetaData(MetaDataBase &meta) {
+        meta = mFileMeta;
+        return OK;
+    }
 
 protected:
     struct Page {
@@ -124,8 +128,8 @@
     vorbis_info mVi;
     vorbis_comment mVc;
 
-    sp<MetaData> mMeta;
-    sp<MetaData> mFileMeta;
+    MetaDataBase mMeta;
+    MetaDataBase mFileMeta;
 
     Vector<TOCEntry> mTableOfContents;
 
@@ -219,9 +223,6 @@
     int64_t mStartGranulePosition;
 };
 
-static void extractAlbumArt(
-        const sp<MetaData> &fileMeta, const void *data, size_t size);
-
 ////////////////////////////////////////////////////////////////////////////////
 
 OggSource::OggSource(OggExtractor *extractor)
@@ -235,11 +236,11 @@
     }
 }
 
-sp<MetaData> OggSource::getFormat() {
-    return mExtractor->mImpl->getFormat();
+status_t OggSource::getFormat(MetaDataBase &meta) {
+    return mExtractor->mImpl->getFormat(meta);
 }
 
-status_t OggSource::start(MetaData * /* params */) {
+status_t OggSource::start(MetaDataBase * /* params */) {
     if (mStarted) {
         return INVALID_OPERATION;
     }
@@ -277,14 +278,14 @@
 
 #if 0
     int64_t timeUs;
-    if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
+    if (packet->meta_data().findInt64(kKeyTime, &timeUs)) {
         ALOGI("found time = %lld us", timeUs);
     } else {
         ALOGI("NO time");
     }
 #endif
 
-    packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    packet->meta_data().setInt32(kKeyIsSyncFrame, 1);
 
     *out = packet;
 
@@ -321,8 +322,9 @@
     vorbis_info_clear(&mVi);
 }
 
-sp<MetaData> MyOggExtractor::getFormat() const {
-    return mMeta;
+status_t MyOggExtractor::getFormat(MetaDataBase &meta) const {
+    meta = mMeta;
+    return OK;
 }
 
 status_t MyOggExtractor::findNextPage(
@@ -606,17 +608,17 @@
     int32_t currentPageSamples;
     // Calculate timestamps by accumulating durations starting from the first sample of a page;
     // We assume that we only seek to page boundaries.
-    if ((*out)->meta_data()->findInt32(kKeyValidSamples, &currentPageSamples)) {
+    if ((*out)->meta_data().findInt32(kKeyValidSamples, &currentPageSamples)) {
         // first packet in page
         if (mOffset == mFirstDataOffset) {
             currentPageSamples -= mStartGranulePosition;
-            (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples);
+            (*out)->meta_data().setInt32(kKeyValidSamples, currentPageSamples);
         }
         mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
     }
 
     int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
-    (*out)->meta_data()->setInt64(kKeyTime, timeUs);
+    (*out)->meta_data().setInt64(kKeyTime, timeUs);
 
     uint32_t frames = getNumSamplesInPacket(*out);
     mCurGranulePosition += frames;
@@ -745,7 +747,7 @@
                 // We've just read the entire packet.
 
                 if (mFirstPacketInPage) {
-                    buffer->meta_data()->setInt32(
+                    buffer->meta_data().setInt32(
                             kKeyValidSamples, mCurrentPageSamples);
                     mFirstPacketInPage = false;
                 }
@@ -767,7 +769,7 @@
                         mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
                         mCurrentPage.mPrevPacketSize = curBlockSize;
                     }
-                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+                    buffer->meta_data().setInt64(kKeyTime, timeUs);
                 }
                 *out = buffer;
 
@@ -813,10 +815,10 @@
                 // is already complete.
 
                 if (timeUs >= 0) {
-                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+                    buffer->meta_data().setInt64(kKeyTime, timeUs);
                 }
 
-                buffer->meta_data()->setInt32(
+                buffer->meta_data().setInt32(
                         kKeyValidSamples, mCurrentPageSamples);
                 mFirstPacketInPage = false;
 
@@ -829,8 +831,7 @@
 }
 
 status_t MyOggExtractor::init() {
-    mMeta = new MetaData;
-    mMeta->setCString(kKeyMIMEType, mMimeType);
+    mMeta.setCString(kKeyMIMEType, mMimeType);
 
     status_t err;
     MediaBufferBase *packet;
@@ -863,7 +864,7 @@
 
         int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
 
-        mMeta->setInt64(kKeyDuration, durationUs);
+        mMeta.setInt64(kKeyDuration, durationUs);
 
         buildTableOfContents();
     }
@@ -979,25 +980,35 @@
     mChannelCount = data[9];
     mCodecDelay = U16LE_AT(&data[10]);
 
-    mMeta->setData(kKeyOpusHeader, 0, data, size);
-    mMeta->setInt32(kKeySampleRate, kOpusSampleRate);
-    mMeta->setInt32(kKeyChannelCount, mChannelCount);
-    mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
-    mMeta->setInt64(kKeyOpusCodecDelay /* ns */,
+    mMeta.setData(kKeyOpusHeader, 0, data, size);
+    mMeta.setInt32(kKeySampleRate, kOpusSampleRate);
+    mMeta.setInt32(kKeyChannelCount, mChannelCount);
+    mMeta.setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
+    mMeta.setInt64(kKeyOpusCodecDelay /* ns */,
             mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
 
     return OK;
 }
 
+struct TmpData {
+    uint8_t *data;
+    TmpData(size_t size) {
+        data = (uint8_t*) malloc(size);
+    }
+    ~TmpData() {
+        free(data);
+    }
+};
+
 status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
     // add artificial framing bit so we can reuse _vorbis_unpack_comment
     int32_t commentSize = buffer->range_length() + 1;
-    sp<ABuffer> aBuf = new ABuffer(commentSize);
-    if (aBuf->capacity() <= buffer->range_length()) {
+    TmpData commentDataHolder(commentSize);
+    uint8_t *commentData = commentDataHolder.data;
+    if (commentData == nullptr) {
         return ERROR_MALFORMED;
     }
 
-    uint8_t* commentData = aBuf->data();
     memcpy(commentData,
             (uint8_t *)buffer->data() + buffer->range_offset(),
             buffer->range_length());
@@ -1120,10 +1131,10 @@
                 return ERROR_MALFORMED;
             }
 
-            mMeta->setData(kKeyVorbisInfo, 0, data, size);
-            mMeta->setInt32(kKeySampleRate, mVi.rate);
-            mMeta->setInt32(kKeyChannelCount, mVi.channels);
-            mMeta->setInt32(kKeyBitRate, mVi.bitrate_nominal);
+            mMeta.setData(kKeyVorbisInfo, 0, data, size);
+            mMeta.setInt32(kKeySampleRate, mVi.rate);
+            mMeta.setInt32(kKeyChannelCount, mVi.channels);
+            mMeta.setInt32(kKeyBitRate, mVi.bitrate_nominal);
 
             ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
             ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
@@ -1138,7 +1149,7 @@
             if (mSource->getSize(&size) == OK) {
                 uint64_t bps = approxBitrate();
                 if (bps != 0) {
-                    mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
+                    mMeta.setInt64(kKeyDuration, size * 8000000ll / bps);
                 }
             }
             break;
@@ -1160,7 +1171,7 @@
                 return ERROR_MALFORMED;
             }
 
-            mMeta->setData(kKeyVorbisBooks, 0, data, size);
+            mMeta.setData(kKeyVorbisBooks, 0, data, size);
             break;
         }
     }
@@ -1176,138 +1187,14 @@
     return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
 }
 
-// also exists in FLACExtractor, candidate for moving to utility/support library?
-static void parseVorbisComment(
-        const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
-{
-    struct {
-        const char *const mTag;
-        uint32_t mKey;
-    } kMap[] = {
-        { "TITLE", kKeyTitle },
-        { "ARTIST", kKeyArtist },
-        { "ALBUMARTIST", kKeyAlbumArtist },
-        { "ALBUM ARTIST", kKeyAlbumArtist },
-        { "COMPILATION", kKeyCompilation },
-        { "ALBUM", kKeyAlbum },
-        { "COMPOSER", kKeyComposer },
-        { "GENRE", kKeyGenre },
-        { "AUTHOR", kKeyAuthor },
-        { "TRACKNUMBER", kKeyCDTrackNumber },
-        { "DISCNUMBER", kKeyDiscNumber },
-        { "DATE", kKeyDate },
-        { "YEAR", kKeyYear },
-        { "LYRICIST", kKeyWriter },
-        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
-        { "ANDROID_LOOP", kKeyAutoLoop },
-    };
-
-        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
-            size_t tagLen = strlen(kMap[j].mTag);
-            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
-                    && comment[tagLen] == '=') {
-                if (kMap[j].mKey == kKeyAlbumArt) {
-                    extractAlbumArt(
-                            fileMeta,
-                            &comment[tagLen + 1],
-                            commentLength - tagLen - 1);
-                } else if (kMap[j].mKey == kKeyAutoLoop) {
-                    if (!strcasecmp(&comment[tagLen + 1], "true")) {
-                        fileMeta->setInt32(kKeyAutoLoop, true);
-                    }
-                } else {
-                    fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
-                }
-            }
-        }
-
-}
-
-// also exists in FLACExtractor, candidate for moving to utility/support library?
-static void extractAlbumArt(
-        const sp<MetaData> &fileMeta, const void *data, size_t size) {
-    ALOGV("extractAlbumArt from '%s'", (const char *)data);
-
-    sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size));
-    if (flacBuffer == NULL) {
-        ALOGE("malformed base64 encoded data.");
-        return;
-    }
-
-    size_t flacSize = flacBuffer->size();
-    uint8_t *flac = flacBuffer->data();
-    ALOGV("got flac of size %zu", flacSize);
-
-    uint32_t picType;
-    uint32_t typeLen;
-    uint32_t descLen;
-    uint32_t dataLen;
-    char type[128];
-
-    if (flacSize < 8) {
-        return;
-    }
-
-    picType = U32_AT(flac);
-
-    if (picType != 3) {
-        // This is not a front cover.
-        return;
-    }
-
-    typeLen = U32_AT(&flac[4]);
-    if (typeLen > sizeof(type) - 1) {
-        return;
-    }
-
-    // we've already checked above that flacSize >= 8
-    if (flacSize - 8 < typeLen) {
-        return;
-    }
-
-    memcpy(type, &flac[8], typeLen);
-    type[typeLen] = '\0';
-
-    ALOGV("picType = %d, type = '%s'", picType, type);
-
-    if (!strcmp(type, "-->")) {
-        // This is not inline cover art, but an external url instead.
-        return;
-    }
-
-    if (flacSize < 32 || flacSize - 32 < typeLen) {
-        return;
-    }
-
-    descLen = U32_AT(&flac[8 + typeLen]);
-    if (flacSize - 32 - typeLen < descLen) {
-        return;
-    }
-
-    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
-
-    // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
-    if (flacSize - 32 - typeLen - descLen < dataLen) {
-        return;
-    }
-
-    ALOGV("got image data, %zu trailing bytes",
-         flacSize - 32 - typeLen - descLen - dataLen);
-
-    fileMeta->setData(
-            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
-
-    fileMeta->setCString(kKeyAlbumArtMIME, type);
-}
 
 void MyOggExtractor::parseFileMetaData() {
-    mFileMeta = new MetaData;
-    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+    mFileMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
 
     for (int i = 0; i < mVc.comments; ++i) {
         const char *comment = mVc.user_comments[i];
         size_t commentLength = mVc.comment_lengths[i];
-        parseVorbisComment(mFileMeta, comment, commentLength);
+        parseVorbisComment(&mFileMeta, comment, commentLength);
         //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
     }
 }
@@ -1348,7 +1235,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-MediaSourceBase *OggExtractor::getTrack(size_t index) {
+MediaTrack *OggExtractor::getTrack(size_t index) {
     if (index >= 1) {
         return NULL;
     }
@@ -1356,17 +1243,18 @@
     return new OggSource(this);
 }
 
-sp<MetaData> OggExtractor::getTrackMetaData(
+status_t OggExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     if (index >= 1) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
-    return mImpl->getFormat();
+    return mImpl->getFormat(meta);
 }
 
-sp<MetaData> OggExtractor::getMetaData() {
-    return mImpl->getFileMetaData();
+status_t OggExtractor::getMetaData(MetaDataBase &meta) {
+    return mImpl->getFileMetaData(meta);
 }
 
 static MediaExtractor* CreateExtractor(
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index c9c37eb..9fe2944 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -34,10 +34,10 @@
     explicit OggExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "OggExtractor"; }
 
 protected:
@@ -55,10 +55,6 @@
     OggExtractor &operator=(const OggExtractor &);
 };
 
-bool SniffOgg(
-        DataSourceBase *source, String8 *mimeType, float *confidence,
-        sp<AMessage> *);
-
 }  // namespace android
 
 #endif  // OGG_EXTRACTOR_H_
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 65c71ef..17836bb 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -10,7 +10,6 @@
         "liblog",
         "libmediaextractor",
         "libstagefright_foundation",
-        "libutils",
     ],
 
     static_libs: [
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index a18cee5..f5a1b01 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -22,7 +22,7 @@
 
 #include <audio_utils/primitives.h>
 #include <media/DataSourceBase.h>
-#include <media/MediaSourceBase.h>
+#include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -55,17 +55,17 @@
     return ptr[1] << 8 | ptr[0];
 }
 
-struct WAVSource : public MediaSourceBase {
+struct WAVSource : public MediaTrack {
     WAVSource(
             DataSourceBase *dataSource,
-            const sp<MetaData> &meta,
+            MetaDataBase &meta,
             uint16_t waveFormat,
             int32_t bitsPerSample,
             off64_t offset, size_t size);
 
-    virtual status_t start(MetaData *params = NULL);
+    virtual status_t start(MetaDataBase *params = NULL);
     virtual status_t stop();
-    virtual sp<MetaData> getFormat();
+    virtual status_t getFormat(MetaDataBase &meta);
 
     virtual status_t read(
             MediaBufferBase **buffer, const ReadOptions *options = NULL);
@@ -79,7 +79,7 @@
     static const size_t kMaxFrameSize;
 
     DataSourceBase *mDataSource;
-    sp<MetaData> mMeta;
+    MetaDataBase &mMeta;
     uint16_t mWaveFormat;
     int32_t mSampleRate;
     int32_t mNumChannels;
@@ -104,23 +104,20 @@
 WAVExtractor::~WAVExtractor() {
 }
 
-sp<MetaData> WAVExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-
-    if (mInitCheck != OK) {
-        return meta;
+status_t WAVExtractor::getMetaData(MetaDataBase &meta) {
+    meta.clear();
+    if (mInitCheck == OK) {
+        meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_WAV);
     }
 
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_WAV);
-
-    return meta;
+    return OK;
 }
 
 size_t WAVExtractor::countTracks() {
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaSourceBase *WAVExtractor::getTrack(size_t index) {
+MediaTrack *WAVExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index > 0) {
         return NULL;
     }
@@ -130,13 +127,15 @@
             mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
 }
 
-sp<MetaData> WAVExtractor::getTrackMetaData(
+status_t WAVExtractor::getTrackMetaData(
+        MetaDataBase &meta,
         size_t index, uint32_t /* flags */) {
     if (mInitCheck != OK || index > 0) {
-        return NULL;
+        return UNKNOWN_ERROR;
     }
 
-    return mTrackMeta;
+    meta = mTrackMeta;
+    return OK;
 }
 
 status_t WAVExtractor::init() {
@@ -285,33 +284,33 @@
                 mDataOffset = offset;
                 mDataSize = chunkSize;
 
-                mTrackMeta = new MetaData;
+                mTrackMeta.clear();
 
                 switch (mWaveFormat) {
                     case WAVE_FORMAT_PCM:
                     case WAVE_FORMAT_IEEE_FLOAT:
-                        mTrackMeta->setCString(
+                        mTrackMeta.setCString(
                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
                         break;
                     case WAVE_FORMAT_ALAW:
-                        mTrackMeta->setCString(
+                        mTrackMeta.setCString(
                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
                         break;
                     case WAVE_FORMAT_MSGSM:
-                        mTrackMeta->setCString(
+                        mTrackMeta.setCString(
                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MSGSM);
                         break;
                     default:
                         CHECK_EQ(mWaveFormat, (uint16_t)WAVE_FORMAT_MULAW);
-                        mTrackMeta->setCString(
+                        mTrackMeta.setCString(
                                 kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
                         break;
                 }
 
-                mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
-                mTrackMeta->setInt32(kKeyChannelMask, mChannelMask);
-                mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
-                mTrackMeta->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
+                mTrackMeta.setInt32(kKeyChannelCount, mNumChannels);
+                mTrackMeta.setInt32(kKeyChannelMask, mChannelMask);
+                mTrackMeta.setInt32(kKeySampleRate, mSampleRate);
+                mTrackMeta.setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
 
                 int64_t durationUs = 0;
                 if (mWaveFormat == WAVE_FORMAT_MSGSM) {
@@ -333,7 +332,7 @@
                         1000000LL * num_samples / mSampleRate;
                 }
 
-                mTrackMeta->setInt64(kKeyDuration, durationUs);
+                mTrackMeta.setInt64(kKeyDuration, durationUs);
 
                 return OK;
             }
@@ -349,7 +348,7 @@
 
 WAVSource::WAVSource(
         DataSourceBase *dataSource,
-        const sp<MetaData> &meta,
+        MetaDataBase &meta,
         uint16_t waveFormat,
         int32_t bitsPerSample,
         off64_t offset, size_t size)
@@ -363,10 +362,10 @@
       mSize(size),
       mStarted(false),
       mGroup(NULL) {
-    CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
-    CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
+    CHECK(mMeta.findInt32(kKeySampleRate, &mSampleRate));
+    CHECK(mMeta.findInt32(kKeyChannelCount, &mNumChannels));
 
-    mMeta->setInt32(kKeyMaxInputSize, kMaxFrameSize);
+    mMeta.setInt32(kKeyMaxInputSize, kMaxFrameSize);
 }
 
 WAVSource::~WAVSource() {
@@ -375,7 +374,7 @@
     }
 }
 
-status_t WAVSource::start(MetaData * /* params */) {
+status_t WAVSource::start(MetaDataBase * /* params */) {
     ALOGV("WAVSource::start");
 
     CHECK(!mStarted);
@@ -408,10 +407,11 @@
     return OK;
 }
 
-sp<MetaData> WAVSource::getFormat() {
+status_t WAVSource::getFormat(MetaDataBase &meta) {
     ALOGV("WAVSource::getFormat");
 
-    return mMeta;
+    meta = mMeta;
+    return OK;
 }
 
 status_t WAVSource::read(
@@ -532,9 +532,9 @@
                 / (mNumChannels * bytesPerSample) / mSampleRate;
     }
 
-    buffer->meta_data()->setInt64(kKeyTime, timeStampUs);
+    buffer->meta_data().setInt64(kKeyTime, timeStampUs);
 
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
     mCurrentPos += n;
 
     *out = buffer;
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 67661ed..467d0b7 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -20,6 +20,7 @@
 
 #include <utils/Errors.h>
 #include <media/MediaExtractor.h>
+#include <media/stagefright/MetaDataBase.h>
 
 namespace android {
 
@@ -32,10 +33,10 @@
     explicit WAVExtractor(DataSourceBase *source);
 
     virtual size_t countTracks();
-    virtual MediaSourceBase *getTrack(size_t index);
-    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
 
-    virtual sp<MetaData> getMetaData();
+    virtual status_t getMetaData(MetaDataBase& meta);
     virtual const char * name() { return "WAVExtractor"; }
 
     virtual ~WAVExtractor();
@@ -51,7 +52,7 @@
     uint16_t mBitsPerSample;
     off64_t mDataOffset;
     size_t mDataSize;
-    sp<MetaData> mTrackMeta;
+    MetaDataBase mTrackMeta;
 
     status_t init();