这边继续介绍 上一篇 findMatchingCodecs 的实现
/frameworks/av/media/libstagefright/MediaCodecList.cpp
357 void MediaCodecList::findMatchingCodecs(
358 const char *mime, bool encoder, uint32_t flags, const sp<AMessage> &format,
359 Vector<AString> *matches) {
360 matches->clear();
361
362 const sp<IMediaCodecList> list = getInstance(); //获取IMediaCodecList 实例
366
367 size_t index = 0;
368 for (;;) {
369 ssize_t matchIndex =
370 list->findCodecByType(mime, encoder, index); //call findCodecByType
371
376 index = matchIndex + 1;
377
378 const sp<MediaCodecInfo> info = list->getCodecInfo(matchIndex);
380
381 AString componentName = info->getCodecName();
382
383 if (!codecHandlesFormat(mime, info, format)) {
384 ALOGV("skipping codec '%s' which doesn't satisfy format %s",
385 componentName.c_str(), format->debugString(2).c_str());
386 continue;
387 }
388
389 if ((flags & kHardwareCodecsOnly) && isSoftwareCodec(componentName)) {
390 ALOGV("skipping SW codec '%s'", componentName.c_str());
391 continue;
392 }
393
394 matches->push(componentName);
395 ALOGV("matching '%s'", componentName.c_str());
396 }
397
398 if (flags & kPreferSoftwareCodecs ||
399 property_get_bool("debug.stagefright.swcodec", false)) {
400 matches->sort(compareSoftwareCodecsFirst);
401 }
402
403 // if we did NOT find anything maybe it's because of a profile mismatch.
404 // let's recurse after trimming the profile from the format to see if that yields
405 // a suitable codec.
406 //
407 int profile = -1;
408 if (matches->empty() && format != nullptr && format->findInt32(KEY_PROFILE, &profile)) {
409 ALOGV("no matching codec found, retrying without profile");
410 sp<AMessage> formatNoProfile = format->dup();
411 formatNoProfile->removeEntryByName(KEY_PROFILE);
412 findMatchingCodecs(mime, encoder, flags, formatNoProfile, matches);
413 }
414 }
(1) 先看下 getInstance() 的实现:
- 获取 “media,player” service;
- 调用 service->getCodecList;
/frameworks/av/media/libstagefright/MediaCodecList.cpp
183 sp<IMediaCodecList> MediaCodecList::getInstance() {
184 Mutex::Autolock _l(sRemoteInitMutex);
185 if (sRemoteList == nullptr) {
186 sMediaPlayer = defaultServiceManager()->getService(String16("media.player")); //获取 "media.player"
187 sp<IMediaPlayerService> service =
188 interface_cast<IMediaPlayerService>(sMediaPlayer);
189 if (service.get() != nullptr) {
190 sRemoteList = service->getCodecList();
191 if (sRemoteList != nullptr) {
192 sBinderDeathObserver = new BinderDeathObserver();
193 sMediaPlayer->linkToDeath(sBinderDeathObserver.get());
194 }
195 }
196 if (sRemoteList == nullptr) {
197 // if failed to get remote list, create local list
198 sRemoteList = getLocalInstance();
199 }
200 }
201 return sRemoteList;
202 }
1. 这边是获取 “media.player” 没有什么;
"media.player" service
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
441 void MediaPlayerService::instantiate() {
442 defaultServiceManager()->addService(
443 String16("media.player"), new MediaPlayerService());
444 }
--------------
446 MediaPlayerService::MediaPlayerService()
447 {
448 ALOGV("MediaPlayerService created");
449 mNextConnId = 1;
450
451 MediaPlayerFactory::registerBuiltinFactories();
452 }
2. 调用 service->getCodecList:主要就是为了 创建 MediaCodecList 里面存有支持的 codec 格式和信息;
518 sp<IMediaCodecList> MediaPlayerService::getCodecList() const {
519 return MediaCodecList::getLocalInstance();
520 }
===================
/frameworks/av/media/libstagefright/MediaCodecList.cpp
147 sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
148 Mutex::Autolock autoLock(sInitMutex);
149
150 if (sCodecList == nullptr) {
151 MediaCodecList *codecList = new MediaCodecList(GetBuilders()); //又去创建 MediaCodecList 对象
152 if (codecList->initCheck() == OK) {
153 sCodecList = codecList;
154
155 if (isProfilingNeeded()) { //这边不是很清楚
156 ALOGV("Codec profiling needed, will be run in separated thread.");
157 pthread_t profiler;
158 if (pthread_create(&profiler, nullptr, profilerThreadWrapper, nullptr) != 0) {
159 ALOGW("Failed to create thread for codec profiling.");
160 }
161 }
162 } else {
163 // failure to initialize may be temporary. retry on next call.
164 delete codecList;
165 }
166 }
167
168 return sCodecList;
169 }
--------------------
/frameworks/av/media/libstagefright/MediaCodecList.cpp
204 MediaCodecList::MediaCodecList(std::vector<MediaCodecListBuilderBase*> builders) {
205 mGlobalSettings = new AMessage();
206 mCodecInfos.clear();
207 MediaCodecListWriter writer;
208 for (MediaCodecListBuilderBase *builder : builders) {
213 auto currentCheck = builder->buildMediaCodecList(&writer);
221 writer.writeGlobalSettings(mGlobalSettings);
222 writer.writeCodecInfos(&mCodecInfos);
223 std::stable_sort( //给 mCodecInfos 根据 Rank 排名
224 mCodecInfos.begin(),
225 mCodecInfos.end(),
226 [](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
227 // null is lowest
228 return info1 == nullptr || (info2 != nullptr && info1->getRank() < info2->getRank());
230 });
231 // 拿掉 mCodecInfos 中重复的 codecName
232 // remove duplicate entries
233 bool dedupe = property_get_bool("debug.stagefright.dedupe-codecs", true);
234 if (dedupe) {
235 std::set<std::string> codecsSeen;
236 for (auto it = mCodecInfos.begin(); it != mCodecInfos.end(); ) {
237 std::string codecName = (*it)->getCodecName();
238 if (codecsSeen.count(codecName) == 0) {
239 codecsSeen.emplace(codecName);
240 it++;
241 } else {
242 it = mCodecInfos.erase(it);
243 }
244 }
245 }
看下new MediaCodecList 入参 GetBuilders() 是什么?
/frameworks/av/media/libstagefright/MediaCodecList.cpp
97 std::vector<MediaCodecListBuilderBase *> GetBuilders() {
98 std::vector<MediaCodecListBuilderBase *> builders;
99 // if plugin provides the input surface, we cannot use OMX video encoders.
100 // In this case, rely on plugin to provide list of OMX codecs that are usable.
101 sp<PersistentSurface> surfaceTest = CCodec::CreateInputSurface();
102 if (surfaceTest == nullptr) {
103 ALOGD("Allowing all OMX codecs");
104 builders.push_back(&sOmxInfoBuilder); //这边是 OMX 的 codec info
105 } else {
106 ALOGD("Allowing only non-surface-encoder OMX codecs");
107 builders.push_back(&sOmxNoSurfaceEncoderInfoBuilder);
108 }
109 builders.push_back(GetCodec2InfoBuilder()); //我们直接看这边 Codec2 的 创建方法
110 return builders;
111 }
----------------
89 MediaCodecListBuilderBase *GetCodec2InfoBuilder() {
90 Mutex::Autolock _l(sCodec2InfoBuilderMutex);
91 if (!sCodec2InfoBuilder) {
92 sCodec2InfoBuilder.reset(new Codec2InfoBuilder);
93 }
94 return sCodec2InfoBuilder.get(); //返回 Codec2InfoBuilder 实例
95 }
----------------
25 class Codec2InfoBuilder : public MediaCodecListBuilderBase {
29 status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
接着就去 调用 Codec2InfoBuilder 实例的 builder->buildMediaCodecList(&writer);
可以看到 buildMediaCodecList 主要就是去解析 XML 获取 codec info 并储存在 writer 中
/frameworks/av/media/codec2/sfplugin/Codec2InfoBuilder.cpp
396 status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
400 // debug.stagefright.ccodec supports 5 values. //这个值可以设置 一些优先级
401 // 0 - No Codec 2.0 components are available.
402 // 1 - Audio decoders and encoders with prefix "c2.android." are available
403 // and ranked first.
404 // All other components with prefix "c2.android." are available with
405 // their normal ranks.
406 // Components with prefix "c2.vda." are available with their normal
407 // ranks.
408 // All other components with suffix ".avc.decoder" or ".avc.encoder"
409 // are available but ranked last.
410 // 2 - Components with prefix "c2.android." are available and ranked
411 // first.
412 // Components with prefix "c2.vda." are available with their normal
413 // ranks.
414 // All other components with suffix ".avc.decoder" or ".avc.encoder"
415 // are available but ranked last.
416 // 3 - Components with prefix "c2.android." are available and ranked
417 // first.
418 // All other components are available with their normal ranks.
419 // 4 - All components are available with their normal ranks.
420 //
421 // The default value (boot time) is 1.
422 //
423 // Note: Currently, OMX components have default rank 0x100, while all
424 // Codec2.0 software components have default rank 0x200.
425 int option = ::android::base::GetIntProperty("debug.stagefright.ccodec", 4);
426
427 // Obtain Codec2Client
428 std::vector<Traits> traits = Codec2Client::ListComponents();
429 //这边去解析 XML 档案,会先去找 /apex/ 路径下的,再去找vendor 下的
430 // parse APEX XML first, followed by vendor XML.
431 // Note: APEX XML names do not depend on ro.media.xml_variant.* properties.
432 MediaCodecsXmlParser parser;
433 parser.parseXmlFilesInSearchDirs(
434 { "media_codecs.xml", "media_codecs_performance.xml" },
435 { "/apex/com.android.media.swcodec/etc" });
436
437 // TODO: remove these c2-specific files once product moved to default file names
438 parser.parseXmlFilesInSearchDirs(
439 { "media_codecs_c2.xml", "media_codecs_performance_c2.xml" });
440
441 // parse default XML files
442 parser.parseXmlFilesInSearchDirs();
..... //后面主要 就是解析 XML 档案
buildMediaCodecList 中详细的解析过程就不看,有兴趣自己追追看,我们一般debug 时回去执行 dumpsys media.player 如下,看起就是 这边解析出来的结果
Decoder infos by media types:
=============================
Media type 'audio/3gpp':
Decoder "c2.android.amrnb.decoder" supports
aliases: [
"OMX.google.amrnb.decoder" ]
attributes: 0x4: [
encoder: 0,
vendor: 0,
software-only: 1,
hw-accelerated: 0 ]
owner: "codec2::software"
rank: 8
profile/levels: []
colors: []
details: AMessage(what = 0x00000000) = {
string bitrate-range = "4750-12200"
string max-channel-count = "1"
string sample-rate-ranges = "8000"
}
Media type 'audio/amr-wb':
Decoder "c2.android.amrwb.decoder" supports
aliases: [
"OMX.google.amrwb.decoder" ]
attributes: 0x4: [
encoder: 0,
vendor: 0,
software-only: 1,
hw-accelerated: 0 ]
owner: "codec2::software"
rank: 8
profile/levels: []
colors: []
details: AMessage(what = 0x00000000) = {
string bitrate-range = "6600-23850"
string max-channel-count = "1"
string sample-rate-ranges = "16000"
}
再来看下 这两个函数在做什么
221 writer.writeGlobalSettings(mGlobalSettings); //把解析的出settings 存到 mGlobalSettings
222 writer.writeCodecInfos(&mCodecInfos); //把解析出的 Infos 存到mCodecInfos
/frameworks/av/media/libstagefright/MediaCodecListWriter.cpp
50 void MediaCodecListWriter::writeGlobalSettings(
51 const sp<AMessage> &globalSettings) const {
52 for (const std::pair<std::string, std::string> &kv : mGlobalSettings) {
53 globalSettings->setString(kv.first.c_str(), kv.second.c_str());
54 }
55 }
----------------
57 void MediaCodecListWriter::writeCodecInfos(
58 std::vector<sp<MediaCodecInfo>> *codecInfos) const {
59 for (const sp<MediaCodecInfo> &info : mCodecInfos) {
60 codecInfos->push_back(info);
61 }
62 }
====================
/frameworks/av/media/codec2/sfplugin/Codec2InfoBuilder.cpp
396 status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
503 for (const auto &v : settings) {
504 if (!hasPrefix(v.first, "media-type-")
505 && !hasPrefix(v.first, "domain-")
506 && !hasPrefix(v.first, "variant-")) {
507 writer->addGlobalSetting(v.first.c_str(), v.second.c_str());
508 }
509 }
511
512 for (const Traits& trait : traits) {
628
629 ALOGV("adding codec entry for '%s'", nameOrAlias.c_str());
630 std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
631 codecInfo->setName(nameOrAlias.c_str());
632 codecInfo->setOwner(("codec2::" + trait.owner).c_str());