由于工作需要,这几天在研究OpenGLES的使用,并需要做出一个APK来实现NV12的渲染,由于对Java编程也不懂,所以还去补了点基础的东西,然后参考了很多文章才完成。这里就记录下我的工程和期间遇到的问题。
参考链接:
- https://blog.youkuaiyun.com/yu540135101/article/details/101023208
- https://blog.youkuaiyun.com/WuNLK/article/details/77017813
- https://blog.youkuaiyun.com/ueryueryuery/article/details/17608185
- https://www.jianshu.com/p/0ecc37cc2f6e
- https://www.cnblogs.com/firstdream/p/7809404.html
- https://blog.youkuaiyun.com/wang2470198567/article/details/45044283
- https://blog.youkuaiyun.com/biggbang/article/details/20037073
还有一些琐碎的就不贴了,零基础的(我这种)可以先看看链接一的大佬的博客,学习点OpenGLES的基础知识,最好再掌握点yuv数据存储方式,这样才会明白分离yuv分量的字节偏移量。
话不多说,开工
- 要使用OpenGLES20,首先需要在AndroidManifest.xml种添加权限说明
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature
android:glEsVersion="0x00020000" android:required="true" />
不要忘了加文件读取的权限~
2. 再放上Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.opengl.GLSurfaceView
android:id="@+id/MyGLView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>```
4. MainActivity
这里面的内容就很简单了,就指定了布局,然后让MyRender渲染就完事儿了。
```java
public class MainActivity extends AppCompatActivity {
//首先创建一个SurfaceView才能显示
private GLSurfaceView mGLSurface;
//创建自定义的Render才能渲染
private MyRender mGLRender;
//这里设定的宽高是yuv数据的宽高
private int pic_width = 1280;
private int pic_height = 720;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGLSurface = findViewById(R.id.MyGLView);
//使用自定义宽高布局
ViewGroup.LayoutParams lp = mGLSurface.getLayoutParams();
Point point_width = new Point();
getWindowManager().getDefaultDisplay().getSize(point_width);
lp.width = 1280;
lp.height = 720;
mGLSurface.setLayoutParams(lp);
try {
mGLRender = new MyRender(mGLSurface, pic_width, pic_height);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
- 现在来看MyRender是怎么实现的
MyRender继承与GLSurface.Render,主要重写了三个父类方法onSurfaceCreated(用于一些初始化操作),onSurfaceChanged(更改渲染信息时更新属性)和onDrawFrame(绘制)。
以下是代码:
public class MyRender implements GLSurfaceView.Renderer{
private static final String TAG = "OpenGLES20_Test";
private GLSurfaceView _GLSurfaceView;
private int _program;
private int _vertexShader;
private int _fragmentShader;
private FloatBuffer _vertexArray = null;
private FloatBuffer _textureArray = null;
private int _positionHandle;
private int _textureHandle;
private FileInputStream _yuvfilestream = null;
private ByteBuffer _frameData = null;
private FileChannel _yuvChinnel = null