Make MP4 extractor use AMediaFormat

Bug: 111407253
Test: manual, CTS
Change-Id: I43fcd270134d653a58715e1da38658d307a59774
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 40b2c97..47dc718 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -16,6 +16,7 @@
     shared_libs: [
         "liblog",
         "libmediaextractor",
+        "libmediandk"
     ],
 
     static_libs: [
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index a61e60a..55a0c47 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -1477,7 +1477,7 @@
     return mImageItemsValid ? mDisplayables.size() : 0;
 }
 
-sp<MetaData> ItemTable::getImageMeta(const uint32_t imageIndex) {
+AMediaFormat *ItemTable::getImageMeta(const uint32_t imageIndex) {
     if (!mImageItemsValid) {
         return NULL;
     }
@@ -1502,28 +1502,31 @@
         }
     }
 
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
+    AMediaFormat *meta = AMediaFormat_new();
+    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
 
     if (image->itemId == mPrimaryItemId) {
-        meta->setInt32(kKeyTrackIsDefault, 1);
+        AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_DEFAULT, 1);
     }
 
     ALOGV("image[%u]: size %dx%d", imageIndex, image->width, image->height);
 
-    meta->setInt32(kKeyWidth, image->width);
-    meta->setInt32(kKeyHeight, image->height);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, image->width);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, image->height);
     if (image->rotation != 0) {
         // Rotation angle in HEIF is CCW, convert to CW here to be
         // consistent with the other media formats.
         switch(image->rotation) {
-            case 90: meta->setInt32(kKeyRotation, 270); break;
-            case 180: meta->setInt32(kKeyRotation, 180); break;
-            case 270: meta->setInt32(kKeyRotation, 90); break;
+            case 90:
+            case 180:
+            case 270:
+                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_ROTATION, 360 - image->rotation);
+                break;
             default: break; // don't set if invalid
         }
     }
-    meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
+    AMediaFormat_setInt32(meta,
+            AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 1.5);
 
     if (!image->thumbnails.empty()) {
         ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(image->thumbnails[0]);
@@ -1531,10 +1534,12 @@
             const ImageItem &thumbnail = mItemIdToItemMap[thumbItemIndex];
 
             if (thumbnail.hvcc != NULL) {
-                meta->setInt32(kKeyThumbnailWidth, thumbnail.width);
-                meta->setInt32(kKeyThumbnailHeight, thumbnail.height);
-                meta->setData(kKeyThumbnailHVCC, kTypeHVCC,
-                        thumbnail.hvcc->data(), thumbnail.hvcc->size());
+                AMediaFormat_setInt32(meta,
+                        AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH, thumbnail.width);
+                AMediaFormat_setInt32(meta,
+                        AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT, thumbnail.height);
+                AMediaFormat_setBuffer(meta,
+                        AMEDIAFORMAT_KEY_CSD_HEVC, thumbnail.hvcc->data(), thumbnail.hvcc->size());
                 ALOGV("image[%u]: thumbnail: size %dx%d, item index %zd",
                         imageIndex, thumbnail.width, thumbnail.height, thumbItemIndex);
             } else {
@@ -1546,24 +1551,30 @@
     }
 
     if (image->isGrid()) {
-        meta->setInt32(kKeyGridRows, image->rows);
-        meta->setInt32(kKeyGridCols, image->columns);
-
+        AMediaFormat_setInt32(meta,
+                AMEDIAFORMAT_KEY_GRID_ROWS, image->rows);
+        AMediaFormat_setInt32(meta,
+                AMEDIAFORMAT_KEY_GRID_COLUMNS, image->columns);
         // point image to the first tile for grid size and HVCC
         image = &mItemIdToItemMap.editValueAt(tileItemIndex);
-        meta->setInt32(kKeyTileWidth, image->width);
-        meta->setInt32(kKeyTileHeight, image->height);
-        meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
+        AMediaFormat_setInt32(meta,
+                AMEDIAFORMAT_KEY_TILE_WIDTH, image->width);
+        AMediaFormat_setInt32(meta,
+                AMEDIAFORMAT_KEY_TILE_HEIGHT, image->height);
+        AMediaFormat_setInt32(meta,
+                AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 1.5);
     }
 
     if (image->hvcc == NULL) {
         ALOGE("%s: hvcc is missing for image[%u]!", __FUNCTION__, imageIndex);
         return NULL;
     }
-    meta->setData(kKeyHVCC, kTypeHVCC, image->hvcc->data(), image->hvcc->size());
+    AMediaFormat_setBuffer(meta,
+            AMEDIAFORMAT_KEY_CSD_HEVC, image->hvcc->data(), image->hvcc->size());
 
     if (image->icc != NULL) {
-        meta->setData(kKeyIccProfile, 0, image->icc->data(), image->icc->size());
+        AMediaFormat_setBuffer(meta,
+                AMEDIAFORMAT_KEY_ICC_PROFILE, image->icc->data(), image->icc->size());
     }
     return meta;
 }
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index 650b3f3..be81b59 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -19,6 +19,8 @@
 
 #include <set>
 
+#include <media/NdkMediaFormat.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -51,7 +53,7 @@
 
     bool isValid() { return mImageItemsValid; }
     uint32_t countImages() const;
-    sp<MetaData> getImageMeta(const uint32_t imageIndex);
+    AMediaFormat *getImageMeta(const uint32_t imageIndex);
     status_t findImageItem(const uint32_t imageIndex, uint32_t *itemIndex);
     status_t findThumbnailItem(const uint32_t imageIndex, uint32_t *itemIndex);
     status_t getImageOffsetAndSize(
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7323f43..b362b4a 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -69,11 +69,11 @@
     kMaxAtomSize = 64 * 1024 * 1024,
 };
 
-class MPEG4Source : public MediaTrackHelper {
+class MPEG4Source : public MediaTrackHelperV2 {
 static const size_t  kMaxPcmFrameSize = 8192;
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
-    MPEG4Source(MetaDataBase &format,
+    MPEG4Source(AMediaFormat *format,
                 DataSourceHelper *dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
@@ -83,21 +83,22 @@
                 const sp<ItemTable> &itemTable);
     virtual status_t init();
 
-    virtual status_t start();
-    virtual status_t stop();
+    virtual media_status_t start();
+    virtual media_status_t stop();
 
-    virtual status_t getFormat(MetaDataBase &);
+    virtual media_status_t getFormat(AMediaFormat *);
 
-    virtual status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
+    virtual media_status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
     virtual bool supportNonblockingRead() { return true; }
-    virtual status_t fragmentedRead(MediaBufferBase **buffer, const ReadOptions *options = NULL);
+    virtual media_status_t fragmentedRead(
+            MediaBufferBase **buffer, const ReadOptions *options = NULL);
 
     virtual ~MPEG4Source();
 
 private:
     Mutex mLock;
 
-    MetaDataBase &mFormat;
+    AMediaFormat *mFormat;
     DataSourceHelper *mDataSource;
     int32_t mTimescale;
     sp<SampleTable> mSampleTable;
@@ -379,6 +380,7 @@
       mFirstTrack(NULL),
       mLastTrack(NULL) {
     ALOGV("mime=%s, mPreferHeif=%d", mime, mPreferHeif);
+    mFileMetaData = AMediaFormat_new();
 }
 
 MPEG4Extractor::~MPEG4Extractor() {
@@ -386,6 +388,7 @@
     while (track) {
         Track *next = track->next;
 
+        AMediaFormat_delete(track->meta);
         delete track;
         track = next;
     }
@@ -397,6 +400,7 @@
     mPssh.clear();
 
     delete mDataSource;
+    AMediaFormat_delete(mFileMetaData);
 }
 
 uint32_t MPEG4Extractor::flags() const {
@@ -405,13 +409,13 @@
                     (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
 }
 
-status_t MPEG4Extractor::getMetaData(MetaDataBase &meta) {
+media_status_t MPEG4Extractor::getMetaData(AMediaFormat *meta) {
     status_t err;
     if ((err = readMetaData()) != OK) {
-        return UNKNOWN_ERROR;
+        return AMEDIA_ERROR_UNKNOWN;
     }
-    meta = mFileMetaData;
-    return OK;
+    AMediaFormat_copy(meta, mFileMetaData);
+    return AMEDIA_OK;
 }
 
 size_t MPEG4Extractor::countTracks() {
@@ -432,18 +436,18 @@
     return n;
 }
 
-status_t MPEG4Extractor::getTrackMetaData(
-        MetaDataBase &meta,
+media_status_t MPEG4Extractor::getTrackMetaData(
+        AMediaFormat *meta,
         size_t index, uint32_t flags) {
     status_t err;
     if ((err = readMetaData()) != OK) {
-        return UNKNOWN_ERROR;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
     Track *track = mFirstTrack;
     while (index > 0) {
         if (track == NULL) {
-            return UNKNOWN_ERROR;
+            return AMEDIA_ERROR_UNKNOWN;
         }
 
         track = track->next;
@@ -451,15 +455,15 @@
     }
 
     if (track == NULL) {
-        return UNKNOWN_ERROR;
+        return AMEDIA_ERROR_UNKNOWN;
     }
 
     [=] {
         int64_t duration;
         int32_t samplerate;
         if (track->has_elst && mHeaderTimescale != 0 &&
-                track->meta.findInt64(kKeyDuration, &duration) &&
-                track->meta.findInt32(kKeySampleRate, &samplerate)) {
+                AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
+                AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
 
             track->has_elst = false;
 
@@ -493,7 +497,7 @@
                 return;
             }
             ALOGV("delay = %" PRId64, delay);
-            track->meta.setInt32(kKeyEncoderDelay, delay);
+            AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_DELAY, delay);
 
             int64_t scaled_duration;
             // scaled_duration = duration * mHeaderTimescale;
@@ -513,8 +517,8 @@
             ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
 
             if (padding < 0) {
-                // track duration from media header (which is what kKeyDuration is) might
-                // be slightly shorter than the segment duration, which would make the
+                // track duration from media header (which is what AMEDIAFORMAT_KEY_DURATION is)
+                // might be slightly shorter than the segment duration, which would make the
                 // padding negative. Clamp to zero.
                 padding = 0;
             }
@@ -533,7 +537,7 @@
                 return;
             }
             ALOGV("paddingsamples = %" PRId64, paddingsamples);
-            track->meta.setInt32(kKeyEncoderPadding, paddingsamples);
+            AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_PADDING, paddingsamples);
         }
     }();
 
@@ -542,7 +546,7 @@
         track->includes_expensive_metadata = true;
 
         const char *mime;
-        CHECK(track->meta.findCString(kKeyMIMEType, &mime));
+        CHECK(AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime));
         if (!strncasecmp("video/", mime, 6)) {
             // MPEG2 tracks do not provide CSD, so read the stream header
             if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)) {
@@ -555,17 +559,19 @@
                     }
                     uint8_t header[kMaxTrackHeaderSize];
                     if (mDataSource->readAt(offset, &header, size) == (ssize_t)size) {
-                        track->meta.setData(kKeyStreamHeader, 'mdat', header, size);
+                        AMediaFormat_setBuffer(track->meta,
+                                AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER, header, size);
                     }
                 }
             }
 
             if (mMoofOffset > 0) {
                 int64_t duration;
-                if (track->meta.findInt64(kKeyDuration, &duration)) {
+                if (AMediaFormat_getInt64(track->meta,
+                        AMEDIAFORMAT_KEY_DURATION, &duration)) {
                     // nothing fancy, just pick a frame near 1/4th of the duration
-                    track->meta.setInt64(
-                            kKeyThumbnailTime, duration / 4);
+                    AMediaFormat_setInt64(track->meta,
+                            AMEDIAFORMAT_KEY_THUMBNAIL_TIME, duration / 4);
                 }
             } else {
                 uint32_t sampleIndex;
@@ -575,16 +581,16 @@
                         && track->sampleTable->getMetaDataForSample(
                             sampleIndex, NULL /* offset */, NULL /* size */,
                             &sampleTime) == OK) {
-                    track->meta.setInt64(
-                            kKeyThumbnailTime,
-                            ((int64_t)sampleTime * 1000000) / track->timescale);
+                        AMediaFormat_setInt64(track->meta,
+                                AMEDIAFORMAT_KEY_THUMBNAIL_TIME,
+                                ((int64_t)sampleTime * 1000000) / track->timescale);
                 }
             }
         }
     }
 
-    meta = track->meta;
-    return OK;
+    AMediaFormat_copy(meta, track->meta);
+    return AMEDIA_OK;
 }
 
 status_t MPEG4Extractor::readMetaData() {
@@ -619,12 +625,14 @@
         off64_t exifOffset;
         size_t exifSize;
         if (mItemTable->getExifOffsetAndSize(&exifOffset, &exifSize) == OK) {
-            mFileMetaData.setInt64(kKeyExifOffset, (int64_t)exifOffset);
-            mFileMetaData.setInt64(kKeyExifSize, (int64_t)exifSize);
+            AMediaFormat_setInt64(mFileMetaData,
+                    AMEDIAFORMAT_KEY_EXIF_OFFSET, (int64_t)exifOffset);
+            AMediaFormat_setInt64(mFileMetaData,
+                    AMEDIAFORMAT_KEY_EXIF_SIZE, (int64_t)exifSize);
         }
         for (uint32_t imageIndex = 0;
                 imageIndex < mItemTable->countImages(); imageIndex++) {
-            sp<MetaData> meta = mItemTable->getImageMeta(imageIndex);
+            AMediaFormat *meta = mItemTable->getImageMeta(imageIndex);
             if (meta == NULL) {
                 ALOGE("heif image %u has no meta!", imageIndex);
                 continue;
@@ -649,8 +657,8 @@
             }
             mLastTrack = track;
 
-            track->meta = *(meta.get());
-            track->meta.setInt32(kKeyTrackID, imageIndex);
+            track->meta = meta;
+            AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_TRACK_ID, imageIndex);
             track->includes_expensive_metadata = false;
             track->skipTrack = false;
             track->timescale = 1000000;
@@ -659,16 +667,18 @@
 
     if (mInitCheck == OK) {
         if (findTrackByMimePrefix("video/") != NULL) {
-            mFileMetaData.setCString(
-                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
+            AMediaFormat_setString(mFileMetaData,
+                    AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_MPEG4);
         } else if (findTrackByMimePrefix("audio/") != NULL) {
-            mFileMetaData.setCString(kKeyMIMEType, "audio/mp4");
+            AMediaFormat_setString(mFileMetaData,
+                    AMEDIAFORMAT_KEY_MIME, "audio/mp4");
         } else if (findTrackByMimePrefix(
                 MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC) != NULL) {
-            mFileMetaData.setCString(
-                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_HEIF);
+            AMediaFormat_setString(mFileMetaData,
+                    AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_HEIF);
         } else {
-            mFileMetaData.setCString(kKeyMIMEType, "application/octet-stream");
+            AMediaFormat_setString(mFileMetaData,
+                    AMEDIAFORMAT_KEY_MIME, "application/octet-stream");
         }
     } else {
         mInitCheck = err;
@@ -693,7 +703,7 @@
             memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
             ptr += (20 + mPssh[i].datalen);
         }
-        mFileMetaData.setData(kKeyPssh, 'pssh', buf, psshsize);
+        AMediaFormat_setBuffer(mFileMetaData, AMEDIAFORMAT_KEY_PSSH, buf, psshsize);
         free(buf);
     }
 
@@ -944,7 +954,9 @@
                 track->includes_expensive_metadata = false;
                 track->skipTrack = false;
                 track->timescale = 0;
-                track->meta.setCString(kKeyMIMEType, "application/octet-stream");
+                track->meta = AMediaFormat_new();
+                AMediaFormat_setString(track->meta,
+                        AMEDIAFORMAT_KEY_MIME, "application/octet-stream");
                 track->has_elst = false;
                 track->subsample_encryption = false;
             }
@@ -968,8 +980,10 @@
 
             if (isTrack) {
                 int32_t trackId;
-                // There must be exact one track header per track.
-                if (!mLastTrack->meta.findInt32(kKeyTrackID, &trackId)) {
+                // There must be exactly one track header per track.
+
+                if (!AMediaFormat_getInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_TRACK_ID, &trackId)) {
                     mLastTrack->skipTrack = true;
                 }
 
@@ -1045,7 +1059,7 @@
                 }
             }
             if (mode != kCryptoModeUnencrypted) {
-                mLastTrack->meta.setInt32(kKeyCryptoMode, mode);
+                AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CRYPTO_MODE, mode);
             }
             break;
         }
@@ -1121,12 +1135,15 @@
                 return ERROR_MALFORMED;
             }
 
-            mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
+            AMediaFormat_setString(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_MIME, 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);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
             }
 
             // If format type is 'alac', it is necessary to get the parameters
@@ -1155,11 +1172,14 @@
                 }
 
                 uint8_t bitsPerSample = cookie[5];
-                mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample);
-                mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]);
-                mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20]));
-                mLastTrack->meta.setData(
-                    kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie));
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
+                AMediaFormat_setBuffer(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
 
                 // Add the size of ALAC Specific Info (36 bytes) and terminator
                 // atom (8 bytes).
@@ -1260,16 +1280,23 @@
             }
 
             int32_t tmpAlgorithmId;
-            if (!mLastTrack->meta.findInt32(kKeyCryptoMode, &tmpAlgorithmId)) {
-                mLastTrack->meta.setInt32(kKeyCryptoMode, defaultAlgorithmId);
+            if (!AMediaFormat_getInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_CRYPTO_MODE, &tmpAlgorithmId)) {
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CRYPTO_MODE, defaultAlgorithmId);
             }
 
-            mLastTrack->meta.setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
-            mLastTrack->meta.setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
-            mLastTrack->meta.setInt32(kKeyEncryptedByteBlock, defaultEncryptedByteBlock);
-            mLastTrack->meta.setInt32(kKeySkipByteBlock, defaultSkipByteBlock);
+            AMediaFormat_setInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, defaultIVSize);
+            AMediaFormat_setBuffer(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_CRYPTO_KEY, defaultKeyId, 16);
+            AMediaFormat_setInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK, defaultEncryptedByteBlock);
+            AMediaFormat_setInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK, defaultSkipByteBlock);
             if (defaultConstantIv != NULL) {
-                mLastTrack->meta.setData(kKeyCryptoIV, 'dciv', defaultConstantIv->data(), defaultConstantIv->size());
+                AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CRYPTO_IV,
+                        defaultConstantIv->data(), defaultConstantIv->size());
             }
             break;
         }
@@ -1418,8 +1445,8 @@
                 }
             }
             if (duration != 0 && mLastTrack->timescale != 0) {
-                mLastTrack->meta.setInt64(
-                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
+                AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION,
+                        (duration * 1000000) / mLastTrack->timescale);
             }
 
             uint8_t lang[2];
@@ -1446,8 +1473,7 @@
             lang_code[2] = (lang[1] & 0x1f) + 0x60;
             lang_code[3] = '\0';
 
-            mLastTrack->meta.setCString(
-                    kKeyMediaLanguage, lang_code);
+            AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_LANGUAGE, lang_code);
 
             break;
         }
@@ -1481,7 +1507,7 @@
                 if (mLastTrack == NULL)
                     return ERROR_MALFORMED;
 
-                CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
+                CHECK(AMediaFormat_getString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, &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.
@@ -1522,7 +1548,7 @@
             }
 
             String8 mimeFormat((const char *)(buffer.get()), chunk_data_size);
-            mLastTrack->meta.setCString(kKeyMIMEType, mimeFormat.string());
+            AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
 
             break;
         }
@@ -1601,20 +1627,23 @@
 
             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));
+                AMediaFormat_setString(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_MIME, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
 
                 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, FourCC2MIME(chunk_type))) {
-                    mLastTrack->meta.setInt32(kKeyBitsPerSample, sample_size);
+                    AMediaFormat_setInt32(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, sample_size);
                     if (chunk_type == FOURCC('t', 'w', 'o', 's')) {
-                        mLastTrack->meta.setInt32(kKeyPcmBigEndian, 1);
+                        AMediaFormat_setInt32(mLastTrack->meta,
+                                AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, 1);
                     }
                 }
             }
             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);
+            AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels);
+            AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
 
             if (chunk_type == FOURCC('a', 'l', 'a', 'c')) {
 
@@ -1640,11 +1669,14 @@
                 }
 
                 uint8_t bitsPerSample = cookie[5];
-                mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample);
-                mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]);
-                mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20]));
-                mLastTrack->meta.setData(
-                        kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie));
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
+                AMediaFormat_setBuffer(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
                 data_offset += sizeof(cookie);
                 *offset = data_offset;
                 CHECK_EQ(*offset, stop_offset);
@@ -1702,10 +1734,11 @@
 
             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));
+                AMediaFormat_setString(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_MIME, FourCC2MIME(chunk_type));
             }
-            mLastTrack->meta.setInt32(kKeyWidth, width);
-            mLastTrack->meta.setInt32(kKeyHeight, height);
+            AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_WIDTH, width);
+            AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_HEIGHT, height);
 
             off64_t stop_offset = *offset + chunk_size;
             *offset = data_offset + sizeof(buffer);
@@ -1793,12 +1826,15 @@
                     ALOGE("max sample size too big: %zu", max_size);
                     return ERROR_MALFORMED;
                 }
-                mLastTrack->meta.setInt32(kKeyMaxInputSize, max_size + 10 * 2);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, 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 (!AMediaFormat_getInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_WIDTH, (int32_t*)&width) ||
+                    !AMediaFormat_getInt32(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_HEIGHT,(int32_t*) &height)) {
                     ALOGE("No width or height, assuming worst case 1080p");
                     width = 1920;
                     height = 1080;
@@ -1813,7 +1849,7 @@
                 }
 
                 const char *mime;
-                CHECK(mLastTrack->meta.findCString(kKeyMIMEType, &mime));
+                CHECK(AMediaFormat_getString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, &mime));
                 if (!strncmp(mime, "audio/", 6)) {
                     // for audio, use 128KB
                     max_size = 1024 * 128;
@@ -1830,26 +1866,28 @@
                 // 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);
+                AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, 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(AMediaFormat_getString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, &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 (AMediaFormat_getInt32(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_TRACK_ID, &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);
+                                    AMediaFormat_setInt32(mLastTrack->meta,
+                                            AMEDIAFORMAT_KEY_FRAME_RATE, frameRate);
                                 }
                                 break;
                             }
@@ -1857,15 +1895,18 @@
                     }
                 } else {
                     int64_t durationUs;
-                    if (mLastTrack->meta.findInt64(kKeyDuration, &durationUs)) {
+                    if (AMediaFormat_getInt64(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_DURATION, &durationUs)) {
                         if (durationUs > 0) {
                             int32_t frameRate = (nSamples * 1000000LL +
                                         (durationUs >> 1)) / durationUs;
-                            mLastTrack->meta.setInt32(kKeyFrameRate, frameRate);
+                            AMediaFormat_setInt32(mLastTrack->meta,
+                                    AMEDIAFORMAT_KEY_FRAME_RATE, frameRate);
                         }
                     }
                     ALOGV("setting frame count %zu", nSamples);
-                    mLastTrack->meta.setInt32(kKeyFrameCount, nSamples);
+                    AMediaFormat_setInt32(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_FRAME_COUNT, nSamples);
                 }
             }
 
@@ -1973,7 +2014,7 @@
             if (buffer[len - 1] != '/') {
                 buffer[len] = '/';
             }
-            mFileMetaData.setCString(kKeyLocation, &buffer[0]);
+            AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_LOCATION, &buffer[0]);
             break;
         }
 
@@ -2003,8 +2044,8 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta.setData(
-                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
+            AMediaFormat_setBuffer(mLastTrack->meta, 
+                    AMEDIAFORMAT_KEY_ESDS, &buffer[4], chunk_data_size - 4);
 
             if (mPath.size() >= 2
                     && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
@@ -2028,7 +2069,8 @@
                 uint8_t objectTypeIndication;
                 if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
                     if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
-                        mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
+                        AMediaFormat_setString(mLastTrack->meta,
+                                AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_MPEG2);
                     }
                 }
             }
@@ -2055,10 +2097,12 @@
             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);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_MAX_BIT_RATE, (int32_t)maxBitrate);
             }
             if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
-                mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
+                AMediaFormat_setInt32(mLastTrack->meta,
+                        AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)avgBitrate);
             }
             break;
         }
@@ -2082,8 +2126,8 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta.setData(
-                    kKeyAVCC, kTypeAVCC, buffer.get(), chunk_data_size);
+            AMediaFormat_setBuffer(mLastTrack->meta, 
+                    AMEDIAFORMAT_KEY_CSD_AVC, buffer.get(), chunk_data_size);
 
             break;
         }
@@ -2104,8 +2148,8 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta.setData(
-                    kKeyHVCC, kTypeHVCC, buffer.get(), chunk_data_size);
+            AMediaFormat_setBuffer(mLastTrack->meta, 
+                    AMEDIAFORMAT_KEY_CSD_HEVC, buffer.get(), chunk_data_size);
 
             *offset += chunk_size;
             break;
@@ -2140,7 +2184,8 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            mLastTrack->meta.setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
+            AMediaFormat_setBuffer(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_D263, buffer, chunk_data_size);
 
             break;
         }
@@ -2268,15 +2313,15 @@
                 duration = d32;
             }
             if (duration != 0 && mHeaderTimescale != 0 && duration < UINT64_MAX / 1000000) {
-                mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+                AMediaFormat_setInt64(mFileMetaData,
+                        AMEDIAFORMAT_KEY_DURATION, duration * 1000000 / mHeaderTimescale);
             }
 
             String8 s;
             if (convertTimeToDate(creationTime, &s)) {
-                mFileMetaData.setCString(kKeyDate, s.string());
+                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DATE, s.string());
             }
 
-
             break;
         }
 
@@ -2318,7 +2363,8 @@
             }
 
             if (duration != 0 && mHeaderTimescale != 0) {
-                mFileMetaData.setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
+                AMediaFormat_setInt64(mFileMetaData,
+                        AMEDIAFORMAT_KEY_DURATION, duration * 1000000 / mHeaderTimescale);
             }
 
             break;
@@ -2352,7 +2398,8 @@
             // 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);
+                    AMediaFormat_setString(mLastTrack->meta,
+                            AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_TEXT_3GPP);
                 }
             }
 
@@ -2396,11 +2443,10 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
-            uint32_t type;
-            const void *data;
+            void *data;
             size_t size = 0;
-            if (!mLastTrack->meta.findData(
-                    kKeyTextFormatData, &type, &data, &size)) {
+            if (!AMediaFormat_getBuffer(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA, &data, &size)) {
                 size = 0;
             }
 
@@ -2427,8 +2473,8 @@
                 return ERROR_IO;
             }
 
-            mLastTrack->meta.setData(
-                    kKeyTextFormatData, 0, buffer, size + chunk_size);
+            AMediaFormat_setBuffer(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA, buffer, size + chunk_size);
 
             delete[] buffer;
 
@@ -2460,8 +2506,8 @@
                 return ERROR_MALFORMED;
             }
 
-            mFileMetaData.setData(
-                kKeyAlbumArt, MetaData::TYPE_NONE,
+            AMediaFormat_setBuffer(mFileMetaData,
+                AMEDIAFORMAT_KEY_ALBUMART,
                 buffer.get() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
 
             break;
@@ -2696,9 +2742,9 @@
         return ERROR_MALFORMED;
     }
 
-    mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC4);
-    mLastTrack->meta.setInt32(kKeyChannelCount, channelCount);
-    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
+    AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AC4);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channelCount);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
     return OK;
 }
 
@@ -2857,9 +2903,9 @@
             }
         }
     }
-    mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_EAC3);
-    mLastTrack->meta.setInt32(kKeyChannelCount, channelCount);
-    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
+    AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_EAC3);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channelCount);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
 
     delete[] chunk;
     return OK;
@@ -2929,9 +2975,9 @@
     unsigned lfeon = br.getBits(1);
     unsigned channelCount = channelCountTable[acmod] + lfeon;
 
-    mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
-    mLastTrack->meta.setInt32(kKeyChannelCount, channelCount);
-    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
+    AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AC3);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channelCount);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
     return OK;
 }
 
@@ -3051,8 +3097,9 @@
         return ERROR_MALFORMED;
 
     int64_t metaDuration;
-    if (!mLastTrack->meta.findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
-        mLastTrack->meta.setInt64(kKeyDuration, sidxDuration);
+    if (!AMediaFormat_getInt64(mLastTrack->meta,
+                AMEDIAFORMAT_KEY_DURATION, &metaDuration) || metaDuration == 0) {
+        AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, sidxDuration);
     }
     return OK;
 }
@@ -3150,7 +3197,7 @@
             return ERROR_MALFORMED;
         }
         if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
-            mFileMetaData.setFloat(kKeyCaptureFramerate, *(float *)&val);
+            AMediaFormat_setFloat(mFileMetaData, AMEDIAFORMAT_KEY_CAPTURE_RATE, *(float *)&val);
         }
     } else if (dataType == 67 && dataSize >= 4) {
         // BE signed int32
@@ -3159,7 +3206,8 @@
             return ERROR_MALFORMED;
         }
         if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.video.temporal_layers_count")) {
-            mFileMetaData.setInt32(kKeyTemporalLayerCount, val);
+            AMediaFormat_setInt32(mFileMetaData,
+                    AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT, val);
         }
     } else {
         // add more keys if needed
@@ -3213,7 +3261,7 @@
     if (mLastTrack == NULL)
         return ERROR_MALFORMED;
 
-    mLastTrack->meta.setInt32(kKeyTrackID, id);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id);
 
     size_t matrixOffset = dynSize + 16;
     int32_t a00 = U32_AT(&buffer[matrixOffset]);
@@ -3249,15 +3297,15 @@
     }
 
     if (rotationDegrees != 0) {
-        mLastTrack->meta.setInt32(kKeyRotation, rotationDegrees);
+        AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_ROTATION, rotationDegrees);
     }
 
     // Handle presentation display size, which could be different
-    // from the image size indicated by kKeyWidth and kKeyHeight.
+    // from the image size indicated by AMEDIAFORMAT_KEY_WIDTH and AMEDIAFORMAT_KEY_HEIGHT.
     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);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, width >> 16);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, height >> 16);
 
     return OK;
 }
@@ -3285,54 +3333,50 @@
 
     uint32_t flags = U32_AT(buffer);
 
-    uint32_t metadataKey = 0;
+    const char *metadataKey = nullptr;
     char chunk[5];
     MakeFourCCString(mPath[4], chunk);
     ALOGV("meta: %s @ %lld", chunk, (long long)offset);
     switch ((int32_t)mPath[4]) {
         case FOURCC(0xa9, 'a', 'l', 'b'):
         {
-            metadataKey = kKeyAlbum;
+            metadataKey = "album";
             break;
         }
         case FOURCC(0xa9, 'A', 'R', 'T'):
         {
-            metadataKey = kKeyArtist;
+            metadataKey = "artist";
             break;
         }
         case FOURCC('a', 'A', 'R', 'T'):
         {
-            metadataKey = kKeyAlbumArtist;
+            metadataKey = "albumartist";
             break;
         }
         case FOURCC(0xa9, 'd', 'a', 'y'):
         {
-            metadataKey = kKeyYear;
+            metadataKey = "year";
             break;
         }
         case FOURCC(0xa9, 'n', 'a', 'm'):
         {
-            metadataKey = kKeyTitle;
+            metadataKey = "title";
             break;
         }
         case FOURCC(0xa9, 'w', 'r', 't'):
         {
-            metadataKey = kKeyWriter;
+            metadataKey = "writer";
             break;
         }
         case FOURCC('c', 'o', 'v', 'r'):
         {
-            metadataKey = kKeyAlbumArt;
+            metadataKey = "albumart";
             break;
         }
         case FOURCC('g', 'n', 'r', 'e'):
-        {
-            metadataKey = kKeyGenre;
-            break;
-        }
         case FOURCC(0xa9, 'g', 'e', 'n'):
         {
-            metadataKey = kKeyGenre;
+            metadataKey = "genre";
             break;
         }
         case FOURCC('c', 'p', 'i', 'l'):
@@ -3342,7 +3386,7 @@
                 sprintf(tmp, "%d",
                         (int)buffer[size - 1]);
 
-                mFileMetaData.setCString(kKeyCompilation, tmp);
+                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_COMPILATION, tmp);
             }
             break;
         }
@@ -3354,7 +3398,7 @@
                 uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
                 sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
 
-                mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
+                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_CDTRACKNUMBER, tmp);
             }
             break;
         }
@@ -3366,7 +3410,7 @@
                 uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
                 sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
 
-                mFileMetaData.setCString(kKeyDiscNumber, tmp);
+                AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DISCNUMBER, tmp);
             }
             break;
         }
@@ -3410,8 +3454,10 @@
                             return ERROR_MALFORMED;
                         }
 
-                        mLastTrack->meta.setInt32(kKeyEncoderDelay, delay);
-                        mLastTrack->meta.setInt32(kKeyEncoderPadding, padding);
+                        AMediaFormat_setInt32(mLastTrack->meta,
+                                AMEDIAFORMAT_KEY_ENCODER_DELAY, delay);
+                        AMediaFormat_setInt32(mLastTrack->meta,
+                                AMEDIAFORMAT_KEY_ENCODER_PADDING, padding);
                     }
                 }
 
@@ -3426,12 +3472,14 @@
             break;
     }
 
-    if (size >= 8 && metadataKey && !mFileMetaData.hasData(metadataKey)) {
-        if (metadataKey == kKeyAlbumArt) {
-            mFileMetaData.setData(
-                    kKeyAlbumArt, MetaData::TYPE_NONE,
+    void *tmpData;
+    size_t tmpDataSize;
+    if (size >= 8 && metadataKey &&
+            !AMediaFormat_getBuffer(mFileMetaData, metadataKey, &tmpData, &tmpDataSize)) {
+        if (!strcmp(metadataKey, "albumart")) {
+            AMediaFormat_setBuffer(mFileMetaData, metadataKey,
                     buffer + 8, size - 8);
-        } else if (metadataKey == kKeyGenre) {
+        } else if (!strcmp(metadataKey, "genre")) {
             if (flags == 0) {
                 // uint8_t genre code, iTunes genre codes are
                 // the standard id3 codes, except they start
@@ -3445,18 +3493,18 @@
                 char genre[10];
                 sprintf(genre, "%d", genrecode);
 
-                mFileMetaData.setCString(metadataKey, genre);
+                AMediaFormat_setString(mFileMetaData, metadataKey, genre);
             } else if (flags == 1) {
                 // custom genre string
                 buffer[size] = '\0';
 
-                mFileMetaData.setCString(
+                AMediaFormat_setString(mFileMetaData, 
                         metadataKey, (const char *)buffer + 8);
             }
         } else {
             buffer[size] = '\0';
 
-            mFileMetaData.setCString(
+            AMediaFormat_setString(mFileMetaData, 
                     metadataKey, (const char *)buffer + 8);
         }
     }
@@ -3486,21 +3534,31 @@
     int32_t type = U32_AT(&buffer[0]);
     if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
             || (type == FOURCC('n', 'c', 'l', 'c') && size >= 10)) {
-        int32_t primaries = U16_AT(&buffer[4]);
-        int32_t transfer = U16_AT(&buffer[6]);
-        int32_t coeffs = U16_AT(&buffer[8]);
-        bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
-
-        ColorAspects aspects;
-        ColorUtils::convertIsoColorAspectsToCodecAspects(
-                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);
+        int32_t existingColor;
+        if (!AMediaFormat_getInt32(mLastTrack->meta,
+                AMEDIAFORMAT_KEY_COLOR_RANGE, &existingColor)) {
+            int32_t primaries = U16_AT(&buffer[4]);
+            int32_t isotransfer = U16_AT(&buffer[6]);
+            int32_t coeffs = U16_AT(&buffer[8]);
+            bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
+
+            int32_t range = 0;
+            int32_t standard = 0;
+            int32_t transfer = 0;
+            ColorUtils::convertIsoColorAspectsToPlatformAspects(
+                    primaries, isotransfer, coeffs, fullRange,
+                    &range, &standard, &transfer);
+
+            if (range != 0) {
+                AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_COLOR_RANGE, range);
+            }
+            if (standard != 0) {
+                AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_COLOR_STANDARD, standard);
+            }
+            if (transfer != 0) {
+                AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_COLOR_TRANSFER, transfer);
+            }
         }
     }
 
@@ -3527,26 +3585,26 @@
         return ERROR_IO;
     }
 
-    uint32_t metadataKey = 0;
+    const char *metadataKey = nullptr;
     switch (mPath[depth]) {
         case FOURCC('t', 'i', 't', 'l'):
         {
-            metadataKey = kKeyTitle;
+            metadataKey = "title";
             break;
         }
         case FOURCC('p', 'e', 'r', 'f'):
         {
-            metadataKey = kKeyArtist;
+            metadataKey = "artist";
             break;
         }
         case FOURCC('a', 'u', 't', 'h'):
         {
-            metadataKey = kKeyWriter;
+            metadataKey = "writer";
             break;
         }
         case FOURCC('g', 'n', 'r', 'e'):
         {
-            metadataKey = kKeyGenre;
+            metadataKey = "genre";
             break;
         }
         case FOURCC('a', 'l', 'b', 'm'):
@@ -3555,10 +3613,10 @@
               char tmp[4];
               sprintf(tmp, "%u", buffer[size - 1]);
 
-              mFileMetaData.setCString(kKeyCDTrackNumber, tmp);
+              AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_CDTRACKNUMBER, tmp);
             }
 
-            metadataKey = kKeyAlbum;
+            metadataKey = "album";
             break;
         }
         case FOURCC('y', 'r', 'r', 'c'):
@@ -3576,7 +3634,7 @@
             if (year < 10000) {
                 sprintf(tmp, "%u", year);
 
-                mFileMetaData.setCString(kKeyYear, tmp);
+                AMediaFormat_setString(mFileMetaData, "year", tmp);
             }
             break;
         }
@@ -3585,7 +3643,7 @@
             break;
     }
 
-    if (metadataKey > 0) {
+    if (metadataKey) {
         bool isUTF8 = true; // Common case
         char16_t *framedata = NULL;
         int len16 = 0; // Number of UTF-16 characters
@@ -3621,11 +3679,11 @@
 
         if (isUTF8) {
             buffer[size] = 0;
-            mFileMetaData.setCString(metadataKey, (const char *)buffer + 6);
+            AMediaFormat_setString(mFileMetaData, metadataKey, (const char *)buffer + 6);
         } else {
             // Convert from UTF-16 string to UTF-8 string.
             String8 tmpUTF8str(framedata, len16);
-            mFileMetaData.setCString(metadataKey, tmpUTF8str.string());
+            AMediaFormat_setString(mFileMetaData, metadataKey, tmpUTF8str.string());
         }
     }
 
@@ -3640,27 +3698,29 @@
 
     if (id3.isValid()) {
         struct Map {
-            int key;
+            const char *key;
             const char *tag1;
             const char *tag2;
         };
         static const Map kMap[] = {
-            { kKeyAlbum, "TALB", "TAL" },
-            { kKeyArtist, "TPE1", "TP1" },
-            { kKeyAlbumArtist, "TPE2", "TP2" },
-            { kKeyComposer, "TCOM", "TCM" },
-            { kKeyGenre, "TCON", "TCO" },
-            { kKeyTitle, "TIT2", "TT2" },
-            { kKeyYear, "TYE", "TYER" },
-            { kKeyAuthor, "TXT", "TEXT" },
-            { kKeyCDTrackNumber, "TRK", "TRCK" },
-            { kKeyDiscNumber, "TPA", "TPOS" },
-            { kKeyCompilation, "TCP", "TCMP" },
+            { AMEDIAFORMAT_KEY_ALBUM, "TALB", "TAL" },
+            { AMEDIAFORMAT_KEY_ARTIST, "TPE1", "TP1" },
+            { AMEDIAFORMAT_KEY_ALBUMARTIST, "TPE2", "TP2" },
+            { AMEDIAFORMAT_KEY_COMPOSER, "TCOM", "TCM" },
+            { AMEDIAFORMAT_KEY_GENRE, "TCON", "TCO" },
+            { AMEDIAFORMAT_KEY_TITLE, "TIT2", "TT2" },
+            { AMEDIAFORMAT_KEY_YEAR, "TYE", "TYER" },
+            { AMEDIAFORMAT_KEY_AUTHOR, "TXT", "TEXT" },
+            { AMEDIAFORMAT_KEY_CDTRACKNUMBER, "TRK", "TRCK" },
+            { AMEDIAFORMAT_KEY_DISCNUMBER, "TPA", "TPOS" },
+            { AMEDIAFORMAT_KEY_COMPILATION, "TCP", "TCMP" },
         };
         static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
 
+        void *tmpData;
+        size_t tmpDataSize;
         for (size_t i = 0; i < kNumMapEntries; ++i) {
-            if (!mFileMetaData.hasData(kMap[i].key)) {
+            if (!AMediaFormat_getBuffer(mFileMetaData, kMap[i].key, &tmpData, &tmpDataSize)) {
                 ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
                 if (it->done()) {
                     delete it;
@@ -3676,7 +3736,7 @@
                 it->getString(&s);
                 delete it;
 
-                mFileMetaData.setCString(kMap[i].key, s);
+                AMediaFormat_setString(mFileMetaData, kMap[i].key, s);
             }
         }
 
@@ -3685,12 +3745,12 @@
         const void *data = id3.getAlbumArt(&dataSize, &mime);
 
         if (data) {
-            mFileMetaData.setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+            AMediaFormat_setBuffer(mFileMetaData, AMEDIAFORMAT_KEY_ALBUMART, data, dataSize);
         }
     }
 }
 
-MediaTrackHelper *MPEG4Extractor::getTrack(size_t index) {
+MediaTrackHelperV2 *MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
@@ -3713,7 +3773,7 @@
 
     Trex *trex = NULL;
     int32_t trackId;
-    if (track->meta.findInt32(kKeyTrackID, &trackId)) {
+    if (AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_TRACK_ID, &trackId)) {
         for (size_t i = 0; i < mTrex.size(); i++) {
             Trex *t = &mTrex.editItemAt(i);
             if (t->track_ID == (uint32_t) trackId) {
@@ -3729,16 +3789,15 @@
     ALOGV("getTrack called, pssh: %zu", mPssh.size());
 
     const char *mime;
-    if (!track->meta.findCString(kKeyMIMEType, &mime)) {
+    if (!AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime)) {
         return NULL;
     }
 
     sp<ItemTable> itemTable;
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
-        uint32_t type;
-        const void *data;
+        void *data;
         size_t size;
-        if (!track->meta.findData(kKeyAVCC, &type, &data, &size)) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_AVC, &data, &size)) {
             return NULL;
         }
 
@@ -3749,10 +3808,9 @@
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)
             || !strcasecmp(mime, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)) {
-        uint32_t type;
-        const void *data;
+        void *data;
         size_t size;
-        if (!track->meta.findData(kKeyHVCC, &type, &data, &size)) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size)) {
             return NULL;
         }
 
@@ -3779,26 +3837,22 @@
 // static
 status_t MPEG4Extractor::verifyTrack(Track *track) {
     const char *mime;
-    CHECK(track->meta.findCString(kKeyMIMEType, &mime));
+    CHECK(AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime));
 
-    uint32_t type;
-    const void *data;
+    void *data;
     size_t size;
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
-        if (!track->meta.findData(kKeyAVCC, &type, &data, &size)
-                || type != kTypeAVCC) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_AVC, &data, &size)) {
             return ERROR_MALFORMED;
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
-        if (!track->meta.findData(kKeyHVCC, &type, &data, &size)
-                    || type != kTypeHVCC) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size)) {
             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)
-                || type != kTypeESDS) {
+        if (!AMediaFormat_getBuffer(track->meta, AMEDIAFORMAT_KEY_ESDS, &data, &size)) {
             return ERROR_MALFORMED;
         }
     }
@@ -3883,7 +3937,7 @@
         if (mLastTrack == NULL)
             return ERROR_MALFORMED;
 
-        mLastTrack->meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
+        AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_QCELP);
         return OK;
     }
 
@@ -3900,10 +3954,12 @@
         uint32_t avgBitrate = 0;
         esds.getBitRate(&maxBitrate, &avgBitrate);
         if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
-            mLastTrack->meta.setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+            AMediaFormat_setInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_MAX_BIT_RATE, (int32_t)maxBitrate);
         }
         if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
-            mLastTrack->meta.setInt32(kKeyBitRate, (int32_t)avgBitrate);
+            AMediaFormat_setInt32(mLastTrack->meta,
+                    AMEDIAFORMAT_KEY_BIT_RATE, (int32_t)avgBitrate);
         }
     }
 
@@ -3947,7 +4003,7 @@
         return ERROR_MALFORMED;
 
     //keep AOT type
-    mLastTrack->meta.setInt32(kKeyAACAOT, objectType);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_AAC_PROFILE, objectType);
 
     uint32_t freqIndex = br.getBits(4);
 
@@ -3968,7 +4024,7 @@
         sampleRate = kSamplingRate[freqIndex];
     }
 
-    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
+    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 tbl 1.13
         if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
         uint32_t extFreqIndex = br.getBits(4);
         int32_t extSampleRate __unused;
@@ -3985,7 +4041,7 @@
             extSampleRate = kSamplingRate[extFreqIndex];
         }
         //TODO: save the extension sampling rate value in meta data =>
-        //      mLastTrack->meta.setInt32(kKeyExtSampleRate, extSampleRate);
+        //      AMediaFormat_setInt32(mLastTrack->meta, kKeyExtSampleRate, extSampleRate);
     }
 
     switch (numChannels) {
@@ -4138,24 +4194,25 @@
         return ERROR_MALFORMED;
 
     int32_t prevSampleRate;
-    CHECK(mLastTrack->meta.findInt32(kKeySampleRate, &prevSampleRate));
+    CHECK(AMediaFormat_getInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &prevSampleRate));
 
     if (prevSampleRate != sampleRate) {
         ALOGV("mpeg4 audio sample rate different from previous setting. "
              "was: %d, now: %d", prevSampleRate, sampleRate);
     }
 
-    mLastTrack->meta.setInt32(kKeySampleRate, sampleRate);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
 
     int32_t prevChannelCount;
-    CHECK(mLastTrack->meta.findInt32(kKeyChannelCount, &prevChannelCount));
+    CHECK(AMediaFormat_getInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_CHANNEL_COUNT, &prevChannelCount));
 
     if (prevChannelCount != numChannels) {
         ALOGV("mpeg4 audio channel count different from previous setting. "
              "was: %d, now: %d", prevChannelCount, numChannels);
     }
 
-    mLastTrack->meta.setInt32(kKeyChannelCount, numChannels);
+    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels);
 
     return OK;
 }
@@ -4163,7 +4220,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Source::MPEG4Source(
-        MetaDataBase &format,
+        AMediaFormat *format,
         DataSourceHelper *dataSource,
         int32_t timeScale,
         const sp<SampleTable> &sampleTable,
@@ -4203,23 +4260,27 @@
 
     memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
 
-    mFormat.findInt32(kKeyCryptoMode, &mCryptoMode);
+    AMediaFormat_getInt32(mFormat,
+            AMEDIAFORMAT_KEY_CRYPTO_MODE, &mCryptoMode);
     mDefaultIVSize = 0;
-    mFormat.findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
-    uint32_t keytype;
-    const void *key;
+    AMediaFormat_getInt32(mFormat,
+            AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &mDefaultIVSize);
+    void *key;
     size_t keysize;
-    if (mFormat.findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
+    if (AMediaFormat_getBuffer(mFormat,
+            AMEDIAFORMAT_KEY_CRYPTO_KEY, &key, &keysize)) {
         CHECK(keysize <= 16);
         memset(mCryptoKey, 0, 16);
         memcpy(mCryptoKey, key, keysize);
     }
 
-    mFormat.findInt32(kKeyEncryptedByteBlock, &mDefaultEncryptedByteBlock);
-    mFormat.findInt32(kKeySkipByteBlock, &mDefaultSkipByteBlock);
+    AMediaFormat_getInt32(mFormat,
+            AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK, &mDefaultEncryptedByteBlock);
+    AMediaFormat_getInt32(mFormat,
+            AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK, &mDefaultSkipByteBlock);
 
     const char *mime;
-    bool success = mFormat.findCString(kKeyMIMEType, &mime);
+    bool success = AMediaFormat_getString(mFormat, AMEDIAFORMAT_KEY_MIME, &mime);
     CHECK(success);
 
     mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -4228,10 +4289,9 @@
     mIsAC4 = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC4);
 
     if (mIsAVC) {
-        uint32_t type;
-        const void *data;
+        void *data;
         size_t size;
-        CHECK(format.findData(kKeyAVCC, &type, &data, &size));
+        CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_AVC, &data, &size));
 
         const uint8_t *ptr = (const uint8_t *)data;
 
@@ -4241,10 +4301,9 @@
         // The number of bytes used to encode the length of a NAL unit.
         mNALLengthSize = 1 + (ptr[4] & 3);
     } else if (mIsHEVC) {
-        uint32_t type;
-        const void *data;
+        void *data;
         size_t size;
-        CHECK(format.findData(kKeyHVCC, &type, &data, &size));
+        CHECK(AMediaFormat_getBuffer(format, AMEDIAFORMAT_KEY_CSD_HEVC, &data, &size));
 
         const uint8_t *ptr = (const uint8_t *)data;
 
@@ -4259,23 +4318,25 @@
     if (mIsPcm) {
         int32_t numChannels = 0;
         int32_t bitsPerSample = 0;
-        CHECK(mFormat.findInt32(kKeyBitsPerSample, &bitsPerSample));
-        CHECK(mFormat.findInt32(kKeyChannelCount, &numChannels));
+        CHECK(AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &bitsPerSample));
+        CHECK(AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels));
 
         int32_t bytesPerSample = bitsPerSample >> 3;
         int32_t pcmSampleSize = bytesPerSample * numChannels;
 
         size_t maxSampleSize;
         status_t err = mSampleTable->getMaxSampleSize(&maxSampleSize);
-        if (err != OK || maxSampleSize != static_cast<size_t>(pcmSampleSize) || bitsPerSample != 16) {
+        if (err != OK || maxSampleSize != static_cast<size_t>(pcmSampleSize)
+               || bitsPerSample != 16) {
             // Not supported
             mIsPcm = false;
         } else {
-            mFormat.setInt32(kKeyMaxInputSize, pcmSampleSize * kMaxPcmFrameSize);
+            AMediaFormat_setInt32(mFormat,
+                    AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, pcmSampleSize * kMaxPcmFrameSize);
         }
     }
 
-    CHECK(format.findInt32(kKeyTrackID, &mTrackId));
+    CHECK(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_TRACK_ID, &mTrackId));
 
 }
 
@@ -4295,13 +4356,13 @@
     free(mCurrentSampleInfoOffsets);
 }
 
-status_t MPEG4Source::start() {
+media_status_t MPEG4Source::start() {
     Mutex::Autolock autoLock(mLock);
 
     CHECK(!mStarted);
 
     int32_t tmp;
-    CHECK(mFormat.findInt32(kKeyMaxInputSize, &tmp));
+    CHECK(AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, &tmp));
     size_t max_size = tmp;
 
     // A somewhat arbitrary limit that should be sufficient for 8k video frames
@@ -4309,11 +4370,11 @@
     const size_t kMaxBufferSize = 64 * 1024 * 1024;
     if (max_size > kMaxBufferSize) {
         ALOGE("bogus max input size: %zu > %zu", max_size, kMaxBufferSize);
-        return ERROR_MALFORMED;
+        return AMEDIA_ERROR_MALFORMED;
     }
     if (max_size == 0) {
         ALOGE("zero max input size");
-        return ERROR_MALFORMED;
+        return AMEDIA_ERROR_MALFORMED;
     }
 
     // Allow up to kMaxBuffers, but not if the total exceeds kMaxBufferSize.
@@ -4326,15 +4387,15 @@
         // file probably specified a bad max size
         delete mGroup;
         mGroup = NULL;
-        return ERROR_MALFORMED;
+        return AMEDIA_ERROR_MALFORMED;
     }
 
     mStarted = true;
 
-    return OK;
+    return AMEDIA_OK;
 }
 
-status_t MPEG4Source::stop() {
+media_status_t MPEG4Source::stop() {
     Mutex::Autolock autoLock(mLock);
 
     CHECK(mStarted);
@@ -4353,7 +4414,7 @@
     mStarted = false;
     mCurrentSampleIndex = 0;
 
-    return OK;
+    return AMEDIA_OK;
 }
 
 status_t MPEG4Source::parseChunk(off64_t *offset) {
@@ -4471,7 +4532,8 @@
         }
         case FOURCC('s', 'a', 'i', 'o'): {
             status_t err;
-            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
+            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size))
+                    != OK) {
                 return err;
             }
             *offset += chunk_size;
@@ -4602,7 +4664,8 @@
     if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
         uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
         if (newPtr == NULL) {
-            ALOGE("failed to realloc %u -> %u", mCurrentSampleInfoOffsetsAllocSize, entrycount * 8);
+            ALOGE("failed to realloc %u -> %u",
+                    mCurrentSampleInfoOffsetsAllocSize, entrycount * 8);
             return NO_MEMORY;
         }
         mCurrentSampleInfoOffsets = newPtr;
@@ -4641,10 +4704,11 @@
     return parseClearEncryptedSizes(drmoffset, false, 0);
 }
 
-status_t MPEG4Source::parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
+status_t MPEG4Source::parseClearEncryptedSizes(
+        off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
 
-    int ivlength;
-    CHECK(mFormat.findInt32(kKeyCryptoDefaultIVSize, &ivlength));
+    int32_t ivlength;
+    CHECK(AMediaFormat_getInt32(mFormat, "crypto-defaultivsize", &ivlength));
 
     // only 0, 8 and 16 byte initialization vectors are supported
     if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
@@ -4988,10 +5052,10 @@
     return OK;
 }
 
-status_t MPEG4Source::getFormat(MetaDataBase &meta) {
+media_status_t MPEG4Source::getFormat(AMediaFormat *meta) {
     Mutex::Autolock autoLock(mLock);
-    meta = mFormat;
-    return OK;
+    AMediaFormat_copy(meta, mFormat);
+    return AMEDIA_OK;
 }
 
 size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
@@ -5042,7 +5106,7 @@
     return 0;
 }
 
-status_t MPEG4Source::read(
+media_status_t MPEG4Source::read(
         MediaBufferBase **out, const ReadOptions *options) {
     Mutex::Autolock autoLock(mLock);
 
@@ -5050,7 +5114,7 @@
 
     if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) {
         *out = nullptr;
-        return WOULD_BLOCK;
+        return AMEDIA_ERROR_WOULD_BLOCK;
     }
 
     if (mFirstMoofOffset > 0) {
@@ -5068,8 +5132,8 @@
             CHECK(mSampleTable == NULL);
             CHECK(mItemTable != NULL);
             int32_t imageIndex;
-            if (!mFormat.findInt32(kKeyTrackID, &imageIndex)) {
-                return ERROR_MALFORMED;
+            if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_TRACK_ID, &imageIndex)) {
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             status_t err;
@@ -5079,7 +5143,7 @@
                 err = mItemTable->findThumbnailItem(imageIndex, &mCurrentSampleIndex);
             }
             if (err != OK) {
-                return err;
+                return AMEDIA_ERROR_UNKNOWN;
             }
         } else {
             uint32_t findFlags = 0;
@@ -5134,10 +5198,10 @@
                     // this all the way to the MediaPlayer would cause abnormal
                     // termination. Legacy behaviour appears to be to behave as if
                     // we had seeked to the end of stream, ending normally.
-                    err = ERROR_END_OF_STREAM;
+                    return AMEDIA_ERROR_END_OF_STREAM;
                 }
                 ALOGV("end of stream");
-                return err;
+                return AMEDIA_ERROR_UNKNOWN;
             }
 
             if (mode == ReadOptions::SEEK_CLOSEST
@@ -5191,20 +5255,23 @@
         }
 
         if (err != OK) {
-            return err;
+            if (err == ERROR_END_OF_STREAM) {
+                return AMEDIA_ERROR_END_OF_STREAM;
+            }
+            return AMEDIA_ERROR_UNKNOWN;
         }
 
         err = mGroup->acquire_buffer(&mBuffer);
 
         if (err != OK) {
             CHECK(mBuffer == NULL);
-            return err;
+            return AMEDIA_ERROR_UNKNOWN;
         }
         if (size > mBuffer->size()) {
             ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
             mBuffer->release();
             mBuffer = NULL;
-            return ERROR_BUFFER_TOO_SMALL;
+            return AMEDIA_ERROR_UNKNOWN; // ERROR_BUFFER_TOO_SMALL
         }
     }
 
@@ -5230,7 +5297,7 @@
                     mBuffer->release();
                     mBuffer = NULL;
 
-                    return ERROR_IO;
+                    return AMEDIA_ERROR_IO;
                 }
 
                 mBuffer->meta_data().clear();
@@ -5238,7 +5305,8 @@
                 mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
 
                 int32_t byteOrder;
-                mFormat.findInt32(kKeyPcmBigEndian, &byteOrder);
+                AMediaFormat_getInt32(mFormat,
+                        AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &byteOrder);
 
                 if (byteOrder == 1) {
                     // Big-endian -> little-endian
@@ -5260,7 +5328,7 @@
                     mBuffer->release();
                     mBuffer = NULL;
 
-                    return ERROR_IO;
+                    return AMEDIA_ERROR_IO;
                 }
 
                 CHECK(mBuffer != NULL);
@@ -5288,14 +5356,14 @@
             *out = mBuffer;
             mBuffer = NULL;
 
-            return OK;
+            return AMEDIA_OK;
         }
 
         if (mIsAC4) {
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_IO;
+            return AMEDIA_ERROR_IO;
         }
 
         // Each NAL unit is split up into its constituent fragments and
@@ -5316,7 +5384,7 @@
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_MALFORMED;
+            return AMEDIA_ERROR_MALFORMED;
         }
 
         MediaBufferBase *clone = mBuffer->clone();
@@ -5335,7 +5403,7 @@
 
         *out = clone;
 
-        return OK;
+        return AMEDIA_OK;
     } else if (mIsAC4) {
         CHECK(mBuffer != NULL);
         // Make sure there is enough space to write the sync header and the raw frame
@@ -5343,7 +5411,7 @@
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_IO;
+            return AMEDIA_ERROR_IO;
         }
 
         uint8_t *dstData = (uint8_t *)mBuffer->data();
@@ -5363,7 +5431,7 @@
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_IO;
+            return AMEDIA_ERROR_IO;
         }
 
         mBuffer->set_range(0, dstOffset + size);
@@ -5387,7 +5455,7 @@
         *out = mBuffer;
         mBuffer = NULL;
 
-        return OK;
+        return AMEDIA_OK;
     } else {
         // Whole NAL units are returned but each fragment is prefixed by
         // the start code (0x00 00 00 01).
@@ -5398,7 +5466,7 @@
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_IO;
+            return AMEDIA_ERROR_IO;
         }
 
         uint8_t *dstData = (uint8_t *)mBuffer->data();
@@ -5418,7 +5486,7 @@
                 ALOGE("Video is malformed");
                 mBuffer->release();
                 mBuffer = NULL;
-                return ERROR_MALFORMED;
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             if (nalLength == 0) {
@@ -5432,7 +5500,7 @@
                 android_errorWriteLog(0x534e4554, "27208621");
                 mBuffer->release();
                 mBuffer = NULL;
-                return ERROR_MALFORMED;
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             dstData[dstOffset++] = 0;
@@ -5479,11 +5547,11 @@
         *out = mBuffer;
         mBuffer = NULL;
 
-        return OK;
+        return AMEDIA_OK;
     }
 }
 
-status_t MPEG4Source::fragmentedRead(
+media_status_t MPEG4Source::fragmentedRead(
         MediaBufferBase **out, const ReadOptions *options) {
 
     ALOGV("MPEG4Source::fragmentedRead");
@@ -5525,7 +5593,7 @@
             mCurrentSampleIndex = 0;
             status_t err = parseChunk(&totalOffset);
             if (err != OK) {
-                return err;
+                return AMEDIA_ERROR_UNKNOWN;
             }
             mCurrentTime = totalTime * mTimescale / 1000000ll;
         } else {
@@ -5537,7 +5605,7 @@
             off64_t tmp = mCurrentMoofOffset;
             status_t err = parseChunk(&tmp);
             if (err != OK) {
-                return err;
+                return AMEDIA_ERROR_UNKNOWN;
             }
             mCurrentTime = 0;
         }
@@ -5565,7 +5633,7 @@
         if (mCurrentSampleIndex >= mCurrentSamples.size()) {
             // move to next fragment if there is one
             if (mNextMoofOffset <= mCurrentMoofOffset) {
-                return ERROR_END_OF_STREAM;
+                return AMEDIA_ERROR_END_OF_STREAM;
             }
             off64_t nextMoof = mNextMoofOffset;
             mCurrentMoofOffset = nextMoof;
@@ -5573,10 +5641,10 @@
             mCurrentSampleIndex = 0;
             status_t err = parseChunk(&nextMoof);
             if (err != OK) {
-                return err;
+                return AMEDIA_ERROR_UNKNOWN;
             }
             if (mCurrentSampleIndex >= mCurrentSamples.size()) {
-                return ERROR_END_OF_STREAM;
+                return AMEDIA_ERROR_END_OF_STREAM;
             }
         }
 
@@ -5585,20 +5653,20 @@
         size = smpl->size;
         cts = mCurrentTime + smpl->compositionOffset;
         mCurrentTime += smpl->duration;
-        isSyncSample = (mCurrentSampleIndex == 0); // XXX
+        isSyncSample = (mCurrentSampleIndex == 0);
 
         status_t err = mGroup->acquire_buffer(&mBuffer);
 
         if (err != OK) {
             CHECK(mBuffer == NULL);
             ALOGV("acquire_buffer returned %d", err);
-            return err;
+            return AMEDIA_ERROR_UNKNOWN;
         }
         if (size > mBuffer->size()) {
             ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
             mBuffer->release();
             mBuffer = NULL;
-            return ERROR_BUFFER_TOO_SMALL;
+            return AMEDIA_ERROR_UNKNOWN;
         }
     }
 
@@ -5617,12 +5685,11 @@
         bufmeta.setInt32(kKeyEncryptedByteBlock, mDefaultEncryptedByteBlock);
         bufmeta.setInt32(kKeySkipByteBlock, mDefaultSkipByteBlock);
 
-        uint32_t type = 0;
-        const void *iv = NULL;
+        void *iv = NULL;
         size_t ivlength = 0;
-        if (!mFormat.findData(
-                kKeyCryptoIV, &type, &iv, &ivlength)) {
-            iv = smpl->iv;
+        if (!AMediaFormat_getBuffer(mFormat,
+                "crypto-iv", &iv, &ivlength)) {
+            iv = (void *) smpl->iv;
             ivlength = 16; // use 16 or the actual size?
         }
         bufmeta.setData(kKeyCryptoIV, 0, iv, ivlength);
@@ -5636,7 +5703,7 @@
                 mBuffer = NULL;
 
                 ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
-                return ERROR_MALFORMED;
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             ssize_t num_bytes_read =
@@ -5647,7 +5714,7 @@
                 mBuffer = NULL;
 
                 ALOGE("i/o error");
-                return ERROR_IO;
+                return AMEDIA_ERROR_IO;
             }
 
             CHECK(mBuffer != NULL);
@@ -5685,7 +5752,7 @@
             *out = mBuffer;
             mBuffer = NULL;
 
-            return OK;
+            return AMEDIA_OK;
         }
 
         // Each NAL unit is split up into its constituent fragments and
@@ -5707,7 +5774,7 @@
             mBuffer->release();
             mBuffer = NULL;
 
-            return ERROR_MALFORMED;
+            return AMEDIA_ERROR_MALFORMED;
         }
 
         MediaBufferBase *clone = mBuffer->clone();
@@ -5726,7 +5793,7 @@
 
         *out = clone;
 
-        return OK;
+        return AMEDIA_OK;
     } else {
         ALOGV("whole NAL");
         // Whole NAL units are returned but each fragment is prefixed by
@@ -5735,7 +5802,7 @@
         void *data = NULL;
         bool isMalFormed = false;
         int32_t max_size;
-        if (!mFormat.findInt32(kKeyMaxInputSize, &max_size)
+        if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, &max_size)
                 || !isInRange((size_t)0u, (size_t)max_size, size)) {
             isMalFormed = true;
         } else {
@@ -5748,7 +5815,7 @@
                 mBuffer->release();
                 mBuffer = NULL;
             }
-            return ERROR_MALFORMED;
+            return AMEDIA_ERROR_MALFORMED;
         }
         num_bytes_read = mDataSource->readAt(offset, data, size);
 
@@ -5757,7 +5824,7 @@
             mBuffer = NULL;
 
             ALOGE("i/o error");
-            return ERROR_IO;
+            return AMEDIA_ERROR_IO;
         }
 
         uint8_t *dstData = (uint8_t *)mBuffer->data();
@@ -5779,7 +5846,7 @@
                 ALOGE("Video is malformed; nalLength %zu", nalLength);
                 mBuffer->release();
                 mBuffer = NULL;
-                return ERROR_MALFORMED;
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             if (nalLength == 0) {
@@ -5793,7 +5860,7 @@
                 android_errorWriteLog(0x534e4554, "26365349");
                 mBuffer->release();
                 mBuffer = NULL;
-                return ERROR_MALFORMED;
+                return AMEDIA_ERROR_MALFORMED;
             }
 
             dstData[dstOffset++] = 0;
@@ -5827,17 +5894,17 @@
         *out = mBuffer;
         mBuffer = NULL;
 
-        return OK;
+        return AMEDIA_OK;
     }
 
-    return OK;
+    return AMEDIA_OK;
 }
 
 MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
         const char *mimePrefix) {
     for (Track *track = mFirstTrack; track != NULL; track = track->next) {
         const char *mime;
-        if (track->meta.findCString(kKeyMIMEType, &mime)
+        if (AMediaFormat_getString(track->meta, AMEDIAFORMAT_KEY_MIME, &mime)
                 && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
             return track;
         }
@@ -5957,7 +6024,8 @@
 
         char chunkstring[5];
         MakeFourCCString(chunkType, chunkstring);
-        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, (long long)offset);
+        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld",
+                chunkstring, chunkSize, (long long)offset);
         switch (chunkType) {
             case FOURCC('f', 't', 'y', 'p'):
             {
@@ -6018,11 +6086,11 @@
     return true;
 }
 
-static CMediaExtractor* CreateExtractor(CDataSource *source, void *) {
-    return wrap(new MPEG4Extractor(new DataSourceHelper(source)));
+static CMediaExtractorV2* CreateExtractor(CDataSource *source, void *) {
+    return wrapV2(new MPEG4Extractor(new DataSourceHelper(source)));
 }
 
-static CreatorFunc Sniff(
+static CreatorFuncV2 Sniff(
         CDataSource *source, float *confidence, void **,
         FreeMetaFunc *) {
     DataSourceHelper helper(source);
@@ -6043,11 +6111,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION_CURRENT,
         UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
-        1, // version
+        2, // version
         "MP4 Extractor",
-        { Sniff }
+        { .v2 = Sniff }
     };
 }
 
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 9b8de20..56b641d 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -22,7 +22,7 @@
 
 #include <media/MediaExtractorPluginApi.h>
 #include <media/MediaExtractorPluginHelper.h>
-#include <media/stagefright/MetaDataBase.h>
+#include <media/NdkMediaFormat.h>
 #include <media/stagefright/foundation/AString.h>
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
@@ -53,15 +53,15 @@
     uint32_t default_sample_flags;
 };
 
-class MPEG4Extractor : public MediaExtractorPluginHelper {
+class MPEG4Extractor : public MediaExtractorPluginHelperV2 {
 public:
     explicit MPEG4Extractor(DataSourceHelper *source, const char *mime = NULL);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelper *getTrack(size_t index);
-    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
-    virtual status_t getMetaData(MetaDataBase& meta);
+    virtual media_status_t getMetaData(AMediaFormat *meta);
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG4Extractor"; }
 
@@ -77,7 +77,7 @@
     };
     struct Track {
         Track *next;
-        MetaDataBase meta;
+        AMediaFormat *meta;
         uint32_t timescale;
         sp<SampleTable> sampleTable;
         bool includes_expensive_metadata;
@@ -107,7 +107,7 @@
 
     Track *mFirstTrack, *mLastTrack;
 
-    MetaDataBase mFileMetaData;
+    AMediaFormat *mFileMetaData;
 
     Vector<uint32_t> mPath;
     String8 mLastCommentMean;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 3956520..2ee5ab0 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -569,7 +569,7 @@
 }
 
 
-std::vector<std::pair<const char *, uint32_t>> tagMappings {
+static std::vector<std::pair<const char *, uint32_t>> stringMappings {
     {
         { "album", kKeyAlbum },
         { "albumartist", kKeyAlbumArtist },
@@ -581,47 +581,108 @@
         { "date", kKeyDate },
         { "discnum", kKeyDiscNumber },
         { "genre", kKeyGenre },
+        { "location", kKeyLocation },
         { "lyricist", kKeyWriter },
         { "title", kKeyTitle },
         { "year", kKeyYear },
     }
 };
 
-void convertMessageToMetaDataTags(const sp<AMessage> &msg, sp<MetaData> &meta) {
-    for (auto elem : tagMappings) {
+static std::vector<std::pair<const char *, uint32_t>> int64Mappings {
+    {
+        { "exif-offset", kKeyExifOffset },
+        { "exif-size", kKeyExifSize },
+    }
+};
+
+static std::vector<std::pair<const char *, uint32_t>> int32Mappings {
+    {
+        { "loop", kKeyAutoLoop },
+        { "time-scale", kKeyTimeScale },
+        { "crypto-mode", kKeyCryptoMode },
+        { "crypto-default-iv-size", kKeyCryptoDefaultIVSize },
+        { "crypto-encrypted-byte-block", kKeyEncryptedByteBlock },
+        { "crypto-skip-byte-block", kKeySkipByteBlock },
+        { "max-bitrate", kKeyMaxBitRate },
+        { "pcm-big-endian", kKeyPcmBigEndian },
+        { "temporal-layer-count", kKeyTemporalLayerCount },
+        { "thumbnail-width", kKeyThumbnailWidth },
+        { "thumbnail-height", kKeyThumbnailHeight },
+    }
+};
+
+static std::vector<std::pair<const char *, uint32_t>> bufferMappings {
+    {
+        { "albumart", kKeyAlbumArt },
+        { "pssh", kKeyPssh },
+        { "crypto-iv", kKeyCryptoIV },
+        { "crypto-key", kKeyCryptoKey },
+        { "icc-profile", kKeyIccProfile },
+        { "text-format-data", kKeyTextFormatData },
+    }
+};
+
+void convertMessageToMetaDataFromMappings(const sp<AMessage> &msg, sp<MetaData> &meta) {
+    for (auto elem : stringMappings) {
         AString value;
         if (msg->findString(elem.first, &value)) {
             meta->setCString(elem.second, value.c_str());
         }
     }
-    sp<ABuffer> buf;
-    if (msg->findBuffer("albumart", &buf)) {
-        meta->setData(kKeyAlbumArt, MetaDataBase::Type::TYPE_NONE, buf->data(), buf->size());
+
+    for (auto elem : int64Mappings) {
+        int64_t value;
+        if (msg->findInt64(elem.first, &value)) {
+            meta->setInt64(elem.second, value);
+        }
     }
 
-    int32_t loop;
-    if (msg->findInt32("loop", &loop)) {
-        meta->setInt32(kKeyAutoLoop, loop);
+    for (auto elem : int32Mappings) {
+        int32_t value;
+        if (msg->findInt32(elem.first, &value)) {
+            meta->setInt32(elem.second, value);
+        }
+    }
+
+    for (auto elem : bufferMappings) {
+        sp<ABuffer> value;
+        if (msg->findBuffer(elem.first, &value)) {
+            meta->setData(elem.second,
+                    MetaDataBase::Type::TYPE_NONE, value->data(), value->size());
+        }
     }
 }
 
-void convertMetaDataToMessageTags(const MetaDataBase *meta, sp<AMessage> format) {
-    for (auto elem : tagMappings) {
+void convertMetaDataToMessageFromMappings(const MetaDataBase *meta, sp<AMessage> format) {
+    for (auto elem : stringMappings) {
         const char *value;
         if (meta->findCString(elem.second, &value)) {
             format->setString(elem.first, value, strlen(value));
         }
     }
-    uint32_t type;
-    const void* data;
-    size_t size;
-    if (meta->findData(kKeyAlbumArt, &type, &data, &size)) {
-        sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size);
-        format->setBuffer("albumart", buf);
+
+    for (auto elem : int64Mappings) {
+        int64_t value;
+        if (meta->findInt64(elem.second, &value)) {
+            format->setInt64(elem.first, value);
+        }
     }
-    int32_t loop;
-    if (meta->findInt32(kKeyAutoLoop, &loop)) {
-        format->setInt32("loop", loop);
+
+    for (auto elem : int32Mappings) {
+        int32_t value;
+        if (meta->findInt32(elem.second, &value)) {
+            format->setInt32(elem.first, value);
+        }
+    }
+
+    for (auto elem : bufferMappings) {
+        uint32_t type;
+        const void* data;
+        size_t size;
+        if (meta->findData(elem.second, &type, &data, &size)) {
+            sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size);
+            format->setBuffer(elem.first, buf);
+        }
     }
 }
 
@@ -648,7 +709,7 @@
     sp<AMessage> msg = new AMessage;
     msg->setString("mime", mime);
 
-    convertMetaDataToMessageTags(meta, msg);
+    convertMetaDataToMessageFromMappings(meta, msg);
 
     uint32_t type;
     const void *data;
@@ -1117,7 +1178,7 @@
                 msg->setInt32("max-bitrate", (int32_t)maxBitrate);
             }
         }
-    } else if (meta->findData(kTypeD263, &type, &data, &size)) {
+    } else if (meta->findData(kKeyD263, &type, &data, &size)) {
         const uint8_t *ptr = (const uint8_t *)data;
         parseH263ProfileLevelFromD263(ptr, size, msg);
     } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
@@ -1217,13 +1278,6 @@
         msg->setBuffer("csd-0", buffer);
     }
 
-    // TODO expose "crypto-key"/kKeyCryptoKey through public api
-    if (meta->findData(kKeyCryptoKey, &type, &data, &size)) {
-        sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
-        msg->setBuffer("crypto-key", buffer);
-        memcpy(buffer->data(), data, size);
-    }
-
     *format = msg;
 
     return OK;
@@ -1422,7 +1476,7 @@
         ALOGW("did not find mime type");
     }
 
-    convertMessageToMetaDataTags(msg, meta);
+    convertMessageToMetaDataFromMappings(msg, meta);
 
     int64_t durationUs;
     if (msg->findInt64("durationUs", &durationUs)) {
@@ -1455,7 +1509,7 @@
             meta->setInt32(kKeyWidth, width);
             meta->setInt32(kKeyHeight, height);
         } else {
-            ALOGW("did not find width and/or height");
+            ALOGV("did not find width and/or height");
         }
 
         int32_t sarWidth, sarHeight;
@@ -1611,7 +1665,7 @@
             // The written ESDS is actually for an audio stream, but it's enough
             // for transporting the CSD to muxers.
             reassembleESDS(csd0, esds.data());
-            meta->setData(kKeyESDS, kKeyESDS, esds.data(), esds.size());
+            meta->setData(kKeyESDS, kTypeESDS, esds.data(), esds.size());
         } else if (mime == MEDIA_MIMETYPE_VIDEO_HEVC ||
                    mime == MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC) {
             std::vector<uint8_t> hvcc(csd0size + 1024);
@@ -1640,11 +1694,12 @@
     } else if ((mime == MEDIA_MIMETYPE_VIDEO_HEVC || mime == MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)
             && msg->findBuffer("csd-hevc", &csd0)) {
         meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
-    }
-
-    int32_t timeScale;
-    if (msg->findInt32("time-scale", &timeScale)) {
-        meta->setInt32(kKeyTimeScale, timeScale);
+    } else if (msg->findBuffer("esds", &csd0)) {
+        meta->setData(kKeyESDS, kTypeESDS, csd0->data(), csd0->size());
+    } else if (msg->findBuffer("mpeg2-stream-header", &csd0)) {
+        meta->setData(kKeyStreamHeader, 'mdat', csd0->data(), csd0->size());
+    } else if (msg->findBuffer("d263", &csd0)) {
+        meta->setData(kKeyD263, kTypeD263, csd0->data(), csd0->size());
     }
 
     // XXX TODO add whatever other keys there are
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 6537ad1..b282ed8 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -288,13 +288,19 @@
 EXPORT const char* AMEDIAFORMAT_KEY_COMPILATION = "compilation";
 EXPORT const char* AMEDIAFORMAT_KEY_COMPLEXITY = "complexity";
 EXPORT const char* AMEDIAFORMAT_KEY_COMPOSER = "composer";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE = "crypto-default-iv-size";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK = "crypto-encrypted-byte-block";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
 EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_AVC = "csd-avc";
 EXPORT const char* AMEDIAFORMAT_KEY_CSD_HEVC = "csd-hevc";
+EXPORT const char* AMEDIAFORMAT_KEY_D263 = "d263";
 EXPORT const char* AMEDIAFORMAT_KEY_DATE = "date";
 EXPORT const char* AMEDIAFORMAT_KEY_DISCNUMBER = "discnum";
 EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop";
@@ -303,13 +309,18 @@
 EXPORT const char* AMEDIAFORMAT_KEY_DURATION = "durationUs";
 EXPORT const char* AMEDIAFORMAT_KEY_ENCODER_DELAY = "encoder-delay";
 EXPORT const char* AMEDIAFORMAT_KEY_ENCODER_PADDING = "encoder-padding";
+EXPORT const char* AMEDIAFORMAT_KEY_ESDS = "esds";
+EXPORT const char* AMEDIAFORMAT_KEY_EXIF_OFFSET = "exif-offset";
+EXPORT const char* AMEDIAFORMAT_KEY_EXIF_SIZE = "exif-size";
 EXPORT const char* AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
+EXPORT const char* AMEDIAFORMAT_KEY_FRAME_COUNT = "frame-count";
 EXPORT const char* AMEDIAFORMAT_KEY_FRAME_RATE = "frame-rate";
 EXPORT const char* AMEDIAFORMAT_KEY_GENRE = "genre";
 EXPORT const char* AMEDIAFORMAT_KEY_GRID_COLUMNS = "grid-cols";
 EXPORT const char* AMEDIAFORMAT_KEY_GRID_ROWS = "grid-rows";
 EXPORT const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO = "hdr-static-info";
 EXPORT const char* AMEDIAFORMAT_KEY_HEIGHT = "height";
+EXPORT const char* AMEDIAFORMAT_KEY_ICC_PROFILE = "icc-profile";
 EXPORT const char* AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_ADTS = "is-adts";
 EXPORT const char* AMEDIAFORMAT_KEY_IS_AUTOSELECT = "is-autoselect";
@@ -319,17 +330,22 @@
 EXPORT const char* AMEDIAFORMAT_KEY_LANGUAGE = "language";
 EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency";
 EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level";
+EXPORT const char* AMEDIAFORMAT_KEY_LOCATION = "location";
 EXPORT const char* AMEDIAFORMAT_KEY_LOOP = "loop";
 EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist";
+EXPORT const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE = "max-bitrate";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
 EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";
 EXPORT const char* AMEDIAFORMAT_KEY_MIME = "mime";
 EXPORT const char* AMEDIAFORMAT_KEY_MPEG_USER_DATA = "mpeg-user-data";
+EXPORT const char* AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER = "mpeg2-stream-header";
 EXPORT const char* AMEDIAFORMAT_KEY_OPERATING_RATE = "operating-rate";
 EXPORT const char* AMEDIAFORMAT_KEY_PCM_ENCODING = "pcm-encoding";
 EXPORT const char* AMEDIAFORMAT_KEY_PRIORITY = "priority";
 EXPORT const char* AMEDIAFORMAT_KEY_PROFILE = "profile";
+EXPORT const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN = "pcm-big-endian";
+EXPORT const char* AMEDIAFORMAT_KEY_PSSH = "pssh";
 EXPORT const char* AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
 EXPORT const char* AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
 EXPORT const char* AMEDIAFORMAT_KEY_ROTATION = "rotation-degrees";
@@ -339,9 +355,13 @@
 EXPORT const char* AMEDIAFORMAT_KEY_SEI = "sei";
 EXPORT const char* AMEDIAFORMAT_KEY_SLICE_HEIGHT = "slice-height";
 EXPORT const char* AMEDIAFORMAT_KEY_STRIDE = "stride";
+EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT = "temporal-layer-count";
 EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
 EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
+EXPORT const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA = "text-format-data";
+EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT = "thumbnail-height";
 EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME = "thumbnail-time";
+EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH = "thumbnail-width";
 EXPORT const char* AMEDIAFORMAT_KEY_TILE_HEIGHT = "tile-height";
 EXPORT const char* AMEDIAFORMAT_KEY_TILE_WIDTH = "tile-width";
 EXPORT const char* AMEDIAFORMAT_KEY_TIME_US = "timeUs";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 3a3268c..89cfd5e 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -188,20 +188,40 @@
 extern const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_IV __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_KEY __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_MODE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CSD_AVC __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CSD_HEVC __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_D263 __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_DATE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_DISCNUMBER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_ENCODER_DELAY __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_ENCODER_PADDING __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ESDS __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_EXIF_OFFSET __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_EXIF_SIZE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_FRAME_COUNT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_ICC_PROFILE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_LOCATION __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LOOP __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_PSSH __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_SAR_HEIGHT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_SAR_WIDTH __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_TITLE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);