1d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang/* 2d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Copyright (C) 2017 The Android Open Source Project 3d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * 4d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Licensed under the Apache License, Version 2.0 (the "License"); 5d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * you may not use this file except in compliance with the License. 6d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * You may obtain a copy of the License at 7d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * 8d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * http://www.apache.org/licenses/LICENSE-2.0 9d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * 10d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Unless required by applicable law or agreed to in writing, software 11d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * distributed under the License is distributed on an "AS IS" BASIS, 12d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * See the License for the specific language governing permissions and 14d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * limitations under the License. 15d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang */ 16d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 17d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang//#define LOG_NDEBUG 0 185e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang#define LOG_TAG "MediaExtractorFactory" 19d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <utils/Log.h> 20d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 21d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <binder/IServiceManager.h> 22d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/DataSource.h> 23d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaAnalyticsItem.h> 24d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaExtractor.h> 25d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/AMessage.h> 26d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/InterfaceUtils.h> 27d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/MediaExtractorFactory.h> 28d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/IMediaExtractor.h> 29d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/IMediaExtractorService.h> 30d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <cutils/properties.h> 31d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <utils/String8.h> 323e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang#include <ziparchive/zip_archive.h> 33d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 34d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <dirent.h> 35d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <dlfcn.h> 36d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 37d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kangnamespace android { 38d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 39d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static 40d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kangsp<IMediaExtractor> MediaExtractorFactory::Create( 41d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang const sp<DataSource> &source, const char *mime) { 426969da62b068aff2aee650d57590532f8fc8de69Dongwon Kang ALOGV("MediaExtractorFactory::Create %s", mime); 43d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 44d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang if (!property_get_bool("media.stagefright.extractremote", true)) { 45d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // local extractor 46d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGW("creating media extractor in calling process"); 475e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang return CreateFromService(source, mime); 48d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } else { 49d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // remote extractor 50d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGV("get service manager"); 51d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor")); 52d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 53d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang if (binder != 0) { 54d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder)); 55d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang sp<IMediaExtractor> ex = mediaExService->makeExtractor( 56d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang CreateIDataSourceFromDataSource(source), mime); 57d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return ex; 58d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } else { 59d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGE("extractor service not running"); 60d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return NULL; 61d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 62d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 63d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return NULL; 64d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang} 65d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 665e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangsp<IMediaExtractor> MediaExtractorFactory::CreateFromService( 67d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang const sp<DataSource> &source, const char *mime) { 68d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 695e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ALOGV("MediaExtractorFactory::CreateFromService %s", mime); 703e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang 715e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang UpdateExtractors(nullptr); 72d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 73d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // initialize source decryption if needed 74d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang source->DrmInitialization(nullptr /* mime */); 75d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 7617e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang void *meta = nullptr; 77d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang MediaExtractor::CreatorFunc creator = NULL; 7817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang MediaExtractor::FreeMetaFunc freeMeta = nullptr; 79d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang float confidence; 805e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang sp<ExtractorPlugin> plugin; 8117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang creator = sniff(source.get(), &confidence, &meta, &freeMeta, plugin); 82d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang if (!creator) { 83d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGV("FAILED to autodetect media content."); 84d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return NULL; 85d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 86d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 872a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen MediaExtractor *ret = creator(source.get(), meta); 8817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang if (meta != nullptr && freeMeta != nullptr) { 8917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang freeMeta(meta); 9017e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang } 9117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang 9217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang ALOGV("Created an extractor '%s' with confidence %.2f", 9317e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang ret != nullptr ? ret->name() : "<null>", confidence); 9417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang 952a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen return CreateIMediaExtractorFromMediaExtractor(ret, source, plugin); 96d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang} 97d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang//static 993e6d245e154f8a382fd88529c2572d1117685511Dongwon Kangvoid MediaExtractorFactory::LoadPlugins(const ::std::string& apkPath) { 1003e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang // TODO: Verify apk path with package manager in extractor process. 1013e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGV("Load plugins from: %s", apkPath.c_str()); 1023e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang UpdateExtractors(apkPath.empty() ? nullptr : apkPath.c_str()); 1035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang} 1045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 1055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangstruct ExtractorPlugin : public RefBase { 1065e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang MediaExtractor::ExtractorDef def; 1075e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang void *libHandle; 1085e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang String8 libPath; 109c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen String8 uuidString; 1105e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 1115e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path) 112c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen : def(definition), libHandle(handle), libPath(path) { 113c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen for (size_t i = 0; i < sizeof MediaExtractor::ExtractorDef::extractor_uuid; i++) { 114c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen uuidString.appendFormat("%02x", def.extractor_uuid.b[i]); 115c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen } 116c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen } 1175e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ~ExtractorPlugin() { 1185e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (libHandle != nullptr) { 1195e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ALOGV("closing handle for %s %d", libPath.c_str(), def.extractor_version); 1205e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang dlclose(libHandle); 1215e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 1225e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 1235e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang}; 1245e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 1255e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon KangMutex MediaExtractorFactory::gPluginMutex; 1265e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangstd::shared_ptr<List<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins; 1275e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangbool MediaExtractorFactory::gPluginsRegistered = false; 128d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 129d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static 130d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon KangMediaExtractor::CreatorFunc MediaExtractorFactory::sniff( 13117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang DataSourceBase *source, float *confidence, void **meta, 13217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang MediaExtractor::FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin) { 133d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *confidence = 0.0f; 13417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang *meta = nullptr; 135d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 1365e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang std::shared_ptr<List<sp<ExtractorPlugin>>> plugins; 137d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang { 1385e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang Mutex::Autolock autoLock(gPluginMutex); 1395e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (!gPluginsRegistered) { 140d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return NULL; 141d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 1425e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugins = gPlugins; 143d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 144d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 145d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang MediaExtractor::CreatorFunc curCreator = NULL; 146d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang MediaExtractor::CreatorFunc bestCreator = NULL; 1475e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang for (auto it = plugins->begin(); it != plugins->end(); ++it) { 148d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang float newConfidence; 14917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang void *newMeta = nullptr; 15017e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang MediaExtractor::FreeMetaFunc newFreeMeta = nullptr; 15117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang if ((curCreator = (*it)->def.sniff(source, &newConfidence, &newMeta, &newFreeMeta))) { 152d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang if (newConfidence > *confidence) { 153d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *confidence = newConfidence; 15417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang if (*meta != nullptr && *freeMeta != nullptr) { 15517e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang (*freeMeta)(*meta); 15617e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang } 157d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *meta = newMeta; 15817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang *freeMeta = newFreeMeta; 1595e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugin = *it; 160d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang bestCreator = curCreator; 16117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang } else { 16217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang if (newMeta != nullptr && newFreeMeta != nullptr) { 16317e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang newFreeMeta(newMeta); 16417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang } 165d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 166d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 167d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 168d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 169d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return bestCreator; 170d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang} 171d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 172d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static 1735e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangvoid MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin, 1745e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang List<sp<ExtractorPlugin>> &pluginList) { 175d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // sanity check check struct version, uuid, name 1765e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (plugin->def.def_version == 0 1775e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang || plugin->def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) { 1785e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version); 179d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return; 180d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 1815e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (memcmp(&plugin->def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) { 182d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGE("invalid UUID, ignoring"); 183d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return; 184d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 1855e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (plugin->def.extractor_name == NULL || strlen(plugin->def.extractor_name) == 0) { 186d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGE("extractors should have a name, ignoring"); 187d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return; 188d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 189d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 1905e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang for (auto it = pluginList.begin(); it != pluginList.end(); ++it) { 1915e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (memcmp(&((*it)->def.extractor_uuid), &plugin->def.extractor_uuid, 16) == 0) { 192d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // there's already an extractor with the same uuid 1935e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if ((*it)->def.extractor_version < plugin->def.extractor_version) { 194d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang // this one is newer, replace the old one 195d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGW("replacing extractor '%s' version %u with version %u", 1965e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugin->def.extractor_name, 1975e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang (*it)->def.extractor_version, 1985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugin->def.extractor_version); 1995e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang pluginList.erase(it); 200d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang break; 201d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } else { 202d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang ALOGW("ignoring extractor '%s' version %u in favor of version %u", 2035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugin->def.extractor_name, 2045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang plugin->def.extractor_version, 2055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang (*it)->def.extractor_version); 206d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang return; 207d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 208d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 209d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 2105e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang ALOGV("registering extractor for %s", plugin->def.extractor_name); 2115e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang pluginList.push_back(plugin); 212d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang} 213d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 2145e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang//static 215767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kangvoid MediaExtractorFactory::RegisterExtractorsInApk( 2163e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang const char *apkPath, List<sp<ExtractorPlugin>> &pluginList) { 2173e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGV("search for plugins at %s", apkPath); 2183e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ZipArchiveHandle zipHandle; 2193e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang int32_t ret = OpenArchive(apkPath, &zipHandle); 2203e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (ret == 0) { 2213e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang char abi[PROPERTY_VALUE_MAX]; 2223e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang property_get("ro.product.cpu.abi", abi, "arm64-v8a"); 2232b22e7083877778100b7e25b375842b23d14e701Andreas Gampe String8 prefix8 = String8::format("lib/%s/", abi); 2242b22e7083877778100b7e25b375842b23d14e701Andreas Gampe ZipString prefix(prefix8.c_str()); 2253e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ZipString suffix("extractor.so"); 2263e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang void* cookie; 2273e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ret = StartIteration(zipHandle, &cookie, &prefix, &suffix); 2283e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (ret == 0) { 2293e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ZipEntry entry; 2303e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ZipString name; 2313e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang while (Next(cookie, &entry, &name) == 0) { 2323e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang String8 libPath = String8(apkPath) + "!/" + 2333e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang String8(reinterpret_cast<const char*>(name.name), name.name_length); 234767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang // TODO: Open with a linker namespace so that it can be linked with sub-libraries 235767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang // within the apk instead of system libraries already loaded. 2363e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL); 2373e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (libHandle) { 2383e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang MediaExtractor::GetExtractorDef getDef = 2393e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF"); 2403e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (getDef) { 2413e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGV("registering sniffer for %s", libPath.string()); 2423e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang RegisterExtractor( 2433e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang new ExtractorPlugin(getDef(), libHandle, libPath), pluginList); 2443e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang } else { 2453e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGW("%s does not contain sniffer", libPath.string()); 2463e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang dlclose(libHandle); 2473e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang } 248d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } else { 2493e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno)); 250d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 251d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 2523e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang EndIteration(cookie); 2533e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang } else { 2543e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGW("couldn't find plugins from %s, %d", apkPath, ret); 255d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang } 2563e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang CloseArchive(zipHandle); 2575e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } else { 2583e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang ALOGW("couldn't open(%s) %d", apkPath, ret); 2595e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 2605e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang} 2615e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 262767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang//static 263767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kangvoid MediaExtractorFactory::RegisterExtractorsInSystem( 264767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList) { 265767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang ALOGV("search for plugins at %s", libDirPath); 266767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang DIR *libDir = opendir(libDirPath); 267767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang if (libDir) { 268767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang struct dirent* libEntry; 269767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang while ((libEntry = readdir(libDir))) { 270767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang String8 libPath = String8(libDirPath) + "/" + libEntry->d_name; 271767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL); 272767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang if (libHandle) { 273767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang MediaExtractor::GetExtractorDef getDef = 274767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF"); 275767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang if (getDef) { 276767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang ALOGV("registering sniffer for %s", libPath.string()); 277767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang RegisterExtractor( 278767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang new ExtractorPlugin(getDef(), libHandle, libPath), pluginList); 279767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } else { 280767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang ALOGW("%s does not contain sniffer", libPath.string()); 281767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang dlclose(libHandle); 282767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } 283767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } else { 284767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno)); 285767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } 286767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } 287767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang 288767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang closedir(libDir); 289767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } else { 290767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang ALOGE("couldn't opendir(%s)", libDirPath); 291767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang } 292767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang} 293767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang 2945e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang// static 2953e6d245e154f8a382fd88529c2572d1117685511Dongwon Kangvoid MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) { 2965e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang Mutex::Autolock autoLock(gPluginMutex); 2973e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (newUpdateApkPath != nullptr) { 2985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang gPluginsRegistered = false; 2995e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 3005e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang if (gPluginsRegistered) { 3015e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang return; 3025e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 3035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 3045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>()); 3055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang 306767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang RegisterExtractorsInSystem("/system/lib" 307767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#ifdef __LP64__ 308767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang "64" 309767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#endif 310767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang "/extractors", *newList); 311767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang 312767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang RegisterExtractorsInSystem("/vendor/lib" 313767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#ifdef __LP64__ 314767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang "64" 315767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#endif 316767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang "/extractors", *newList); 317d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 3183e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang if (newUpdateApkPath != nullptr) { 319767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang RegisterExtractorsInApk(newUpdateApkPath, *newList); 3205e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang } 321d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 3225e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang gPlugins = newList; 3235e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang gPluginsRegistered = true; 3245e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang} 325d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang 326c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissenstatus_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) { 327c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen Mutex::Autolock autoLock(gPluginMutex); 328c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen String8 out; 329c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen out.append("Available extractors:\n"); 330f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen if (gPluginsRegistered) { 331f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) { 332f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen out.appendFormat(" %25s: uuid(%s), version(%u), path(%s)\n", 333f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen (*it)->def.extractor_name, 334f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen (*it)->uuidString.c_str(), 335f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen (*it)->def.extractor_version, 336f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen (*it)->libPath.c_str()); 337f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen } 338f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen } else { 339f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen out.append(" (no plugins registered)\n"); 340c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen } 341c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen write(fd, out.string(), out.size()); 342c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen return OK; 343c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen} 344c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen 345c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen 346d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang} // namespace android 347