前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >OpenGL ES for Android 视频缩放、旋转、平移

OpenGL ES for Android 视频缩放、旋转、平移

作者头像
老孟Flutter
发布于 2020-09-11 08:07:44
发布于 2020-09-11 08:07:44
2.8K00
代码可运行
举报
文章被收录于专栏:FlutterFlutter
运行总次数:0
代码可运行

一个

有态度

的程序员

在上一篇文章中我们介绍了使用OpenGL ES 播放视频,在末尾提到如果渲染视频的窗口宽高比和视频宽高比不一致会导致视频拉伸,这篇文章将会介绍如何通过视频的缩放来解决这个问题。

我们希望当视频的比例和窗口的比例不一样时,其中一边占满全屏,另一边等比缩放并居中,其余部分显示黑色,这个效果和我们平时使用的视频播放器的效果是一样的,效果如图:

我们在OpenGL ES 播放视频的基础进行修改,修改顶点shader

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
attribute vec4 a_Position;
attribute vec2 a_TexCoordinate;
varying vec2 v_TexCoord;
uniform mat4 mvpMatrix;
void main()
{
    v_TexCoord = a_TexCoordinate;
    gl_Position = mvpMatrix*a_Position;
}

在顶点shader中加入mvpMatrix(MVP矩阵)并与a_Position相乘。

获取mvpMatrix索引

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
            GLES20.glClearColor(0F, 0F, 0F, 1F)
      ...
            mvpMatrixLoc = GLES20.glGetUniformLocation(mProgramHandle, "mvpMatrix")
      ...
}

获取视频及渲染窗口的宽高

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
            GLES20.glViewport(0, 0, width, height)
            screenWidth = width
            screenHeight = height
            if (videoWidth > 0 && videoHeight > 0) {
                computeMatrix()
            }
        }
mediaPlayer.setOnVideoSizeChangedListener { mp, width, height ->
                run {
                    videoWidth = width
                    videoHeight = height
                    if (screenWidth > 0 && screenHeight > 0) {
                        computeMatrix()
                    }
                }
            }

渲染窗口的宽高在onSurfaceChanged中获取,视频的宽高需要给meidaplay添加OnVideoSizeChangedListener回调,由于视频的播放是在onSurfaceCreated中调用且这2个回调都是异步的,因此无法判断先后顺序,因此在这2个回调中都增加判断,只有当视频和渲染窗口的宽高都获取到才计算MVP矩阵,或者我们也可以在onSurfaceChanged中调用视频播放,这样就可以只在OnVideoSizeChangedListener回调中计算矩阵。

计算矩阵

假设视频的宽高比小于屏幕的宽高比,那么视频则在高度上铺满窗口,在宽度上进行缩放,为了不拉伸视频,缩放的系数为1 - ((屏幕的宽高比 - 视频的宽高比) / 2),反之如果视频的宽高比大于屏幕的宽高比,视频在高度上的缩放的系数为1 - ((视频的宽高比 - 屏幕的宽高比 ) / 2),代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var modelMatrix = FloatArray(16)
fun computeMatrix() {
            val videoRatio = videoWidth / videoHeight.toFloat()
            val screenRatio = screenWidth / screenHeight.toFloat()
            Matrix.setIdentityM(modelMatrix, 0)
            if (videoRatio > screenRatio) {
                Matrix.scaleM(modelMatrix, 0, 1F, 1 - ((videoRatio - screenRatio) / 2), 1F)
            } else if (videoRatio < screenRatio) {
                Matrix.scaleM(modelMatrix, 0, 1 - ((screenRatio - videoRatio) / 2), 1F, 1F)
            }
        }

绘制

在绘制的时候设置modelMatrix矩阵,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
override fun onDrawFrame(p0: GL10?) {
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
            GLES20.glUseProgram(mProgramHandle)
            //设置顶点数据
            vertexBuffer.position(0)
            GLES20.glEnableVertexAttribArray(vPositionLoc)
            GLES20.glVertexAttribPointer(vPositionLoc, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer)
            //设置纹理顶点数据
            texBuffer.position(0)
            GLES20.glEnableVertexAttribArray(texCoordLoc)
            GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT, false, 0, texBuffer)
            //设置纹理
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
            GLES20.glUniform1i(textureLoc, 0)
            //设置mvp矩阵
            GLES20.glUniformMatrix4fv(mvpMatrixLoc, 1, false, modelMatrix, 0)
            GLES20.glDrawElements(
                GLES20.GL_TRIANGLES,
                index.size,
                GLES20.GL_UNSIGNED_SHORT,
                indexBuffer
            )
        }

GLES20.glUniformMatrix4fv(mvpMatrixLoc, 1, false, modelMatrix, 0)为矩阵数据设置,其他已经在OpenGL ES 播放视频中介绍,这里不在介绍。

到这里我们介绍完了视频的缩放功能,想一想如果在欢迎界面播放视频,我们希望视频充满屏幕,而不是出现黑屏,但市场上的手机屏幕比例各种各样,尤其是全面屏、折叠屏的出现,有16:9的、2:1的,还有16:10的,那么如何使用同一个视频去适配所有的屏幕呢?其实一样可以通过视频缩放而解决,只不过一个缩放视频,一个是放大视频。

视频的旋转、平移和缩放是一样的,我们只需要对矩阵进行相应的操作,比如将视频旋转45度,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Matrix.rotateM(modelMatrix,0,45F,0F,0F,1F)

效果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老孟Flutter 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
​OpenGL 学习系列---投影矩阵
OpenGL 在观察空间转换到裁剪空间时,需要用到投影矩阵。而在着色器脚本中,也需要提供一个投影矩阵给对应的 u_ProjectionMatrix变量。
音视频开发进阶
2019/07/25
1.2K0
SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,
在要求实时性比较高的游戏开发中,显然,view的ondraw是满足不了你的,这时候只能是用SurfaceView。
zhangjiqun
2024/12/16
1030
SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,
OpenGL ES + MediaPlayer 渲染播放视频+滤镜效果
之前曾经写过用SurfaceView,TextureView+MediaPlayer 播放视频,和 ffmpeg avi 解码后SurfaceView播放视频 ,今天再给大家来一篇 OpenGL ES+MediaPlayer 来播放视频。
字节流动
2020/11/30
2.2K0
OpenGL ES + MediaPlayer 渲染播放视频+滤镜效果
OpenGL ES for Android 绘制立方体
a_Position为顶点数据,a_color为顶点颜色数据,v_color为varying变量,传递给我片段shader使用。
老孟Flutter
2020/09/11
8960
OpenGL ES for Android 相机预览适配不同分辨率的手机
上一篇讲到OpenGL ES for Android 相机预览,相机的预览分辨率设置为1280*720,大家有没有想过如果将GLSurfaceView设置为正方形会如何?很明显画面会被拉伸导致变形,在想一下如果设置GLSurfaceView为全屏,但目前市场上的手机有很多种不同的分辨率,尤其是全面屏、折叠屏屏,这些手机并不是常见的16:9的手机,因此我们需要适配这些不同分辨率的手机。
老孟Flutter
2020/09/11
1.6K0
Android OpenGL ES(二)-正交投影
平移矩阵和单位矩阵和类似。但是向量[x,y,z,1]前乘这个平移矩阵后的结构就是平移矩阵中定义的偏移量。
deep_sadness
2018/08/30
1.6K0
Android OpenGL ES(二)-正交投影
用纹理增加细节
  OpenGL中的纹理可以用来表示照片,图像。每个二维的纹理都由许多小的纹理元素组成,他们是小块的数据,类似于我们前面讨论的片段和像素。要使用纹理,最直接的方式是从图像文件加载数据。我们现在要加载下面这副图像作为空气曲棍球桌子的表面纹理:
故乡的樱花开了
2024/02/05
1250
用纹理增加细节
FFmpeg + OpenGLES 实现视频解码播放和视频滤镜
前面 Android FFmpeg 开发系列文章中,我们已经利用 FFmpeg 的解码功能和 ANativeWindow 的渲染功能,实现了的视频的解码播放。
字节流动
2020/08/20
3K0
FFmpeg + OpenGLES 实现视频解码播放和视频滤镜
OpenGL ES for Android 相机预览
Android上打开摄像头需要camera权限,在Android 6.0及以上的版本需要动态申请权限,在`AndroidManifest.xml`中添加camera权限:
老孟Flutter
2020/09/11
1K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】二、使用OpenGL渲染视频画面
在第一篇文章【音视频基础知识】文章中,就介绍过,视频其实就是一张张图片组成的,在上文【初步了解OpenGL ES】中,介绍了如何通过OpenGL渲染一张图片,可以猜想到,视频的渲染和图片的渲染应该是差不多的。话不多说,马上就来看看。
开发的猫
2020/04/02
2.3K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】二、使用OpenGL渲染视频画面
[ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门
问:学OpenGL能干嘛? 答: 为所欲为。 说起OpenGLES,大家可能都敬而远之,其实它并没有想象中的那么可怕,当然也并没有那么容易 都0202年了,本系列使用OpenGLES3.0,这是一次有预谋的计划: [- 多媒体 -] OpenGLES3.0 接入视频实现特效 - 引言 [ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门 [ - OpenGLES3.0 - ] 第二集 主线 - 绘制面与图片贴图 [ - OpenGLES3.0 - ] 第三集 主线 -
张风捷特烈
2020/04/30
6561
[ - OpenGLES3.0 - ]  第一集 主线 - 打开新世界的大门
OpenGL ES for Android 绘制旋转的地球
No 图 No Code,上面旋转的地球是不是很酷炫,下面就让我们开始说说如何绘制旋转地球吧?绘制旋转地球需要3个步骤:
老孟Flutter
2020/09/11
1.7K0
Android中基于OpenGL的特效
大家都知道,给图片加滤镜加特效,通常是对图像进行矩阵运算。通过颜色矩阵的乘法,我们可以对图像中的元素进行变换。 但是,如果需要对实时变化的图像进行实时处理,就不是每种图像变换的方式都可以用了。因为,实时变化的预览图像,会有帧率的压力,我们的处理一定要快。
Oceanlong
2018/08/14
2.2K0
Android中基于OpenGL的特效
音视频开发之旅(42)-光照基础(一)
环境光(Ambient Lightiing)不来自任何特定方向的光,在经典光照模型中会用一个常量来表示 使用时只需要对其片源着色器添加一个环境光常量,作为gl_Fragcolor的调制即可_
音视频开发之旅
2021/04/19
5680
音视频开发之旅(42)-光照基础(一)
Android OpenGLES 绘制图片纹理
把shader代码写入raw里面 vertex_shader.glsl attribute vec4 av_Position;//顶点位置 attribute vec2 af_Position;//纹理位置 varying vec2 v_texPo;//纹理位置 与fragment_shader交互 void main() { v_texPo = af_Position; gl_Position = av_Position; } fragment_shader.glsl precisio
曾大稳
2018/09/11
1.1K0
Android OpenGLES 绘制图片纹理
这交互炸了,Android 仿自如APP裸眼 3D 效果 OpenGL 版
https://juejin.cn/post/7035645207278256165
字节流动
2021/12/20
1.6K0
这交互炸了,Android 仿自如APP裸眼 3D 效果 OpenGL 版
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】一、初步了解OpenGL ES
提到OpenGL,想必很多人都会说,我知道这个东西,可以用来渲染2D画面和3D模型,同时又会说,OpenGL很难、很高级,不知道怎么用。
开发的猫
2020/04/01
2K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】一、初步了解OpenGL ES
[-综合篇-] 相机、OpenGL、视频、Flutter和SurfaceView
认识一个类,相当于结交一位朋友;看一篇源码,相当于一次顶级的会话; 读一个框架,相当于见证一段思想;做一个程序,相当于创造一个生命; 一次Git提交,相当于记录一次成长;生活也许并非那么美好,但一切可以这么崇高。----张风捷特烈
张风捷特烈
2020/04/30
3.2K0
[-综合篇-] 相机、OpenGL、视频、Flutter和SurfaceView
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】三、OpenGL渲染多视频,实现画中画
距离上次更新已经有两个星期,由于这段时间事情比较多,还请各位关注本系列文章的小伙伴见谅,一有时间我会加紧码字,感谢大家的关注和督促。
开发的猫
2020/04/02
2.6K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】三、OpenGL渲染多视频,实现画中画
构建简单物体
  我们的空气曲棍球游戏已经取得了很大的进展,桌子已经放到了一个很好的角度,并且由于使用了纹理,更加好看了。然而,我们现在是用的点去代替木槌,它们实际看起来还不像木槌,许多应用都是通过合并简单的物体去构建更复杂的物体,我们在这篇文章中将学会如何绘制木槌以及桌子中间的冰球。
故乡的樱花开了
2024/02/08
1010
构建简单物体
推荐阅读
相关推荐
​OpenGL 学习系列---投影矩阵
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文