当前位置: 首页 > news >正文

郑州做网站公司汉狮价格购物网站建设策划书

郑州做网站公司汉狮价格,购物网站建设策划书,网站建设和成本,互联网项目为了了解 ACodec 是如何与 OpenMAX 组件进行 buffer 流转的#xff0c;我们有必要先来学习 OMXNodeInstance#xff0c;在前面的章节中#xff0c;我们已经了解了 media.codec 进程包含的内容#xff0c;以及 OpenMAX 框架中的一些内容。这一节我们将来学习 OMXNode 与 med… 为了了解 ACodec 是如何与 OpenMAX 组件进行 buffer 流转的我们有必要先来学习 OMXNodeInstance在前面的章节中我们已经了解了 media.codec 进程包含的内容以及 OpenMAX 框架中的一些内容。这一节我们将来学习 OMXNode 与 media.codec 进程之间的关系了解OMXNode是如何创建、使用、销毁的。 1、创建 OMXNodeInstance 我们回到 Omx.cpp 来看 allocateNode 方法 Returnvoid Omx::allocateNode(const hidl_string name,const spIOmxObserver observer,allocateNode_cb _hidl_cb) {using ::android::IOMXNode;using ::android::IOMXObserver;spOMXNodeInstance instance;{// 检查是否到达了 OMXNode 实例最大个数Mutex::Autolock autoLock(mLock);if (mLiveNodes.size() kMaxNodeInstances) {_hidl_cb(toStatus(NO_MEMORY), nullptr);return Void();}// 创建 OMXNodeInstance 实例传入参数为 IOmx 服务IOmxObserver以及组件名称instance new OMXNodeInstance(this, new LWOmxObserver(observer), name.c_str());// 调用 OMXStore 的方法创建 OMX_COMPONENTTYPE 对象OMX_COMPONENTTYPE *handle;OMX_ERRORTYPE err mStore-makeComponentInstance(name.c_str(), OMXNodeInstance::kCallbacks,instance.get(), handle);if (err ! OMX_ErrorNone) {LOG(ERROR) Failed to allocate omx component name.c_str() err asString(err) (0x std::hex unsigned(err) );_hidl_cb(toStatus(StatusFromOMXError(err)), nullptr);return Void();}// 将创建的 OMX_COMPONENTTYPE 对象与 OMXNodeInstance 进行绑定instance-setHandle(handle);// 获取 quirks 信息// Find quirks from mParserconst auto codec mParser.getCodecMap().find(name.c_str());if (codec mParser.getCodecMap().cend()) {LOG(WARNING) Failed to obtain quirks for omx component name.c_str() from XML files;} else {uint32_t quirks 0;for (const auto quirk : codec-second.quirkSet) {if (quirk quirk::requires-allocate-on-input-ports) {quirks | OMXNodeInstance::kRequiresAllocateBufferOnInputPorts;}if (quirk quirk::requires-allocate-on-output-ports) {quirks | OMXNodeInstance::kRequiresAllocateBufferOnOutputPorts;}}// 如果有 quirks 信息则设置instance-setQuirks(quirks);}// 将 IOmxObersver 和 OMXNodeInstance 以键值的形式存储mLiveNodes.add(observer.get(), instance);// 将 OMXNodeInstance 和 IOmxObersver 以键值的形式存储mNode2Observer.add(instance.get(), observer.get());}observer-linkToDeath(this, 0);// 返回 OMXNodeInstance 给 ACodec_hidl_cb(toStatus(OK), new TWOmxNode(instance));return Void(); }allocateNode 方法中的内容还是比较清晰简洁的主要做了如下几件事情 检查 OMXNode 实例个数是否达到上限创建 OMXNodeInstance 实例传入参数为 IOmx 服务IOmxObserver以及组件名称将创建的 OMX_COMPONENTTYPE 对象与 OMXNodeInstance 进行绑定获取 quirks 并给 OMXNodeInstance 设置相关信息将 IOmxObersver 和 OMXNodeInstance 以键值的形式双向绑定存储返回 OMXNodeInstance 返回给 ACodec。 以上是代码的解释接下来是我们对这段代码的理解 OMX_COMPONENTTYPE 是由 OMXStore 创建这个指针由 OMXStore 来管理所以最终也由 OMXStore 来释放OMX_COMPONENTTYPE 和 OMXNodeInstance 进行了绑定OMXNodeInstance帮我们进行OMX组件方法的封装之后上层调用 OMXNodeInstance 的方法OMXNodeInstance 最终调用到组件的接口OMXNodeInstance 的引用计数为2mLiveNodes 中存有一个计数上层ACodec存有一个计数mNode2Observer 中存储的是指针所以不会有计数增加。 2、OMXNodeInstance 构造函数 OMXNodeInstance::OMXNodeInstance(Omx *owner, const spIOMXObserver observer, const char *name): mOwner(owner),mHandle(NULL),mObserver(observer),mDying(false),mSailed(false),mQueriedProhibitedExtensions(false),mQuirks(0),mBufferIDCount(0),mRestorePtsFailed(false),mMaxTimestampGapUs(0LL),mPrevOriginalTimeUs(-1LL),mPrevModifiedTimeUs(-1LL) {mName ADebug::GetDebugName(name);DEBUG ADebug::GetDebugLevelFromProperty(name, debug.stagefright.omx-debug);ALOGV(debug level for %s is %d, name, DEBUG);DEBUG_BUMP DEBUG;mNumPortBuffers[0] 0;mNumPortBuffers[1] 0;mDebugLevelBumpPendingBuffers[0] 0;mDebugLevelBumpPendingBuffers[1] 0;mMetadataType[0] kMetadataBufferTypeInvalid;mMetadataType[1] kMetadataBufferTypeInvalid;mPortMode[0] IOMX::kPortModePresetByteBuffer;mPortMode[1] IOMX::kPortModePresetByteBuffer;mSecureBufferType[0] kSecureBufferTypeUnknown;mSecureBufferType[1] kSecureBufferTypeUnknown;mGraphicBufferEnabled[0] false;mGraphicBufferEnabled[1] false;mIsSecure AString(name).endsWith(.secure);mLegacyAdaptiveExperiment ADebug::isExperimentEnabled(legacy-adaptive); }OMXNodeInstance 的构造函数主要就初始化了几个数组这个数组中都是由两个元素索引0表示input port索引 1 表示 output port以下是一些数组的意义 mNumPortBuffersport 中buffer的数量mMetadataTypemeta data 的类型这个用于确定有surface的情况下ouput buffer的类型以及input为camera或者是graphic录屏的情况下 input buffer的类型mPortMode端口模式mSecureBufferTypesecure buffer 的类型mGraphicBufferEnabled是否使用graphic buffer 看过前面章节的小伙伴应该大致可以揣摩出使用的枚举类型的意义。 void OMXNodeInstance::setHandle(OMX_HANDLETYPE handle) {CLOG_LIFE(allocateNode, handle%p, handle);CHECK(mHandle NULL);mHandle handle;if (handle ! NULL) {mDispatcher new CallbackDispatcher(this);} }setHandle方法可以把创建的OMX组件和OMXNodeInstance实例进行绑定同时会创建一个CallbackDispatcher对象。 3、CallbackDispatcher CallbackDispatcher 从名字上来看是回调的调度者它的作用是开启一个线程所有由OMX组件发上来的消息或者事件都会进入到该线程的队列当中按照顺序一个一个通过 IOmxObserver 发回到 ACodec 层。 OMX callback 会把事件或者消息封装成为 omx_message再通过IOmxObserver发送具体如何封装的以及ACodec如何解封装参考OnEvent、OnEmptyBufferDone、OnFillBufferDone这三个方法的实现。 具体 CallbackDispatcher 和 CallbackDispatcherThread 是如何实现的我们这里不做过多的了解。 4、销毁 OMXNodeInstance 我们常常只关注对象是如何创建的其实销毁的过程也很重要这里我们就一起来了解OMXNode是如何被销毁的。 目光回到 ACodec 中来当我们调用了 initiateShutdown 去释放组件时ACodec 会调用 IOMXNode 的 freeNode 方法 case ACodec::kWhatReleaseCodecInstance:{ALOGI([%s] forcing the release of codec,mCodec-mComponentName.c_str());status_t err mCodec-mOMXNode-freeNode();ALOGE_IF([%s] failed to release codec instance: err%d,mCodec-mComponentName.c_str(), err);mCodec-mCallback-onReleaseCompleted();mCodec-changeState(mCodec-mUninitializedState);break;}最终调用到 OMXNodeInstance 的 freeNode 方法中 status_t OMXNodeInstance::freeNode() {CLOG_LIFE(freeNode, handle%p, mHandle);static int32_t kMaxNumIterations 10;// Transition the node from its current state all the way down// to Loaded.// This ensures that all active buffers are properly freed even// for components that dont do this themselves on a call to// FreeHandle.// The code below may trigger some more events to be dispatched// by the OMX component - we want to ignore them as our client// does not expect them.bool expected false;if (!mDying.compare_exchange_strong(expected, true)) {// exit if we have already freed the node or doing so right now.// NOTE: this ensures that the block below executes at most once.ALOGV(Already dying);return OK;}// 获取 OMX 组件当前的状态OMX_STATETYPE state;CHECK_EQ(OMX_GetState(mHandle, state), OMX_ErrorNone);switch (state) {case OMX_StateExecuting:{// 将OMX状态置为 IdleALOGV(forcing Executing-Idle);sendCommand(OMX_CommandStateSet, OMX_StateIdle);OMX_ERRORTYPE err;int32_t iteration 0;// 阻塞等待while ((err OMX_GetState(mHandle, state)) OMX_ErrorNone state ! OMX_StateIdle state ! OMX_StateInvalid) {if (iteration kMaxNumIterations) {CLOGW(failed to enter Idle state (now %s(%d), aborting.,asString(state), state);state OMX_StateInvalid;break;}usleep(100000);}CHECK_EQ(err, OMX_ErrorNone);if (state OMX_StateInvalid) {break;}FALLTHROUGH_INTENDED;}case OMX_StateIdle:{// 将 OMX 组件状态设置为 LoadedALOGV(forcing Idle-Loaded);sendCommand(OMX_CommandStateSet, OMX_StateLoaded);// 销毁所有 bufferfreeActiveBuffers();OMX_ERRORTYPE err;int32_t iteration 0;// 阻塞等待while ((err OMX_GetState(mHandle, state)) OMX_ErrorNone state ! OMX_StateLoaded state ! OMX_StateInvalid) {if (iteration kMaxNumIterations) {CLOGW(failed to enter Loaded state (now %s(%d), aborting.,asString(state), state);state OMX_StateInvalid;break;}ALOGV(waiting for Loaded state...);usleep(100000);}CHECK_EQ(err, OMX_ErrorNone);FALLTHROUGH_INTENDED;}case OMX_StateLoaded:{// 销毁所有 bufferfreeActiveBuffers();FALLTHROUGH_INTENDED;}case OMX_StateInvalid:break;default:LOG_ALWAYS_FATAL(unknown state %s(%#x)., asString(state), state);break;}Mutex::Autolock _l(mLock);// 调用 OMXNodeInstance 的另一个 freeNode 方法传入参数为自身status_t err mOwner-freeNode(this);// 关闭 Dispatcher 线程销毁相关内容 mDispatcher.clear();mOMXBufferSource.clear();mHandle NULL;CLOG_IF_ERROR(freeNode, err, );free(mName);mName NULL;ALOGV(OMXNodeInstance going away.);return err; }获取 OMX 组件当前的状态按照状态依次设定 OMX_StateIdle、OMX_StateLoaded并且调用 freeActiveBuffers 释放所有的 buffer这里的buffer指的是什么我们后面再看调用 IOmx 的 freeNode 方法传入参数为自身关闭 Dispatcher 线程 这里比较令人疑惑的可能就是第二点了我们刚刚调用的 OMXNode freeNode 干了什么为什么又要调用一个freeNode呢 其实从上面的代码我们可以看出来OMXNodeInstance 的 freeNode 方法是用于关闭或者销毁 OMX 组件所使用的一些资源但是这时候 OMX 组件还是存在没有被销毁的。之所以把销毁资源的方法放在 OMXNodeInstance 中是为了保证 API 调用逻辑的统一所有的关于组件的操作方法都放在 OMXNode 当中。 当OMX组件的资源全部释放完成下一步就是要销毁OMX组件了调用的方法就是 IOmx 的 freeNode 方法 status_t Omx::freeNode(spOMXNodeInstance const instance) {if (instance NULL) {return OK;}{Mutex::Autolock autoLock(mLock);// 获取OMXNode指针ssize_t observerIndex mNode2Observer.indexOfKey(instance.get());if (observerIndex 0) {wpIBase observer mNode2Observer.valueAt(observerIndex);ssize_t nodeIndex mLiveNodes.indexOfKey(observer);// 移除引用计数移除指针if (nodeIndex 0) {mNode2Observer.removeItemsAt(observerIndex);mLiveNodes.removeItemsAt(nodeIndex);spIBase sObserver observer.promote();if (sObserver ! nullptr) {sObserver-unlinkToDeath(this);}} else {LOG(WARNING) Inconsistent observer record;}}}OMX_ERRORTYPE err OMX_ErrorNone;if (instance-handle() ! NULL) {// 调用destroyComponentInstance销毁OMX组件err mStore-destroyComponentInstance(static_castOMX_COMPONENTTYPE*(instance-handle()));}return StatusFromOMXError(err); }移除两个keyedVector 中的键值减少OMXNode引用计数减少IOmxObserver 的引用计数释放资源调用destroyComponentInstance销毁OMX组件最终创建的组件还是由 OMXStore 来销毁 Omx::freeNode 执行完成OMX组件被销毁这时候 OMXNodeInstance 有没有被销毁呢答案是没有的退出 Omx::freeNode 时OMXNodeInstance 的引用计数为 1通过 binder 被 ACodec 持有当 ACodec 销毁时OMXNodeInstance 自然就销毁了。 把之前的一幅图改改来表示 OMXNodeInsatnce、OMX_HANDLE、IOmx、OMXStore 之间的关系
http://www.yutouwan.com/news/76915/

相关文章:

  • 免费制作网站用什么做济南 建网站
  • 杭州如何设计网站首页关键字挖掘机爱站网
  • 三三网是什么网站网上怎么开自己的网店呀
  • 做电脑网站与手机上的一样吗湖南建设厅网站不良记录
  • 网站编辑注意问题网络营销包括哪些
  • 郑州网站设计推荐南海网站设计
  • 做响应式网站兼容哪几个尺寸花生壳做网站速度
  • 手机怎样做刷赞网站《基层建设》官方网站
  • 济南网页开发公司seo建站网络公司
  • seo网站推广方案策划书手机如何创建网页链接
  • 网站建设商务合同范本360搜索推广官网
  • 网站开发后端菜鸟教程广西网站建设价钱
  • 页网站企业资质查询平台
  • 充值网站怎么做的网上祭奠类网站怎么做
  • 自己做的网站如何赚钱吗建在线教育网站需要多少钱
  • 网上做视频赚钱的网站深圳设计公司vi设计模板
  • 网站内容建设 内容审核流程现货行情分析软件app
  • 网站建设业务员的工作总结及计划四川seo关键词工具
  • 黄石有哪些做视觉网站的公司wordpress的播放器
  • 大学学风建设网站莱芜哪里做网站
  • 如何做生鲜配送网站生意安徽网站seo公司
  • 搜集10个优秀网站邯郸网站建设
  • 如乐建站之家学会网站建设项目
  • 建站模板源码高端品牌网站建设公司哪家好
  • 阜阳哪里做网站的多河北 全部阳性了
  • 十大国外室内设计网站怎样在百度上建立网站
  • 网站开发设计手册电费由谁承担
  • 网站营销公司简介中建建设银行网站
  • 网站建设五行属什么icp备案信息查询系统
  • 衡阳网站建设网站做交友信息网站可行么