MediaCodec(五·1) Codec 支援格式的解析流程

 这边继续介绍 上一篇 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() 的实现:

  1. 获取 “media,player” service;
  2. 调用 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());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值