SurfaceTexture的Buffer入队流程

Figure 1queueBuffer流程

1. 在AWesomePlayer的Render中将解码后的Buf通过ANativeWindow接口通知SurfaceTextureClient

struct AwesomeNativeWindowRenderer : public AwesomeRenderer {

virtual void render(MediaBuffer *buffer) {

int64_t timeUs;

CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));

native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);

status_t err = mNativeWindow->queueBuffer(

mNativeWindow.get(), buffer->graphicBuffer().get());

 

}

}

进入到SurfaceTextureClient的queueBuffer(),这里的工作主要有:

1) 更新timestamp,如果没有,则用系统时间

2) 根据Buffer地址从slots中取出Buffer的序号

3) 将序号以及时间戳、以及其它信息通过Binder通信发送给SurfaceTexture。

int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {

LOGV("SurfaceTextureClient::queueBuffer");

Mutex::Autolock lock(mMutex);

int64_t timestamp;

if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {

timestamp = systemTime(SYSTEM_TIME_MONOTONIC);

LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",

timestamp / 1000000.f);

} else {

timestamp = mTimestamp;

}

int i = getSlotFromBufferLocked(buffer);

status_t err = mSurfaceTexture->queueBuffer(i, timestamp,

&mDefaultWidth, &mDefaultHeight, &mTransformHint);

return err;

}

2. 在SurfaceFlinger进程中,本地端的SurfaceTexture接收到Binder消息,并进入queueBuffer函数。主要做以下工作:

1) 根据传入的int buf从slots中找出相应的Buffer,并更新此buffer的相关信息。

2)发信号mDequeueCondition.signal(),用作通知等待者

3) 通知监听者,onFrameAvailable有帧到达

status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,

uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {

ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);

 

sp<FrameAvailableListener> listener;

 

{ // scope for the lock

Mutex::Autolock lock(mMutex);

//一些参数检查

 

if (mSynchronousMode) {

// In synchronous mode we queue all buffers in a FIFO.

mQueue.push_back(buf);

 

// Synchronous mode always signals that an additional frame should

// be consumed.

listener = mFrameAvailableListener;

} else {

// In asynchronous mode we only keep the most recent buffer.

if (mQueue.empty()) {

mQueue.push_back(buf);

 

// Asynchronous mode only signals that a frame should be

// consumed if no previous frame was pending. If a frame were

// pending then the consumer would have already been notified.

listener = mFrameAvailableListener;

} else {

Fifo::iterator front(mQueue.begin());

// buffer currently queued is freed

mSlots[*front].mBufferState = BufferSlot::FREE;

// and we record the new buffer index in the queued list

*front = buf;

}

}

 

mSlots[buf].mBufferState = BufferSlot::QUEUED;

mSlots[buf].mCrop = mNextCrop;

mSlots[buf].mTransform = mNextTransform;

mSlots[buf].mScalingMode = mNextScalingMode;

mSlots[buf].mTimestamp = timestamp;

mFrameCounter++;

mSlots[buf].mFrameNumber = mFrameCounter;

 

mDequeueCondition.signal();

 

*outWidth = mDefaultWidth;

*outHeight = mDefaultHeight;

*outTransform = 0;

} // scope for the lock

 

// call back without lock held

if (listener != 0) {

listener->onFrameAvailable();

}

return OK;

}

在Layer中,第一次引用时会创建SurfaceTexture,并实现FrameAvailableListener

void Layer::onFirstRef()

{

LayerBaseClient::onFirstRef();

 

struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {

FrameQueuedListener(Layer* layer) : mLayer(layer) { }

private:

wp<Layer> mLayer;

virtual void onFrameAvailable() {

sp<Layer> that(mLayer.promote());

if (that != 0) {

that->onFrameQueued();

}

}

};

mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);

mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));

mSurfaceTexture->setSynchronousMode(true);

mSurfaceTexture->setBufferCountServer(2);

}

控制流进入Layer:onFrameQueued()函数,最后调用SurfaceFlinger的事件函数,通知其新事件。

void Layer::onFrameQueued() {

android_atomic_inc(&mQueuedFrames);

mFlinger->signalEvent();

}

3. 在SurfaceFlinger中获得事件,进入主循环处理事件

bool SurfaceFlinger::threadLoop()

{

waitForEvent();

// post surfaces (if needed)

handlePageFlip();//设置刚入队的Buffer为当前激活的Buffer

handleRepaint();//将当前激活的Buffer地址送给硬件叠加层,进行叠加

 

在lockPageFlip函数中遍历每一层设置当前激活的Buffer

bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)

{

bool recomputeVisibleRegions = false;

size_t count = currentLayers.size();

sp<LayerBase> const* layers = currentLayers.array();

for (size_t i=0 ; i<count ; i++) {

const sp<LayerBase>& layer(layers[i]);

layer->lockPageFlip(recomputeVisibleRegions);

}

return recomputeVisibleRegions;

}

对每个Layer将当前Buffer设置为激活Buffer

void Layer::lockPageFlip(bool& recomputeVisibleRegions)

{

// update the active buffer

mActiveBuffer = mSurfaceTexture->getCurrentBuffer();

 

在handleRepaint()中调用setupHardwareComposer建立叠加层

setupHardwareComposer(mDirtyRegion);

void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut)

{

/*

* update the per-frame h/w composer data for each layer

* and build the transparent region of the FB

*/

for (size_t i=0 ; i<count ; i++) {

const sp<LayerBase>& layer(layers[i]);

layer->setPerFrameData(&cur[i]);

}

}

 

将当前激活的buffer设置到 handware composer中进行叠加

void Layer::setPerFrameData(hwc_layer_t* hwcl) {

const sp<GraphicBuffer>& buffer(mActiveBuffer);

if (buffer == NULL) {

// this can happen if the client never drew into this layer yet,

// or if we ran out of memory. In that case, don't let

// HWC handle it.

hwcl->flags |= HWC_SKIP_LAYER;

hwcl->handle = NULL;

} else {

hwcl->handle = buffer->handle;

}

}

 

 

转载于:https://www.cnblogs.com/zhgyee/archive/2011/12/27/2302709.html

解密Android图形管线:BufferQueue工作模式与Gralloc内存分配的22个优化技巧 本文深入剖析Android图形管线中BufferQueue的三种核心工作模式(同步、非阻塞、丢弃)的实战选型逻辑,并结合Gralloc内存分配器的底层原理,提供了22个从理论到实践的深度优化技巧。文章旨在帮助架构师和资深开发者解决界面卡顿、内存拷贝等性能瓶颈,通过优化缓冲区管理与内存访问策略,实现高帧率游戏、实时视频处理等场景下的极致图形渲染性能。 阅读详情

相关推荐

深入解析Android相机架构:从Camera2 API到HAL与BufferQueue的底层原理

在移动应用开发中,相机功能是实现图像处理、视频通话和AR等场景的核心组件。其底层架构基于生产者-消费者模型,通过BufferQueue机制管理图像数据流,确保高效传输。相机硬件抽象层(HAL)作为硬件与系统的桥梁,定义了统一的接口标准以屏蔽设备差异,而图像信号处理器(ISP)则负责将原始传感器数据转换为YUV或JPEG格式。理解这套体系对于优化预览流畅度、降低拍照延迟至关重要,尤其在处理多流并发和计算摄影等高级需求时。本文聚焦Android相机体系,剖析Camera2 API的异步状态机设计、Capture

weixin_30321449的博客 342

Android图形显示系统——下层显示3:窗口系统

Android之窗口系统 要点 1.Android窗口系统通过C-S架构和一套Buffer循环机制实现,在保证安全稳定的前提下基本上做到了极致性能(无大块内存拷贝,IPC通信内容最少)。 2.SurfaceFlinger创建Layer,将其中的BufferQueueProducer作为IGraphicBufferProduce...

weixin_34218890的博客 554

Unity低延迟RTMP推流实战:从渲染到编码的优化全解析

视频编码与流媒体传输是实时音视频应用的核心技术。其原理是将原始图像数据通过编码算法压缩,再通过网络协议传输,以实现高效、实时的内容分发。这项技术的价值在于能够平衡画质、带宽与延迟,广泛应用于直播、远程协作、云游戏等场景。其中,低延迟优化是工程实践中的关键挑战,涉及渲染管线、硬件加速与网络传输的协同。本文聚焦于Unity引擎与RTMP协议的结合,通过AsyncGPUReadback实现GPU异步读取,并利用NVENC硬件编码器进行高效处理,为数字孪生、虚拟演播等需要高实时性的3D内容推送提供了可行的解决方案。

weixin_33910460的博客 359

android 解码出来的视频frame数据,是如何一步步的传递到显示端的(使用 GPU offline 合成)

经过一段时间的研究,对android视频解码,直到显示端的整体流程,有了浅薄的理解 这里总结一下,解码出来的视频帧,是怎么一步步走到显示的。 平台: Exynos 4412  android 4.4 1,  Exynos 4412 视频编解码依赖于硬件MFC。  解码出来的数据,不会进行原始数据的搬运。实际传递的是这些解码完数据的物理地址。 2,显示端硬件获得这

WAN8180192的博客 3952

Unity集成FFmpeg:构建高性能自定义视频播放器的架构与优化实践

视频编解码是多媒体处理的核心技术,它通过特定算法对视频数据进行压缩与还原,以平衡存储、传输与画质需求。其原理涉及帧内预测、帧间预测、变换量化及熵编码等环节,旨在高效去除时空冗余。在游戏开发与交互式应用领域,掌握底层解码流程具有重要技术价值,它使开发者能突破通用播放器的限制,实现帧级精准控制、低延迟流处理及跨平台格式兼容。尤其在Unity引擎中,当面对高码率全景视频、多实例播放或WebGL平台兼容性等复杂应用场景时,集成FFmpeg这一开源多媒体框架,通过设计独立解码线程与环形缓冲队列的架构,并结合硬件加速与

weixin_34226706的博客 316

Android平台C++媒体播放器开发:从FFmpeg解码到音视频同步实战

在移动应用开发中,高性能音视频处理是核心技术领域之一,其底层实现通常依赖于C/C++语言以保证执行效率。其核心原理涉及媒体数据的解封装、解码、渲染与同步流程,通过FFmpeg等开源库实现跨格式编解码,结合多线程架构管理数据流。这项技术的工程价值在于能够为短视频、直播、游戏等场景提供稳定高效的播放能力,解决音画同步、低延迟等关键问题。本文以Android平台为例,详细解析如何利用NDK、OpenGL ES和OpenSL ES构建本地播放器,涵盖FFmpeg集成、线程模型设计及音视频同步策略,帮助开发者深入理解

weixin_30918633的博客 416

gstreamer

gstreamer (2010-11-19 10:58:41) 转载 gstreamer介绍Rainbow编码器是基于gstreamer实现的,webkit的video标签使用了gstreamer,gstreamer项目里还有一个rtsp的服务器,gstreamer的应用越来越多,而且它的确是一个不错的东西。最近有几次需要向人家解释gstreamer,发现这样一些观点:gst...

aobo1237的博客 491

AndroidR上关于TextureView的刷新流程

AndroidR上关于TextureView的刷新流程 声明: 本人愚钝,学习内容比较慢也不是很深,写这个博客的文章就是为了记录之前的一些的累积的东西,如果有什么写的不好的请帮忙指出,大家共同学习。 之前由于工作需要修,HWUI的bug,所以不得不看下video + surfacetexture的更新绘制的流程,之前查看网页,也没有太多的关于HWUI的说明,有的也只是大概的流程,但是具体中很多的细节的内容,还是需要不断探索和研究,所以写出来这个总结博客好做个参考。 1. View上层刷新的过程 注:每行开

liwenjie28的博客 3144

Android NativeWindow render 打印输出

1.获取graphicBuffer中的内存; struct AwesomeNativeWindowRenderer : public AwesomeRenderer {     AwesomeNativeWindowRenderer(             const sp &nativeWindow,             int32_t rotationDegrees,in

huangqbio2的专栏 1277

Android 图形架构 之四——图形缓冲区的申请和消费流程及核心类

前言 Android应用的UI显示到Display的过程中,SurfaceFlinger扮演的角色只是“Flinger”,就是定于检查Layer更新,然后计算DirtyRegion,然后将结果推送给底层显示驱动进行显示。 应用层把UI内容 写入到GraphicBuffer,SurfaceFlinger读取数据后 ,合成显示。BufferQueue 是用来管理GraphicBuffer的 一、生产者消费者模型 对GraphicBuffer的管理 使用的是生产者消费者模型,app 产生数据,通知SurfaceF

薛瑄的博客 7690

yersinia -G打不开图形化界面解决方案(曲线救国,实操可行)

附Kali 2021 VMware懒人版,已完成汉化,更新源,并已经安装yersinia。ping 114.114.114.114也不通,接着ifconfig发现 IP地址有的,然后手动配置了IP地址,发现还是Ping不通114.11.4.114.114,然后输入。更新源后,报错源无法解析,同时ping www.baidu.com也不通,那可能是DNS存在问题,更新一下DNS服务器。百度找了很久,有个回答比较接近,但一一尝试了几遍,还是无解,解决不了呀!•(2)Yersinia编译的时候,要选择gtk。

weilandeyongheng的专栏 4170

Androi4.0 SurfaceTexture的Buffer入队流程

SurfaceTexture的Buffer入队流程 Figure 1queueBuffer流程 1. 在AWesomePlayer的Render中将解码后的Buf通过ANativeWindow接口通知SurfaceTextureClient struct AwesomeNativeWindowRenderer : public AwesomeRenderer

martin的专栏 1676

应用软件——Altium Designer 19 Gerber/坐标文件

如何输出Gerber文件 步骤如下: 打开需要输出的PCB文件 2. 设置原点坐标 3. 打开Gerber Files 选项,File–>Fabrication Opuputs–>Gerber Files。 4. General参数设置。 用于指定输出Gerber文件中使用的单位(Units)和格式(Format)。单位可以是公制(Millimeters)和英制(Inches);格式栏中2:3,2:4,2:5代表文件中使用的不同数据精度,其中2:3表示数据含2位整数3位小数;相应的,另外两个分

染血黑兔的博客 7203

Android4.0显示SurfaceTextureClient queuebuffer 队列

ICS Overlay主要流程 只关注到Overlay的主要过程,对FB未做分析,待以后完善。 posted @ 2012-01-09 22:49 yeeman 阅读(191) 评论(0) 编辑 2011年12月27日 SurfaceTexture的Buffer入队流程 Figure 1queueBuffer流程 1. 在A

yiaic的专栏 5066

C#上位机与MES系统数据对接:从协议选型到安全传输的实战解析

本文详细解析了C#上位机与MES系统数据对接的全过程,从协议选型到安全传输的实战技巧。针对工业互联网场景下的数据对接挑战,提供了RESTful API、MQTT和OPC UA等协议的选型建议,并分享了健壮性设计、异常处理和安全传输的实用代码示例,帮助开发者高效实现数据上传与系统集成。

weixin_30566063的博客 105

基于强化学习方法的PID参数整定

前言 PID控制器在工业界应用非常广泛,但是PID的参数调节一般需要人工根据经验法来试。对于有经验的工程师来说,一般试几次就可以获得满足调节的参数。然而对于新手工程师却很难确定一套比较好的参数。 这里我们采用强化学习的方法来调节PID参数。 这个例子展示了如何使用双延迟深度确定性策略梯度(TD3:twin-delayed deep deterministic policy gradient)强化学习算法来调整PI控制器。整定控制器的性能与使用Control System Tuner app整定的控制器的性能

weixin_42188287的博客 2万+

android openmax&surfaceflinger

ICS Overlay主要流程   ICS Overlay主要流程 只关注到Overlay的主要过程,对FB未做分析,待以后完善。 SurfaceTexture的Buffer入队流程   Figure 1queueBuffer流程 1. 在AWesomePlayer的Render中将解码后的Buf通过ANativeWindow接口通知SurfaceT

brucexu1978的专栏 3583

在Simulink中实现基于深度强化学习的控制算法仿真建模

通过上述步骤,你可以在Simulink中实现基于深度强化学习的控制算法仿真建模。这种方法适用于许多复杂的控制问题,尤其是当传统控制方法难以找到有效解决方案时。随着经验的积累,你可以进一步探索不同的深度强化学习算法及其变种,以适应更广泛的应用场景。此外,还可以结合其他先进技术(如迁移学习、多智能体协作等),提升模型的表现能力。

amy_mhd的博客 415

android双缓冲技术,深入浅出Android BufferQueue

1. 背景对业务开发来说,无法接触到BufferQueue,甚至不知道BufferQueue是什么东西。对系统来说,BufferQueue是很重要的传递数据的组件,Android显示系统依赖于BufferQueue,只要显示内容到“屏幕”(此处指抽象的屏幕,有时候还可以包含编码器),就一定需要用到BufferQueue,可以说在显示/播放器相关的领悟中,BufferQueue无处不在。即使直接调用...

weixin_39539761的博客 1835

【全志V821_FoxPi】6-3 GC2083 MIPI摄像头适配

本文介绍了在全志V821芯片上适配GC2083 MIPI摄像头的方案。GC2083是一款支持1080P@30fps的高性能CMOS图像传感器,采用MIPI CSI-2接口,具有低功耗特性。文章详细列出了传感器的技术参数和工作电压要求,并提供了设备树配置示例,包括CSI接口、ISP处理单元和传感器节点的具体设置。通过快速配置命令one_gc2083_sensor或手动修改设备树即可启用该摄像头模组,适用于IPC等对图像质量有要求的嵌入式应用场景。

第四维度的博客 1928

手把手教你双目测距理论及生成视差图,深度图,点云图像

Stereo Vision, 也叫双目立体视觉,它的研究可以帮助我们更好的理解人类的双眼是如何进行深度感知的。双目视觉在许多领域得到了应用,例如城市三维重建、3D模型构建(如kinect fusion)、视角合成、3D跟踪、机器人导航(自动驾驶)、人类运动捕捉(Microsoft Kinect)等等。双目测距也属于双目立体视觉的一个应用领域,双目测距的基本原理主要是三角测量原理,即通过视差来判定物体的远近。

qq_53545309的博客 2280

android 显示系统

ICS Overlay主要流程   ICS Overlay主要流程 只关注到Overlay的主要过程,对FB未做分析,待以后完善。 SurfaceTexture的Buffer入队流程   Figure 1queueBuffer流程 1. 在AWesomePlayer的Render中将解码后的Buf通过ANativeWindow接口通知SurfaceT

ekenlinbing的专栏 2905

Android插件化和组件化面试题及参考答案

如何使用 Gradle 来管理 Android 项目中的模块依赖? Gradle 是一个强大的构建工具,在 Android 项目中管理模块依赖主要通过以下方式。 首先,在项目的根目录下的 build.gradle 文件中,需要配置仓库。一般会添加如 Google 的 Maven 仓库和 JCenter 等,例如在 repositories 部分添加: repositories { google() jcenter() } 对于模块依赖,在每个模块(例如 app

大模型大数据攻城狮的专栏 1185

Android camera Hal 杂谈

camera id 的生成是更具在v4l2 camera hal 文件中遍历/dev下面video节点,并通过capture能力校验,并对同相同格式的流去重,而得到的。在camera hal 生成camera id时,会自动创建关于camera id 对应节点的v4l2 camera 和v4l2 wrapper 这两个类。由这两个类对camera的buffer轮转进行操作。

meiyoumajia的博客 505

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

上一篇: OpenMax图示
下一篇: ICS Overlay主要流程
aobo1237
博客等级 码龄11年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值