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

现代电子商务网站建设技术竹木工艺品网站建设

现代电子商务网站建设技术,竹木工艺品网站建设,北京卓天下网站建设公司,龙华做网站联系电话上一节我们了解到 ACodec 执行完 start 流程后,会把所有的 input buffer 都提交给 MediaCodec 层,MediaCodec 是如何处理传上来的 buffer 呢?这一节我们就来了解一下这部分内容。 1、ACodecBufferChannel::fillThisBuffer ACodec 通过调用 A…

上一节我们了解到 ACodec 执行完 start 流程后,会把所有的 input buffer 都提交给 MediaCodec 层,MediaCodec 是如何处理传上来的 buffer 呢?这一节我们就来了解一下这部分内容。

1、ACodecBufferChannel::fillThisBuffer

ACodec 通过调用 ACodecBufferChannel::fillThisBuffer 把input buffer传递给 MediaCodc,传入参数为 buffer id:

void ACodecBufferChannel::fillThisBuffer(IOMX::buffer_id bufferId) {ALOGV("fillThisBuffer #%d", bufferId);std::shared_ptr<const std::vector<const BufferInfo>> array(std::atomic_load(&mInputBuffers));// 遍历buffer数组,查找对应ACodecBufferChannel::BufferInfoBufferInfoIterator it = findBufferId(array, bufferId);if (it == array->end()) {ALOGE("fillThisBuffer: unrecognized buffer #%d", bufferId);return;}// 如果存在解密/解扰,那么需要设置input formatif (it->mClientBuffer != it->mCodecBuffer) {it->mClientBuffer->setFormat(it->mCodecBuffer->format());}// 调用callbackmCallback->onInputBufferAvailable(std::distance(array->begin(), it),it->mClientBuffer);
}

fillThisBuffer 很简单,主要步骤如下:

  1. 遍历buffer数组,根据bufferid查找对应ACodecBufferChannel::BufferInfo,从而获得mClientBuffer;我们这里再回顾一下,在不用解密/解扰的模式下,mClientBuffer和mCodecBuffer其实是指向同一个MediaCodecBuffer的,解密/解扰的模式那么mClientBuffer和mCodecBuffer指向的则不是同一块MediaCodecBuffer了;
  2. 如果mClientBuffer和mCodecBuffer不是指向同一块MediaCodecBuffer,那么需要给 mClientBuffer 设置默认的 input format;
  3. 调用 onInputBufferAvailable 将消息回传给 MediaCodec;

这里有一点很容易让人忽略,为什么调用onInputBufferAvailable时,传递的index要用std::distance来计算呢?

std::distance应该计算的是 ACodecBufferChannel::BufferInfo 在数组中的位置,也就是数组索引,所以传递给 MediaCodec 用的 index 其实是 ACodecBufferChannel 的buffer数组索引,它和buffer id是两码事。

2、BufferCallback::onInputBufferAvailable

void BufferCallback::onInputBufferAvailable(size_t index, const sp<MediaCodecBuffer> &buffer) {sp<AMessage> notify(mNotify->dup());notify->setInt32("what", kWhatFillThisBuffer);notify->setSize("index", index);notify->setObject("buffer", buffer);notify->post();
}

onInputBufferAvailable 会把回传的数组索引 以及 MediaCodecBuffer 重新封装到 AMessage中,最后交由 MediaCodec Handler 处理。

2、kWhatFillThisBuffer

                case kWhatFillThisBuffer:{// 将拿到的 MediaCodec 加入到列表当中/* size_t index = */updateBuffers(kPortIndexInput, msg);// 如果正在处理以下事件,则直接将所有的buffer返回给Codecif (mState == FLUSHING|| mState == STOPPING|| mState == RELEASING) {returnBuffersToCodecOnPort(kPortIndexInput);break;}// 如果 csd buffer 不为空,则先写入csd bufferif (!mCSD.empty()) {ssize_t index = dequeuePortBuffer(kPortIndexInput);CHECK_GE(index, 0);// If codec specific data had been specified as// part of the format in the call to configure and// if there's more csd left, we submit it here// clients only get access to input buffers once// this data has been exhausted.status_t err = queueCSDInputBuffer(index);if (err != OK) {ALOGE("queueCSDInputBuffer failed w/ error %d",err);setStickyError(err);postActivityNotificationIfPossible();cancelPendingDequeueOperations();}break;}// CCodec 使用的,暂时略过if (!mLeftover.empty()) {ssize_t index = dequeuePortBuffer(kPortIndexInput);CHECK_GE(index, 0);status_t err = handleLeftover(index);if (err != OK) {setStickyError(err);postActivityNotificationIfPossible();cancelPendingDequeueOperations();}break;}// 如果使用的是异步模式if (mFlags & kFlagIsAsync) {// 并且输入不是surface,输入是surface的情况我们暂时不看if (!mHaveInputSurface) {// 状态是 flushed,则暂时不处理该input buffer,等待重新启动if (mState == FLUSHED) {mHavePendingInputBuffers = true;} else {// 调用onInputBufferAvailable将input buffer返回给上层onInputBufferAvailable();}}} else if (mFlags & kFlagDequeueInputPending) {// 如果是同步模式,并且处在阻塞等待的状态,收到input buffer,发送消息结束阻塞CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));// 增加阻塞等待计数,使得kWhatDequeueInputTimedOut无效++mDequeueInputTimeoutGeneration;mFlags &= ~kFlagDequeueInputPending;mDequeueInputReplyID = 0;} else {postActivityNotificationIfPossible();}break;}

kWhatFillThisBuffer 消息处理流程中的内容稍有一点多,我们有选择的对内容进行展开:

  • 将拿到的 MediaCodec 加入到列表当中,这里的列表有两个,一个是用来记录 ACodecBufferChannel 中所有的 buffer(分为input / output 两个数组)mPortBuffers;第二个列表是用来记录可用的input/output buffer的 mAvailPortBuffers,同样分为input / output 两个数组,这里面记录的是可用的索引。
size_t MediaCodec::updateBuffers(int32_t portIndex, const sp<AMessage> &msg) {CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);size_t index;CHECK(msg->findSize("index", &index));sp<RefBase> obj;CHECK(msg->findObject("buffer", &obj));sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());{Mutex::Autolock al(mBufferLock);if (mPortBuffers[portIndex].size() <= index) {mPortBuffers[portIndex].resize(align(index + 1, kNumBuffersAlign));}mPortBuffers[portIndex][index].mData = buffer;}mAvailPortBuffers[portIndex].push_back(index);return index;
}
  • ==这里有一点非常重要,如果没看懂很容易对接下来的内容产生疑惑:==将传来的MediaCodecBuffer记录到 mPortBuffers 中时,这里会有一个隐式转换,用 MediaCodecBuffer 创建了一个 MediaCodec::BufferInfo,好家伙,人手一个bufferinfo是吧。
    struct BufferInfo {BufferInfo();sp<MediaCodecBuffer> mData;bool mOwnedByClient;};MediaCodec::BufferInfo::BufferInfo() : mOwnedByClient(false) {}

用一张图表示一下 buffer之间的关系:
请添加图片描述

  • 如果正在处理release/stop/release,则直接将所有的buffer返回给Codec,MediaCodec 不会持有任何 buffer;
void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);Mutex::Autolock al(mBufferLock);if (portIndex == kPortIndexInput) {mLeftover.clear();}for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {BufferInfo *info = &mPortBuffers[portIndex][i];if (info->mData != nullptr) {sp<MediaCodecBuffer> buffer = info->mData;if (isReclaim && info->mOwnedByClient) {ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",portIndex, i);} else {info->mOwnedByClient = false;info->mData.clear();}mBufferChannel->discardBuffer(buffer);}}mAvailPortBuffers[portIndex].clear();
}
  • returnBuffersToCodecOnPort 会遍历所有 MediaCodec 记录的 BufferChannel 中的 buffer,这里之所以要遍历记录的buffer,是因为可能刚开始解码,还有buffer没有传给MediaCodec流程就结束了;MediaCodecBuffer 的 mOwnedByClient 指的是 buffer 是否被上层 app 所持有;
http://www.yayakq.cn/news/955039/

相关文章:

  • 有哪些在线做图的网站百度招聘电话
  • 建站目的wordpress怎么切换中文
  • 建站什么程序好亚马逊电商现在好做吗
  • 山东网站建设最便宜佛山市seo推广
  • 网站服务是什么做微站比较好的网站
  • 建设项目环保试生产网站哪里有营销型网站公司
  • 网站域名注册证书查询搭建wordpress服务器
  • 网站建设需求模版优帮云查询数据云查询
  • 企业网站建站源码免费网站建设专业的公司
  • 网站用ai做还是ps深圳尼高品牌设计有限公司
  • 宁波网站推广报价外卖小程序源码
  • 四川省建设资格注册中心网站自己做的网站如何赚钱
  • 长沙营销型网站制作费用在百度怎么建自己的网站
  • 学校网站制作代码恋月wordpress
  • 如何做好网站推广黔东南州两学一做教育网站
  • 中国十大设计素材网站中国电信企业邮箱登录入口
  • 一个企业做网站的意义电工证如何做的相关网站能查到
  • 会展免费网站模板住房和城乡建设部官网进行查询
  • 建一个网站模板网wordpress登录后台
  • 网站备案需要关闭网站吗网络营销有哪些模式
  • 网站源码在线下载潍坊网站制作小程序
  • 有没有代做毕业设计的网站网站规划与网页设计第四版电子书
  • 做网站一般做几个尺寸wordpress悬浮搜索
  • 上海网站优化加盟帝国视频网站模板
  • 做个卖车票的网站怎么做app软件开发成本
  • 电脑上制作网站的软件网站建设优惠
  • 营销型网站建设的意义北京网站建设优化学校
  • 山西网站建设服务公司深圳龙华天气
  • 网站建设企业文化wordpress 代码大全
  • 男女做暧暧网站免费做汽车配件网站的公司