Android解码输出yuv,Android OpenGLES2.0 直接导出YUV420数据

Android OpenGLES2.0中提供的glReadPixels方法提供的格式只有RGB的几种格式,但是这并不妨碍我们导出YUV格式的数据,因为不管是RGBA还是YUV,都不是glReadPixels方法关心的,它关心的其实是每个色彩分量占多少位。可以看到glReadPixels提供的导出格式有RGBA、RGB等,却不会在提供了RGBA的导出格式后又提供ABGR、ARGB这样的导出格式,就是这个道理了。

获取YUV420的方案

如果我们要做的工作只是处理视频图像,然后再编码,我们无需这一步,可以直接利用MediaCodec+Surface编码,效率比导出YUV来编码更高,可以参考我的上一篇博客Android利用硬解硬编和OpenGLES来高效的处理MP4视频。但是我们需要对图像进行处理,然后传输的时候,就要考虑导出YUV数据了。利用OpenGLES2.0 处理完图像后,获取YUV数据的方案大致分为以下几种:

glReadPixels 获取RGB的数据,然后利用libyuv获取其他方式将RGB转换成YUV420

渲染三次,将图像分别渲染为Y平面,U平面,V平面,每次渲染后就glReadPixels得到YUV420

将图像渲染成YUV444导出,然后利用CPU将YUV444转换成YUV420

将图像渲染成YUV420导出

(注:异步读取的问题暂时先不讨论)

方案1可以算是“传统”方法,毕竟RGB是GLES2.0字面上就支持的格式,它需要读取的数据大小是width*height*3,而且还有一步CPU中RGB转YUV的处理过程。速度真是不敢恭维,利用几款手机测试,368*640大小的图像,GPU处理&glReadPixels(注:glReadPixels会等待GPU处理当前图像完成)读取时间大概为16-24ms,转换5-12ms。

方案2方案3,我还没有试过,不过我心里对这两个方案是比较抵触的,如果方案4确实行不通,我不介意选择方案3,方案2渲染3次,readPixels3次不得不说是一个比较糟糕的方案。

方案4数据大小为width*height*3/2,而且也不需要CPU处理,实现之前唯一的担心就是GPU中处理起来太麻烦,会耗时比较长。最后用几款手机及测试,368*640大小的图像,GPU处理&glReadPixels时间为12-20ms。这个时间还是比较可观的。

导出算法

之前有在CPU中实现过RGBA转YUV&#x

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 中使用 OpenGL ES 2.0 和 C/C++ 实现使用 MediaCodec 解码 MP4 视频格式并将其转换为 RGB 图像,需要完成以下步骤: 1. 创建 Android 应用程序并引入必要的库文件 在 Android Studio 中创建一个新的 Android 应用程序,并在 build.gradle 文件中添加以下库文件的引用: ``` // For decoding MP4 video format implementation 'com.google.android.exoplayer:exoplayer-core:2.X.X' implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X' // For using OpenGL ES in Android implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' // For using C/C++ in Android implementation 'com.android.support:support-compat:28.0.0' implementation 'com.android.support:support-core-utils:28.0.0' implementation 'com.android.support:support-annotations:28.0.0' implementation 'com.android.support:support-core-ui:28.0.0' // For using MediaCodec in Android implementation 'com.android.support:support-media-compat:28.0.0' ``` 2. 创建 OpenGL 上下文并加载着色器程序 在 C/C++ 中使用 OpenGL ES 2.0,需要创建一个 OpenGL 上下文并加载着色器程序。可以使用 Android 提供的 NativeActivity 类来创建一个带有 OpenGL 上下文的活动,并使用 GLES20.glCreateProgram() 和 GLES20.glAttachShader() 等方法来加载着色器程序。 3. 使用 MediaCodec 解码 MP4 视频格式并将其转换为 RGB 图像 可以使用 Android 提供的 MediaCodec 类来解码 MP4 视频格式,并使用 GLES20.glTexImage2D() 和 GLES20.glTexSubImage2D() 等方法将解码后的视频帧转换为 RGB 图像。需要注意的是,由于 MediaCodec 解码后的视频帧是 YUV 格式的,需要进行 YUVRGB 的转换。 4. 在 OpenGL 中渲染 RGB 图像 将转换后的 RGB 图像渲染到 OpenGL 中,可以使用 GLES20.glDrawArrays() 和 GLES20.glEnableVertexAttribArray() 等方法。需要注意的是,由于 RGB 图像的数据格式是 GL_UNSIGNED_BYTE,需要使用 GLES20.glPixelStorei() 方法设置像素存储模式。 以上是大致的代码实现步骤,实际上还有很多细节需要注意,比如使用 OpenGL ES 2.0 的版本号、将 YUV 转换为 RGB 的算法等。如果需要深入了解,可以查看 Android 官方文档和相关的开源库代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值