win7家用电脑做网站服务器,360建筑网官网下载,网站优化千牛帮,深圳十佳设计公司排名上节学到setDataSource()时会创建各种Source#xff0c;source用来读取音视频源文件#xff0c;读取到之后需要demux出音、视频、字幕数据流#xff0c;然后再送去解码。那么负责进行demux功能的media extractor模块是在什么时候阶段创建的#xff1f;这里暂时不考虑APP创建…上节学到setDataSource()时会创建各种Sourcesource用来读取音视频源文件读取到之后需要demux出音、视频、字幕数据流然后再送去解码。那么负责进行demux功能的media extractor模块是在什么时候阶段创建的这里暂时不考虑APP创建的情况以前面学过的GenericSource为例它是在prepare阶段被创建的。本节暂时不分析GenericSource创建extractor的流程先来看看MediaExtractorService的启动过程。
mediaextractor
MediaExtractorService的服务名为mediaextractor
//frameworks/av/services/mediaextractor/mediaextractor.rc
service mediaextractor /system/bin/mediaextractorclass mainuser mediaexgroup drmrpc mediadrmioprio rt 4writepid /dev/cpuset/foreground/tasks
直接看main函数
//frameworks/av/services/mediaextractor/main_extractorservice.cpp
int main(int argc __unused, char** argv)
{#if __has_feature(hwaddress_sanitizer)ALOGI(disable media.extractor memory limits (hwasan enabled));
#elseALOGI(enable media.extractor memory limits);limitProcessMemory(ro.media.maxmem, /* property that defines limit */SIZE_MAX, /* upper limit in bytes */20 /* upper limit as percentage of physical RAM */);
#endifsignal(SIGPIPE, SIG_IGN);//b/62255959: this forces libutis.so to dlopen vendor version of libutils.so//before minijail is on. This is dirty but required since some syscalls such//as pread64 are used by linker but arent allowed in the minijail. By//calling the function before entering minijail, we can force dlopen.android::report_sysprop_change();SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);strcpy(argv[0], media.extractor);spProcessState proc(ProcessState::self());spIServiceManager sm defaultServiceManager();MediaExtractorService::instantiate();ProcessState::self()-startThreadPool();IPCThreadState::self()-joinThreadPool();
}
由于MediaExtractorService继承自模板类BinderService所以直接调用它的instantiate()来创建service且加入service manager中
//frameworks/native/include/binder/BinderService.h
static void instantiate() { publish(); }static status_t publish(bool allowIsolated false,int dumpFlags IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {spIServiceManager sm(defaultServiceManager());return sm-addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);
}
接下来主要看MediaExtractorService构造函数做了什么
//frameworks/av/services/mediaextractor/MediaExtractorService.cpp
MediaExtractorService::MediaExtractorService() {MediaExtractorFactory::LoadExtractors();
}
其直接调用到MediaExtractorFactory中的LoadExtractors()方法
//frameworks/av/media/libstagefright/MediaExtractorFactory.cpp
// static
void MediaExtractorFactory::LoadExtractors() {Mutex::Autolock autoLock(gPluginMutex);if (gPluginsRegistered) {return;}gIgnoreVersion property_get_bool(debug.extractor.ignore_version, false);std::shared_ptrstd::listspExtractorPlugin newList(new std::listspExtractorPlugin());android_namespace_t *mediaNs android_get_exported_namespace(com_android_media);if (mediaNs ! NULL) {const android_dlextinfo dlextinfo {.flags ANDROID_DLEXT_USE_NAMESPACE,.library_namespace mediaNs,};RegisterExtractors(/apex/com.android.media/lib
#ifdef __LP64__64
#endif/extractors, dlextinfo, *newList);} else {ALOGE(couldnt find media namespace.);}RegisterExtractors(/system/lib
#ifdef __LP64__64
#endif/extractors, NULL, *newList);RegisterExtractors(/system_ext/lib
#ifdef __LP64__64
#endif/extractors, NULL, *newList);newList-sort(compareFunc);gPlugins newList;for (auto it gPlugins-begin(); it ! gPlugins-end(); it) {if ((*it)-def.def_version EXTRACTORDEF_VERSION_NDK_V2) {for (size_t i 0;; i) {const char* ext (*it)-def.u.v3.supported_types[i];if (ext nullptr) {break;}gSupportedExtensions.push_back(std::string(ext));}}}gPluginsRegistered true;
}
简单描述下这段代码所做的操作
创建一个list用来保存即将获取到的指向ExtractorPlugin对象的sp指针。依次到如下目录通过RegisterExtractors()方法逐个注册ExtractorPlugin到list中 /apex/com.android.media/lib(64)/extractors/system/lib(64)/extractors/system_ext/lib(64)/extractors将list内的内容按extractor_name从小到大的顺序重新排序并将其保存到gPlugins中。最后一个for循环主要是将各个extractor所支持的mime type或者文件扩展名保存到gSupportedExtensions中可用于后续查询。
再简单看看RegisterExtractors()方法
//frameworks/av/media/libstagefright/MediaExtractorFactory.cpp
void MediaExtractorFactory::RegisterExtractors(const char *libDirPath, const android_dlextinfo* dlextinfo,std::listspExtractorPlugin pluginList) {ALOGV(search for plugins at %s, libDirPath);DIR *libDir opendir(libDirPath);if (libDir) {struct dirent* libEntry;while ((libEntry readdir(libDir))) {if (libEntry-d_name[0] .) {continue;}String8 libPath String8(libDirPath) / libEntry-d_name;if (!libPath.contains(extractor.so)) {continue;}void *libHandle android_dlopen_ext(libPath.string(),RTLD_NOW | RTLD_LOCAL, dlextinfo);if (libHandle nullptr) {ALOGI(dlopen(%s) reported error %s, libPath.string(), strerror(errno));continue;}GetExtractorDef getDef (GetExtractorDef) dlsym(libHandle, GETEXTRACTORDEF);if (getDef nullptr) {ALOGI(no sniffer found in %s, libPath.string());dlclose(libHandle);continue;}ALOGV(registering sniffer for %s, libPath.string());RegisterExtractor(new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);}closedir(libDir);} else {ALOGI(plugin directory not present (%s), libDirPath);}
}
主要功能如下
遍历指定目录下的所有后缀为extractor.so的库并将其通过dlopen()打开。再通过dlsym()方法获取到GETEXTRACTORDEF()函数的指针。对于每一个extractor创建一个对应的ExtractorPlugin然后将他们一个个的加入pluginList中。
到此MediaExtractorService就启动完成了所做的事情也是相当简单加载目标目录下所有的extractor并保存到一个list中。
MediaExtractorService还提供了另外两个接口makeExtractor()和makeIDataSource()。通过搜索code大概总结一下
makeIDataSource()提供给GenericSource调用用于根据本地播放文件创建出一个IDataSource对象。这个对象进一步会被封装成一个TinyCacheSource对象用于后面创建extractor。makeExtractor()会被封装到MediaExtractorFactory::Create()方法中该方法会被GenericSource调用还会被JNI/JAVA调用来创建extractor。
简单以图来总结下