Initial Contribution
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
new file mode 100644
index 0000000..9cbafbc
--- /dev/null
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -0,0 +1,182 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <media/mediametadataretriever.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#define LOG_TAG "MediaMetadataRetriever"
+#endif
+
+#include <utils/Log.h>
+#include <dlfcn.h>
+
+namespace android {
+
+// Factory class function in shared libpvplayer.so
+typedef MediaMetadataRetrieverImpl* (*createRetriever_f)();
+
+MediaMetadataRetrieverImpl *MediaMetadataRetriever::mRetriever = NULL;
+void                       *MediaMetadataRetriever::mLibHandler = NULL;
+
+void MediaMetadataRetriever::create()
+{
+    // Load libpvplayer library once and only once.
+    if (!mLibHandler) {
+        mLibHandler = dlopen("libopencoreplayer.so", RTLD_NOW);
+        if (!mLibHandler) {
+            LOGE("setDataSource: dlopen failed on libopencoreplayer.so");
+            return;
+        }
+    }
+    
+    // Each time create a new MediaMetadataRetrieverImpl object.
+    if (mRetriever) {
+        delete mRetriever;
+    }
+    createRetriever_f createRetriever = reinterpret_cast<createRetriever_f>(dlsym(mLibHandler, "createRetriever"));
+    if (!createRetriever) {
+        LOGE("setDataSource: dlsym failed on createRetriever in libpvplayer.so");
+        return;
+    }
+    mRetriever = createRetriever();
+    if (!mRetriever) {
+        LOGE("setDataSource: createRetriever failed in libpvplayer.so");
+    }
+}
+
+status_t MediaMetadataRetriever::setDataSource(const char* srcUrl)
+{
+    if (srcUrl == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    
+    if (mRetriever) {
+        return mRetriever->setDataSource(srcUrl);
+    }
+    return UNKNOWN_ERROR;
+}
+
+const char* MediaMetadataRetriever::extractMetadata(int keyCode)
+{
+    if (mRetriever) {
+        return mRetriever->extractMetadata(keyCode);
+    }
+    return NULL;
+}
+
+MediaAlbumArt* MediaMetadataRetriever::extractAlbumArt()
+{
+    if (mRetriever) {
+        return mRetriever->extractAlbumArt();
+    }
+    return NULL;
+}
+
+SkBitmap* MediaMetadataRetriever::captureFrame()
+{
+    if (mRetriever) {
+        return mRetriever->captureFrame();
+    }
+    return NULL;
+}
+
+void MediaMetadataRetriever::setMode(int mode)
+{
+    if (mRetriever) {
+        mRetriever->setMode(mode);
+    }
+}
+
+void MediaMetadataRetriever::release()
+{
+    if (!mLibHandler) {
+        dlclose(mLibHandler);
+        mLibHandler = NULL;
+    }
+    if (!mRetriever) {
+        delete mRetriever;
+        mRetriever = NULL;
+    }
+}
+
+void MediaAlbumArt::clearData() {
+    if (data != NULL) {
+        delete []data;
+        data = NULL;
+    }
+    length = 0;
+}
+
+
+MediaAlbumArt::MediaAlbumArt(const char* url)
+{
+    length = 0;
+    data = NULL;
+    FILE *in = fopen(url, "r");
+    if (!in) {
+        LOGE("extractExternalAlbumArt: Failed to open external album art url: %s.", url);
+        return;
+    }
+    fseek(in, 0, SEEK_END);
+    length = ftell(in);  // Allocating buffer of size equals to the external file size.
+    if (length == 0 || (data = new char[length]) == NULL) {
+        if (length == 0) {
+            LOGE("extractExternalAlbumArt: External album art url: %s has a size of 0.", url);
+        } else if (data == NULL) {
+            LOGE("extractExternalAlbumArt: No enough memory for storing the retrieved album art.");
+            length = 0;
+        }
+        fclose(in);
+        return;
+    }
+    rewind(in);
+    if (fread(data, 1, length, in) != length) {  // Read failed.
+        length = 0;
+        delete []data;
+        data = NULL;
+        LOGE("extractExternalAlbumArt: Failed to retrieve the contents of an external album art.");
+    }
+    fclose(in);
+}
+
+status_t MediaAlbumArt::setData(unsigned int len, const char* buf) {
+    clearData();
+    length = len;
+    data = copyData(len, buf);
+    return (data != NULL)? OK: UNKNOWN_ERROR;
+}
+
+char* MediaAlbumArt::copyData(unsigned int len, const char* buf) {
+    if (len == 0 || !buf) {
+        if (len == 0) {
+            LOGE("copyData: Length is 0.");
+        } else if (!buf) {
+            LOGE("copyData: buf is NULL pointer");
+        }
+        return NULL;
+    }
+    char* copy = new char[len];
+    if (!copy) {
+        LOGE("copyData: No enough memory to copy out the data.");
+        return NULL;
+    }
+    memcpy(copy, buf, len);
+    return copy;
+}
+
+}; // namespace android