MediaCodec(五) 从MediaCodec到Codec2之create Competent(2)

接着 《MediaCodec(四) 从MediaCodec到Codec2之create Competent(1)》 来看:

codec->init(componentName)  的实现还是比较多的,把主要的步骤分步来看:

/frameworks/av/media/libstagefright/MediaCodec.cpp
1886  status_t MediaCodec::init(const AString &name) {
1887      status_t err = mResourceManagerProxy->init();  //Setp 1
1894  
1895      // save init parameters for reset
1896      mInitName = name;
1902  
1903      mCodecInfo.clear();  //清空 mCodecInfo
1904  
1905      bool secureCodec = false;
1906      const char *owner = "";
1907      if (!name.startsWith("android.filter.")) {
1908          err = mGetCodecInfo(name, &mCodecInfo);  //Step2 调用mGetCodecInfo 函数
1920          secureCodec = name.endsWith(".secure"); //判断是否是加密的组件
1921          Vector<AString> mediaTypes;
1922          mCodecInfo->getSupportedMediaTypes(&mediaTypes); //获取MediaTypes
1923          for (size_t i = 0; i < mediaTypes.size(); ++i) { //根据MediaTypes 区分mDomain   Video or audio or image(image是什么不是很清楚)
1924              if (mediaTypes[i].startsWith("video/")) {
1925                  mDomain = DOMAIN_VIDEO;
1926                  break;
1927              } else if (mediaTypes[i].startsWith("audio/")) {
1928                  mDomain = DOMAIN_AUDIO;
1929                  break;
1930              } else if (mediaTypes[i].startsWith("image/")) {
1931                  mDomain = DOMAIN_IMAGE;
1932                  break;
1933              }
1934          }
1935          owner = mCodecInfo->getOwnerName();
1936      }
1937  
1938      mCodec = mGetCodecBase(name, owner);   //Step3
1944  
1945      if (mDomain == DOMAIN_VIDEO) {  //Video 单独新创建一个 Looper
1946          // video codec needs dedicated looper
1947          if (mCodecLooper == NULL) {
1948              status_t err = OK;
1949              mCodecLooper = new ALooper;
1950              mCodecLooper->setName("CodecLooper");
1951              err = mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
1956          }
1957  
1958          mCodecLooper->registerHandler(mCodec);
1959      } else {
1960          mLooper->registerHandler(mCodec);
1961      }
1964  
1965      mCodec->setCallback(  // Setp4 设置 Codec的 回调函数
1966              std::unique_ptr<CodecBase::CodecCallback>(
1967                      new CodecCallback(new AMessage(kWhatCodecNotify, this))));
1968      mBufferChannel = mCodec->getBufferChannel();  //Step5 获取 BufferChannel
1969      mBufferChannel->setCallback( //设置 BufferChannel 的回调函数
1970              std::unique_ptr<CodecBase::BufferCallback>(
1971                      new BufferCallback(new AMessage(kWhatCodecNotify, this))));
1972      sp<AMessage> msg = new AMessage(kWhatInit, this);  // Step6 发送 kWhatInit
1973      if (mCodecInfo) {
1974          msg->setObject("codecInfo", mCodecInfo);
1977      }
1978      msg->setString("name", name); //设置msg 参数

1980      // initial naming setup covers the period before the first call to ::configure().
1981      // after that, we manage this through ::configure() and the setup message.
1982      if (mMetricsHandle != 0) {
1983          mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
1984          mediametrics_setCString(mMetricsHandle, kCodecMode, toCodecMode(mDomain));
1985      }
1986  
1987      if (mDomain == DOMAIN_VIDEO) {  //video 创建 BatteryChecker?
1988          mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this));
1989      }
1990  
1991      std::vector<MediaResourceParcel> resources;
1992      resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain)));
1993  
1994      // If the ComponentName is not set yet, use the name passed by the user.
1995      if (mComponentName.empty()) {
1996          mResourceManagerProxy->setCodecName(name.c_str()); //Step 7
1997      }
1998      for (int i = 0; i <= kMaxRetry; ++i) {
1999          if (i > 0) {
2000              // Don't try to reclaim resource for the first time.
2001              if (!mResourceManagerProxy->reclaimResource(resources)) {
2002                  break;
2003              }
2004          }
2005  
2006          sp<AMessage> response;
2007          err = PostAndAwaitResponse(msg, &response);
2008          if (!isResourceError(err)) {
2009              break;
2010          }
2011      }
2012  
2013      if (OK == err) {
2014          // Notify the ResourceManager that, this codec has been created
2015          // (initialized) successfully.
2016          mResourceManagerProxy->notifyClientCreated();
2017      }
2018      return err;
2019  }

 Step1:先看下 mResourceManagerProxy->init()

看起来主要是为了获取 "media.resource_manager" 这个service 像是资源管理的,目前还不知做什么用的

 /frameworks/av/media/libstagefright/MediaCodec.cpp
360  struct MediaCodec::ResourceManagerServiceProxy : public RefBase {
------------
//初始化
399  MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(
400          pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client)
401          : mPid(pid), mUid(uid), mClient(client),
402            mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
403      if (mUid == MediaCodec::kNoUid) {
404          mUid = AIBinder_getCallingUid();
405      }
406      if (mPid == MediaCodec::kNoPid) {
407          mPid = AIBinder_getCallingPid();
408      }
409  }
-------------
424  status_t MediaCodec::ResourceManagerServiceProxy::init() {
425      ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.resource_manager"));
426      mService = IResourceManagerService::fromBinder(binder);
431  
432      int callerPid = AIBinder_getCallingPid();
433      int callerUid = AIBinder_getCallingUid();
434      if (mPid != callerPid || mUid != callerUid) {
435          // Media processes don't need special permissions to act on behalf of other processes.
436          if (callerUid != AID_MEDIA) {
437              char const * permission = "android.permission.MEDIA_RESOURCE_OVERRIDE_PID";
438              if (!checkCallingPermission(String16(permission))) {
439                  ALOGW("%s is required to override the caller's PID for media resource management.",
440                          permission);
441                  return PERMISSION_DENIED;
442              }
443          }
444      }
445  
446      // Kill clients pending removal.
447      mService->reclaimResourcesFromClientsPendingRemoval(mPid);
448  
449      // so our handler will process the death notifications
450      addCookie(this);
451  
452      // after this, require mLock whenever using mService
453      AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
454      return OK;
455  }

Step2:err = mGetCodecInfo(name, &mCodecInfo)

这边就用到了上一篇 MediaCodec::MediaCodec的匿名函数:

1058      if (!mGetCodecInfo) {
1059          mGetCodecInfo = [&log = mErrorLog](const AString &name,
1060                                             sp<MediaCodecInfo> *info) -> status_t {
1061              *info = nullptr;
1062              const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
1067              AString tmp = name;
1068              if (tmp.endsWith(".secure")) { //如果是name 是 .secure 结束的,那么就移除.secure 储存在 tmp 中 
1069                  tmp.erase(tmp.size() - 7, 7);  
1070              }
1071              for (const AString &codecName : { name, tmp }) {  //首先寻找secure的,如果没有就找non_secure的 codec,比如 {"c2.android.amrnb.decoder.secure", "c2.android.amrnb.decoder"}
1072                  ssize_t codecIdx = mcl->findCodecByName(codecName.c_str()); //在 MediaCodecList 寻找 findCodecByName
1073                  if (codecIdx < 0) {
1074                      continue;
1075                  }
1076                  *info = mcl->getCodecInfo(codecIdx);
1077                  return OK;
1078              }
1079              log.log(LOG_TAG, base::StringPrintf("Codec with name '%s' is not found on the device.",
1080                                    name.c_str()));
1081              return NAME_NOT_FOUND;
1082          };
1083      }
  • 首先是获取 MediaCodecList::getInstance();这边主要就是为了获取   sp<IMediaCodecList> MediaCodecList::sRemoteList; 具体的获取方法在下一篇有讲,这边就不展开了;
 /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"));
187          sp<IMediaPlayerService> service = //获取"media.player" 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  }
  • 然后 mcl->findCodecByName(codecName.c_str()) 寻找 codecInx,如果没有找到就返回 ENOENT

Decoder "c2.android.amrnb.decoder" supports
aliases: ["OMX.google.amrnb.decoder" ]

 /frameworks/av/media/libstagefright/MediaCodecList.cpp
294  ssize_t MediaCodecList::findCodecByName(const char *name) const {
295      Vector<AString> aliases;
296      for (size_t i = 0; i < mCodecInfos.size(); ++i) {
297          if (strcmp(mCodecInfos[i]->getCodecName(), name) == 0) {  //如果在 mCodecInfos中找到 name 的codec 就返回 i
298              return i;
299          }
300          mCodecInfos[i]->getAliases(&aliases);  //不然就再用 mCodecInfos 的别名中查找 name 的codec
301          for (const AString &alias : aliases) {
302              if (alias == name) {
303                  return i;
304              }
305          }
306      }
307  
308      return -ENOENT;  //没有找到的话就会返回 ENOENT
309  }
  • 最后看一下 mcl->getCodecInfo(codecIdx); 主要是为了获取到 index 对应的 MediaCodecInfo 信息,里面主要储存了 ProfileLevel、Attributes、Capabilities、CapabilitiesWriter
 /frameworks/av/media/libstagefright/include/media/stagefright/MediaCodecList.h
51      virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const {
52          if (index >= mCodecInfos.size()) {
53              ALOGE("b/24445127");
54              return NULL;
55          }
56          return mCodecInfos[index];
57      }
 std::vector<sp<MediaCodecInfo> > mCodecInfos;
========================
 /frameworks/av/media/libmedia/include/media/MediaCodecInfo.h
45  struct MediaCodecInfo : public RefBase {
46      struct ProfileLevel {
47          uint32_t mProfile;
48          uint32_t mLevel;
49          bool operator <(const ProfileLevel &o) const {
50              return mProfile < o.mProfile || (mProfile == o.mProfile && mLevel < o.mLevel);
51          }
52      };
55  
56      enum Attributes : int32_t {
57          // attribute flags
58          kFlagIsEncoder = 1 << 0,
59          kFlagIsVendor = 1 << 1,
60          kFlagIsSoftwareOnly = 1 << 2,
61          kFlagIsHardwareAccelerated = 1 << 3,
62      };
63  
64      struct Capabilities : public RefBase {
65          constexpr static char FEATURE_ADAPTIVE_PLAYBACK[] = "feature-adaptive-playback";
66          constexpr static char FEATURE_DYNAMIC_TIMESTAMP[] = "feature-dynamic-timestamp";
67          constexpr static char FEATURE_FRAME_PARSING[] = "feature-frame-parsing";
68          constexpr static char FEATURE_INTRA_REFRESH[] = "feature-frame-parsing";
69          constexpr static char FEATURE_MULTIPLE_FRAMES[] = "feature-multiple-frames";
70          constexpr static char FEATURE_SECURE_PLAYBACK[] = "feature-secure-playback";
71          constexpr static char FEATURE_TUNNELED_PLAYBACK[] = "feature-tunneled-playback";
.......
118      };
119
120      /**
121       * This class is used for modifying information inside a `Capabilities`
122       * object. An object of type `CapabilitiesWriter` can be obtained by calling
123       * `MediaCodecInfoWriter::addMediaType()`.
124       */
125      struct CapabilitiesWriter {
......
186      };
253  };

Step 3:mCodec = mGetCodecBase(name, owner); 这边主要是为了获取 ACodec 或者 Codec2 的对象;

 /frameworks/av/media/libstagefright/MediaCodec.cpp
1054          mGetCodecBase = [](const AString &name, const char *owner) {
1055              return GetCodecBase(name, owner);
1056          };
-----------------
1845  sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, const char *owner) {
1846      if (owner) {
1847          if (strcmp(owner, "default") == 0) {
1848              return new ACodec;  //创建 ACodec
1849          } else if (strncmp(owner, "codec2", 6) == 0) {
1850              return CreateCCodec(); //创建 CCodec
1851          }
1852      }
1853  
1854      if (name.startsWithIgnoreCase("c2.")) {
1855          return CreateCCodec();
1856      } else if (name.startsWithIgnoreCase("omx.")) {
1857          // at this time only ACodec specifies a mime type.
1858          return new ACodec;
1859      } else {
1860          return NULL;
1861      }
1862  }

继续来看 CreateCCodec创建 Codec2 的对象,其中主要是为了创建 CCodecBufferChannel(buffer 相关的) 和 CCodecConfig 这两个比较重要,在后面单独去看!

 /frameworks/av/media/libstagefright/MediaCodec.cpp
1840  static CodecBase *CreateCCodec() {
1841      return new CCodec;
1842  }
==============
//这边开始进入 CCodec 了,主要是为了创建 CCodecBufferChannel 和  CCodecConfig
 /frameworks/av/media/codec2/sfplugin/CCodec.cpp
693  CCodec::CCodec()
694      : mChannel(new CCodecBufferChannel(std::make_shared<CCodecCallbackImpl>(this))),
695        mConfig(new CCodecConfig) {
696  }

Step 4: mCodec->setCallback(std::unique_ptr<CodecBase::CodecCallback>(new CodecCallback(new AMessage(kWhatCodecNotify, this))));  这边就是设置 codec 的回调函数,最终都会call kWhatCodecNotify 中去

new AMessage(kWhatCodecNotify, this)  //创建 AMessage 对象,把 kWhatCodecNotify 的实现赋给 mWhat,这样回调的话,就会call 到 kWhatCodecNotify 中去
60  AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
61      : mWhat(what) {
62      setTarget(handler);
63  }
======================
new CodecCallback(new AMessage(kWhatCodecNotify, this) // 再把Amessage作为参数赋值给CodecCallback 的 mNotify
735  class CodecCallback : public CodecBase::CodecCallback {
766  CodecCallback::CodecCallback(const sp<AMessage> &notify) : mNotify(notify) {}

Step5:mBufferChannel = mCodec->getBufferChannel(); 调用Acodec/Codec2 的 getBufferChannel函数 获取 CCodecBufferChannel 对象,CCodecBufferChannel 部分在 《Codec2(1) CCodecBufferChannel》学习。

/frameworks/av/media/codec2/sfplugin/
H A D	CCodec.cpp	701 std::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
/frameworks/av/media/libstagefright/
H A D	ACodec.cpp	631 std::shared_ptr<BufferChannelBase> ACodec::getBufferChannel() {
======================
//看下Codec2 的,很简单 就是返回 mChannel,而mChannel 是在上面创建 Codec2 对像的时候 new 的
701  std::shared_ptr<BufferChannelBase> CCodec::getBufferChannel() {
702      return mChannel;
703  }

mBufferChannel->setCallback(std::unique_ptr<CodecBase::BufferCallback>(new BufferCallback(new AMessage(kWhatCodecNotify, this)))); 这一句为 mBufferChannel 设置回调函数和Setp 4一样,最终返回值在 kWhatCodecNotify 中处理;

Step6:sp<AMessage> msg = new AMessage(kWhatInit, this);

kWhatInit 的处理 主要是根据传送的 codecinfo 和name 去调用 CCodec/Acodec 的 initiateAllocateComponent 创建组件,同时设置状态为 INITIALIZING

 /frameworks/av/media/libstagefright/MediaCodec.cpp
4353          case kWhatInit:
4354          {
4360              if (mReplyID) {
4361                  mDeferredMessages.push_back(msg);
4362                  break;
4363              }
4364              sp<AReplyToken> replyID;
4365              CHECK(msg->senderAwaitsResponse(&replyID));
4366  
4367              mReplyID = replyID;
4368              setState(INITIALIZING);  //设置状态 INITIALIZING
4369  
4370              sp<RefBase> codecInfo;
4371              (void)msg->findObject("codecInfo", &codecInfo);
4372              AString name;
4373              CHECK(msg->findString("name", &name));
4374  
4375              sp<AMessage> format = new AMessage;
4376              if (codecInfo) {
4377                  format->setObject("codecInfo", codecInfo);
4378              }
4379              format->setString("componentName", name);
4380  
4381              mCodec->initiateAllocateComponent(format); //根据传送过来的codecInfo 和 name 创建 Component
4382              break;
4383          }

initiateAllocateComponent 的实现看下篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值