Merge "libstagefright: run codec profiling in worker thread." into mnc-dev
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index df5e519..3aaa032 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -55,7 +55,10 @@
     // to be used by MediaPlayerService alone
     static sp<IMediaCodecList> getLocalInstance();
 
-    // only to be used in getLocalInstance
+    // only to be used by getLocalInstance
+    static void *profilerThreadWrapper(void * /*arg*/);
+
+    // only to be used by MediaPlayerService
     void parseTopLevelXMLFile(const char *path, bool ignore_errors = false);
 
 private:
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index f366b1f..d48ede9 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -46,8 +46,6 @@
 
 static Mutex sInitMutex;
 
-static MediaCodecList *gCodecList = NULL;
-
 static bool parseBoolean(const char *s) {
     if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
         return true;
@@ -57,64 +55,76 @@
     return *s != '\0' && *end == '\0' && res > 0;
 }
 
+static bool isProfilingNeeded() {
+    bool profilingNeeded = true;
+    FILE *resultsFile = fopen(kProfilingResults, "r");
+    if (resultsFile) {
+        AString currentVersion = getProfilingVersionString();
+        size_t currentVersionSize = currentVersion.size();
+        char *versionString = new char[currentVersionSize + 1];
+        fgets(versionString, currentVersionSize + 1, resultsFile);
+        if (strcmp(versionString, currentVersion.c_str()) == 0) {
+            // profiling result up to date
+            profilingNeeded = false;
+        }
+        fclose(resultsFile);
+        delete[] versionString;
+    }
+    return profilingNeeded;
+}
+
 // static
 sp<IMediaCodecList> MediaCodecList::sCodecList;
 
 // static
-sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
-    bool profilingNeeded = false;
+void *MediaCodecList::profilerThreadWrapper(void * /*arg*/) {
+    ALOGV("Enter profilerThreadWrapper.");
+    MediaCodecList *codecList = new MediaCodecList();
+    if (codecList->initCheck() != OK) {
+        ALOGW("Failed to create a new MediaCodecList, skipping codec profiling.");
+        delete codecList;
+        return NULL;
+    }
+
     Vector<sp<MediaCodecInfo>> infos;
+    for (size_t i = 0; i < codecList->countCodecs(); ++i) {
+        infos.push_back(codecList->getCodecInfo(i));
+    }
+    ALOGV("Codec profiling started.");
+    profileCodecs(infos);
+    ALOGV("Codec profiling completed.");
+    codecList->parseTopLevelXMLFile(kProfilingResults, true /* ignore_errors */);
 
     {
         Mutex::Autolock autoLock(sInitMutex);
+        sCodecList = codecList;
+    }
+    return NULL;
+}
 
-        if (gCodecList == NULL) {
-            gCodecList = new MediaCodecList;
-            if (gCodecList->initCheck() == OK) {
-                sCodecList = gCodecList;
+// static
+sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
+    Mutex::Autolock autoLock(sInitMutex);
 
-                FILE *resultsFile = fopen(kProfilingResults, "r");
-                if (resultsFile) {
-                    AString currentVersion = getProfilingVersionString();
-                    size_t currentVersionSize = currentVersion.size();
-                    char *versionString = new char[currentVersionSize];
-                    fgets(versionString, currentVersionSize, resultsFile);
-                    if (strncmp(versionString, currentVersion.c_str(), currentVersionSize) != 0) {
-                        // profiling result out of date
-                        profilingNeeded = true;
-                    }
-                    fclose(resultsFile);
-                    delete[] versionString;
-                } else {
-                    // profiling results doesn't existed
-                    profilingNeeded = true;
+    if (sCodecList == NULL) {
+        MediaCodecList *codecList = new MediaCodecList;
+        if (codecList->initCheck() == OK) {
+            sCodecList = codecList;
+
+            if (isProfilingNeeded()) {
+                ALOGV("Codec profiling needed, will be run in separated thread.");
+                pthread_t profiler;
+                if (pthread_create(&profiler, NULL, profilerThreadWrapper, NULL) != 0) {
+                    ALOGW("Failed to create thread for codec profiling.");
                 }
-
-                if (profilingNeeded) {
-                    for (size_t i = 0; i < gCodecList->countCodecs(); ++i) {
-                        infos.push_back(gCodecList->getCodecInfo(i));
-                    }
-                }
-            } else {
-                // failure to initialize may be temporary. retry on next call.
-                delete gCodecList;
-                gCodecList = NULL;
             }
+        } else {
+            // failure to initialize may be temporary. retry on next call.
+            delete codecList;
         }
     }
 
-    if (profilingNeeded) {
-        profileCodecs(infos);
-    }
-
-    {
-        Mutex::Autolock autoLock(sInitMutex);
-        if (profilingNeeded) {
-            gCodecList->parseTopLevelXMLFile(kProfilingResults, true /* ignore_errors */);
-        }
-
-        return sCodecList;
-    }
+    return sCodecList;
 }
 
 static Mutex sRemoteInitMutex;