我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android SurfaceTexture说明

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android SurfaceTexture说明

what

SurfaceTexture用来捕获视频流中的图像帧,视频流可以是相机预览或者是视频解码数据。

里边承接图像数据的也是GraphicBuffer, GLConsumer 作为其BufferQueue的消费方,取得数据后可以通过eglImage挂到opengles texture 里边对其做纹理采样。

how

就用法来讲,主要就是有数据后BufferQueue Producer在queueBuffer时 回调应用的onFrameAvailable(),应用自己决定是否、何时调用updateTetxtureImage()去做纹理绑定、采样

BufferQueue:

native层,在SurfaceTexture native对象 创建前创建了生产者和消费者;

消费者作为其构造函数传入给SurfaceTexture;

生产者作为全局变量保存,同时也保存在SurfaceTexture java 对象的mProducer里边 ;

GraphicBuffer的获取

生产方:通过 SurfaceTexture_getProducer()获取到BufferQueueProducer ;

消费方:SurfaceTexture 在UpdateTexImage()时去acquireBuffer

相关技术点

SurfaceView

what

只拥有BufferQueue的生产端,消费端为SurfaceFlinger,渲染后必须上屏。

TextureView

what

由于其里边拥有SurfaceTexture, 可用于离屏渲染,拥有BufferQueue的生产端和消费端,

生产端可为camera、MediaCodec、任意render 模块, 可以跨进程(底层是GraphicBuffer嘛),消费端为SurfaceTexture GLConsumer, 可对图像做二次处理。

YUV

why

一般情况下SurfaceTexture承载的数据都是YUV类型(来自mediacodec、camera),有必要简单说下。

what

一种图像数据编码格式,常用的为YUV420,俗称I420,

各格式说明:

4:4 ,完全取样

2:2 ,2:1水平取样,垂直完全采样

2:0 ,2:1水平取样,垂直2:1采样

1:1 ,4:1水平取样,垂直完全采样

 格式 packed,planar、semi-planar

packed:不带后缀,如YUV420,数据以逐像素为单位排列,如

planar:带后缀P,如YUV420P,Y、U、V 分开存储,如

 

semi-planar:带后缀SP,如YUV420SP,UV交叉存储,与Y分开存储,如

这边可能要注意,排列可能为YYY.....UVUV, 或YYY...VUVU,即UV的第一个值到底是U还是V,

前者准确点叫YUV,后者叫YVU,又如 NV12、NV21 哈哈哈是不是有点迷糊了😜,

rgb与yuv的转换

一般可以用gpu,做个纹理采样去转,若gpu不支持硬件转换,需自己写shader;

有的gpu硬件支持直接转,如高通平台adreno,SurfaceTexture.updateTexImage()把YUV 图像数据挂上后,shader里边通过samplerExternal2D 采出来就是RGB数据。

android 系统 + 高通平台,如何获取不同YUV数据类型的GraphicBuffer大小,

接口:hardware/qcom/display/gralloc/gr_utils.cpp:: GetBufferSizeAndDimensions()

对于抓帧工具而言,将GraphicBuffer lock后,获取size,buffer里边分为Y、UV数据块,若是ubwc类型,头部还带meta数据,分块读取保存比较麻烦,由于这些分块数据在内存里边连续存储,所以可以直接整大块读取保存。

//notes: 该功能只有vendor才有能力开发,因为GraphicBuffer接口不对开发者开放,开放的AHardwareBuffer 相关的接口也起不了什么作用。

参考 kernel/msm-4.19/include/uapi/media/msm_media_info.h

EGLImage

what

 EGLImageKHR是EGL定义的一种专门用于共享2D图像数据的扩展格式,它可以在EGL的各种client api之间共享gpu侧数据(如OpenGL,OpenVG),也可称之为direct texture(Using direct textures on Android), 当我们需要对一块GraphicBuffer数据做纹理采样就可以使用EGLImage,所以其底层数据载体当然为GraphicBuffer。

对于Android系统,既然共享,又用了GraphicBuffer,那么就是不仅可以在不同线程间共享,还可以跨进程共享。

适用场景 : 需要经常更新纹理数据的场合,比如逐帧更新;

                   对camera、mediacode的输出做采样处理;

                   跨进程、跨线程共享纹理;

数据类型: 由于做为扩展给gpu厂家去自行支持, EGLImage里边可以存的数据其格式可以是opengles标准不支持的, 具体看厂家自己去实现,理论上可以存各种数据, 但一般在高通平台主要也就RGB和YUV,再加上是否带UBWC压缩。

why

性能优化,能跨进程、跨线程在gpu 侧直接共享纹理数据,减少拷贝次数;

在跨进程、跨线程共享texture上统一定义了标准接口与用法。

how

底层通过GraphicBuffer 实现(基于EGL_ANDROID_image_native_buffer 扩展),

所以原理上其实EGLImage只是一种接口封装,对GraphicBuffer的封装,将其封装成texture,

eglCreateImageKHR()glBindTexture()glEGLImageTargetTexture2DOES()//glDrawXXX()eglDestroyImageKHR()

关于EGL_ANDROID_image_native_buffer 扩展

说明:

This extension enables using an Android window buffer (struct

ANativeWindowBuffer) as an EGLImage source.

该扩展使得可以将ANativeWindowBuffer 作为EGLImage的输入源

限制 :

If is EGL_NATIVE_BUFFER_ANDROID, must be a valid display,

must be EGL_NO_CONTEXT, must be a pointer to a valid

ANativeWindowBuffer object (cast into the type EGLClientBuffer), and

attributes other than EGL_IMAGE_PRESERVED_KHR are ignored."

即  对于EGLImageKHR eglCreateImageKHR( EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)

  dpy必须合法,上下文必须为EGL_NO_CONTEXT,

  buffer输入源必须为ANativeWindowBuffer,GraphicBuffer通过getNativeBuffer()类型转换而来。

引用自: frameworks/native/opengl/specs/EGL_ANDROID_image_native_buffer.txt

bind texture

可以通过glEGLImageTargetTexture2DOES() 与GL_TEXTURE_2D、GL_TEXTURE_EXTERNAL_OES绑定,

eglImage和eglImageKHR

带KHR表示khronos 加的扩展,整体用法在Android上应该都差不多,一般都用带KHR后缀的,

具体细节倒没理得那么清😂。

EGLImage和EGLSurface

相同点: 底层都是GraphicBuffer,都是可以作为RenderTarget或texture使用;

不同点:创建的接口不同,eglCreateWindowSurface()、eglCreatePixmapSurface()、eglCreatePbufferSurface()、eglCreatePbufferFromClientBuffer(),eglCreateImageKHR()

             用法不同,EGLImage上下文无关,可以跨进程、线程共享、

              EGLSurface 上下文绑定。

GraphicBuffer 与eglImage 关系

等我看看freedreno代码先。。。

进程间共享图像数据方式

GPU侧:GraphicBuffer + EGLImage + oes texture;

CPU侧:共享内存;

共进程,不同opengl es线程共享纹理方式

(1)share context后,共享texture;

(2)EGLImage;

GL_TEXTURE_EXTERNAL_OES

what

俗称oes texture, 专门为EGLImage而加的texute类型,对于装有YUV数据的EGLImage,EGLImage一般通过挂到GL_TEXTURE_EXTERNAL_OES去做处理;

shader里边的sampler类型: samplerExternalOES;

如果是采样YUV数据类型的纹理,会自动转成RGB(GPU厂商需要实现这个功能),

Sampling an external texture will return an RGBA vector in the same colorspace as the source image. If the source image is stored in YUV (or some other basis) then the YUV values will be transformed to RGB values.

why

为何不直接挂到GL_TEXTURE_2D处理呢? 为什么要加上这个扩展?

这块理的不是特别清楚,相关资料都没讲得那么清,以下是一些整理+自己理解

来自:frameworks/base/libs/hwui/surfacetexture/SurfaceTexture.h

即,除非需要从fbo拷贝数据到该texture挂的eglimage,才会将该eglImage挂到GL_TEXTURE_2D上,

而咱们一般都是对这块eglimage做采样嘛,所以要挂到GL_TEXTURE_EXTERNAL_OES上。

(感觉有点牵强,可以先接着往下看)

(1)外部纹理,即gpu侧图像数据来自其他上下文,对其采样时,目前的GL_TEXTURE2D不能挂,需要用eglimage挂到GL_TEXTURE_EXTERNAL_OES,

(2)硬件对YUV转RGB的支持

对于装YUV数据格式的EGLImage,一般GPU也不支持硬件YUV转RGB,若直接挂到GL_TEXTURE_2D做采样,需要自己在shader做RGB转换;

TEXTURE_EXTERNAL_OES 作为扩展,当GPU支持硬件YUV转RGB时,就会通过支持该扩展来表明。

how

怎么把gpu这个功能用上呢?

使用TEXTURE_EXTERNAL_OES,把EGLImage挂上去。

eglCreateImageKHR()glBindTexture(TEXTURE_EXTERNAL_OES, textureId)//eglImage 装YUV格式数据glEGLImageTargetTexture2DOES(TEXTURE_EXTERNAL_OES, eglImage)//glDrawXXX()eglDestroyImageKHR()

通过samplerExternalOES类型的采样器,从YUV数据类型的TEXTURE_EXTERNAL_OES里边采样出来的数据,就是RGB,gpu做了转换,无需shader去转,eg:

            //声明使用该扩展            "#extension GL_OES_EGL_image_external : require\n" +            "precision mediump float;\n" +            //指定sampler类型            "uniform samplerExternalOES tex_sampler_0;\n" +            "varying vec2 v_texcoord;\n" +            "void main() {\n" +            "  gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" +            "}\n";

跨线程使用

准确的说是跨拥有不同opengles context的线程

attachToGLContext()detachToGLContext()//通过这2个接口跨线context

代码分析

 主要代码流程

SurfaceTexture.java -->base/core/jni/android/graphics/SurfaceTexture.cpp-->base/libs/hwui/surfacetexture/SurfaceTexture.cpp--> EGLConsumer.cpp --> opengl es

SurfaceTexture.java:

主要是做类的作用、用法说明,对每个接口做了详细的说明,没什么逻辑,都是直接转调native 接口,

base/core/jni/android/graphics/SurfaceTexture.cpp:

实现SurfaceTexture.jave 的jni接口,里边没什么具体逻辑, 主要是承接 SurfaceTexture.jave 和base/libs/hwui/surfacetexture/SurfaceTexture.cpp

base/libs/hwui/surfacetexture/SurfaceTexture.cpp:

对SurfaceTexture.java的实现,主要是GraphicBuffer 的处理

EGLConsumer.cpp :

opengl es接口的封装,主要做了 基于acquireBuffer()出来的GraphicBuffer创建eglImageKHR, 将其挂到指定的oes texture 上

时序图

注册SurfaceTexture.OnFrameAvailableListener:

 生产者生产完一块GraphicBuffer 数据后回调onFrameAvailable() 流程:

UpdateTextureImage(),消费者消费该GrapicBuffer,将其挂到opengles texture做纹理采样流程:

参考

https://blog.csdn.net/xkuzhang/article/details/115423061

https://paaatrick.com/2020-01-26-yuv-pixel-formats/

https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_image_base.txt

https://registry.khronos.org/OpenGL/extensions/OES/OES_EGL_image_external.txt

http://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt

来源地址:https://blog.csdn.net/goodnight1994/article/details/129379585

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android SurfaceTexture说明

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android ContentResolver使用说明

Android是如何实现应用程序之间数据共享的?一个应用程序可以将自己的数据完全暴露出去,外界更本看不到,也不用看到这个应用程序暴露的数据是如何存储的,或者是使用数据库还是使用文件,还是通过网上获得,这些一切都不重要,重要的是外界可以通过这
2022-06-06

Android ListView UI组件使用说明

一、ListView 该组件是android中最常用的一个UI组件,用于实现在屏幕上显示多个内容,以便于我们用手指来回翻转。 先在layout中进行布局我们的组件2022-06-06

Android中各级目录的作用说明

Android中各级目录的作用 1>目录结构 1.根目录: src目录---存放源代码文件 gen目录---ADT插件生成的文件,(自动生成) assets目录---存放资源文件目录,不会在R.java中生成ID res目录---存放
2022-06-06

Android 解析JSON对象及实例说明

JSON是一种轻量级的对象,数据体积小,方便传输,易于解析! 首先新建一个类工具类JsonUtil,用于获取请求返回的数据 代码如下:public class JsonUtil { private static final String T
2022-06-06

Android布局中gravity与layout_gravity属性说明

这篇文章主要介绍了Android布局中gravity与layout_gravity属性说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-17

Android pdf viewer在android studio应用问题说明详解

之前一直是做.NET开发的,最近需要弄一个新闻app,能力有限,只能借助HTML5 WebAPP+android studio来完成这项工作。 android studio主要用WebView来加载发布好的WebApp,打包生产APP。
2022-06-06

Android音频可视化开发案例说明

Android 调用自带的录制音频程序 Android中有自带的音频录制程序,我们可以通过指定一个Action MediaStore.Audio.Media.RECORD_SOUND_ACTION的Intent来 启动它就可以了。然后在on
2022-06-06

Android中数据库升级onUpgrade方法说明

Andoird的SQLiteOpenHelper类中有一个onUpgrade方法。帮助文档中只是说当数据库升级时该方法被触发。经过实践,解决了我一连串的疑问:1. 帮助文档里说的“数据库升级”是指什么?你开发了一个程
2022-06-06

Android.bp文件说明

一、说明 Android.bp是安卓系统,Soong构建系统使用的配置文件。具体描述可以查看官方描述; 关于Soong也可以看下这篇网上的文章; 这里关于Android.bp文件的说明谷歌官方给出参考,仅用于快速查看,没有进行翻译,详细可以
2023-08-30

MySql变量说明

1 #变量 2 12 #一、系统变量 13 /* 14 说明:变量由系统定义,不是用户定义
MySql变量说明
2018-05-23

window.dialogArguments 使用说明

window.dialogArguments 使用说明,需要的朋友可以参考下。
2022-11-21

Persistence.xml 配置说明

persistence.xml是Java Persistence API(JPA)中用于配置持久化单元(Persistence Unit)的文件。在persistence.xml中,可以配置以下内容:1. 持久化单元的名称(name):用于
2023-09-15

Android Eclipse 注释模板的使用(图文说明)

1、设置的入口,我我们可以在下图所示的地方个性化我们自己的代码风格2、文件(Files)注释标签代码如下:/* * @Title: ${file_name} * @Copyright: XXX Co., Ltd. Copyright
2022-06-06

怎样实现android http-post方法实例说明

代码如下: package com.hl; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录