











GLint EGLVideoShader::InitShader(const char *code, GLint type) { //创建shader GLint sh = glCreateShader(type); if (sh == 0) { LOG_D("glCreateShader %d failed!", type); GLenum error = glGetError(); LOG_D("glCreateShader(%d) failed! Error: 0x%X", type, error); return 0; } //加载shader glShaderSource(sh, 1, //shader数量 &code, //shader代码 0); //代码长度 //编译shader glCompileShader(sh); //获取编译情况 GLint status; glGetShaderiv(sh, GL_COMPILE_STATUS, &status); if (status == 0) { LOG_D("glCompileShader failed!"); return 0; } LOG_D("glCompileShader success!"); return sh; } void EGLVideoShader::Init(int width, int height) { this->width = width; this->height = height; LOG_I("删除datas start"); if (datas[0] != nullptr) { // 检查是否为有效指针 delete[] datas[0]; // 释放Y分量数组 delete[] datas[1]; // 释放U分量数组 delete[] datas[2]; // 释放V分量数组 // 释放后重置为nullptr,避免重复释放 datas[0] = datas[1] = datas[2] = nullptr; } LOG_I("删除datas end"); ///分配材质内存空间 datas[0] = new unsigned char[width * height]; //Y datas[1] = new unsigned char[width * height / 4]; //U datas[2] = new unsigned char[width * height / 4]; //V if (texts[0]) { glDeleteTextures(3, texts); } LOG_I("开始初始化Shader"); //创建三个纹理 glGenTextures(3, texts); //顶点和片元shader初始化 //顶点shader初始化 vsh = InitShader(vertexSource, GL_VERTEX_SHADER); //片元yuv420 shader初始化 fsh = InitShader(fragmentSource, GL_FRAGMENT_SHADER); ///////////////////////////////////////////////////////////// //创建渲染程序 program = glCreateProgram(); if (program == 0) { LOG_D("glCreateProgram failed!"); return; } //渲染程序中加入着色器代码 glAttachShader(program, vsh); glAttachShader(program, fsh); //链接程序 glLinkProgram(program); GLint status = 0; glGetProgramiv(program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { LOG_D("glLinkProgram failed!"); return; } glUseProgram(program); LOG_D("glLinkProgram success!"); GLuint apos = (GLuint) glGetAttribLocation(program, "aPosition"); glEnableVertexAttribArray(apos); //传递顶点 glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 12, vers); GLuint atex = (GLuint) glGetAttribLocation(program, "aTexCoord"); glEnableVertexAttribArray(atex); glVertexAttribPointer(atex, 2, GL_FLOAT, GL_FALSE, 8, txts); //材质纹理初始化 //设置纹理层 glUniform1i(glGetUniformLocation(program, "yTexture"), 0); //对于纹理第1层 glUniform1i(glGetUniformLocation(program, "uTexture"), 1); //对于纹理第2层 glUniform1i(glGetUniformLocation(program, "vTexture"), 2); //对于纹理第3层 //设置纹理属性 glBindTexture(GL_TEXTURE_2D, texts[0]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 glTexImage2D(GL_TEXTURE_2D, 0, //细节基本 0默认 GL_LUMINANCE,//gpu内部格式 亮度,灰度图 width, height, //拉升到全屏 0, //边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致 GL_UNSIGNED_BYTE, //像素的数据类型 NULL //纹理的数据 ); //设置纹理属性 glBindTexture(GL_TEXTURE_2D, texts[1]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 glTexImage2D(GL_TEXTURE_2D, 0, //细节基本 0默认 GL_LUMINANCE,//gpu内部格式 亮度,灰度图 width / 2, height / 2, //拉升到全屏 0, //边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致 GL_UNSIGNED_BYTE, //像素的数据类型 NULL //纹理的数据 ); //设置纹理属性 glBindTexture(GL_TEXTURE_2D, texts[2]); //缩小的过滤器 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //设置纹理的格式和大小 glTexImage2D(GL_TEXTURE_2D, 0, //细节基本 0默认 GL_LUMINANCE,//gpu内部格式 亮度,灰度图 width / 2, height / 2, //拉升到全屏 0, //边框 GL_LUMINANCE,//数据的像素格式 亮度,灰度图 要与上面一致 GL_UNSIGNED_BYTE, //像素的数据类型 NULL //纹理的数据 ); LOG_I("Shader初始化成功"); } void EGLVideoShader::Render(AVFrame *frame, std::function<void()> renderCallback) { // LOG_E("渲染:width=%d,height=%d,frame->width=%d,frame->height=%d",width,height,frame->width,frame->height); if (!datas[0] || width * height == 0 || frame->width != this->width || frame->height != this->height) { LOG_E("空数据开始释放内存AVFrame"); av_frame_free(&frame); return; } // LOG_E("Start Render View"); if (width == frame->linesize[0]) //无需对齐 { LOG_E("无需对齐数据->start"); memcpy(datas[0], frame->data[0], width * height); memcpy(datas[1], frame->data[1], width * height / 4); memcpy(datas[2], frame->data[2], width * height / 4); LOG_E("无需对齐数据->end"); } else//行对齐问题 { // LOG_E("逐行copy数据->start"); for (int i = 0; i < height; i++) //Y memcpy(datas[0] + width * i, frame->data[0] + frame->linesize[0] * i, width); for (int i = 0; i < height / 2; i++) //U memcpy(datas[1] + width / 2 * i, frame->data[1] + frame->linesize[1] * i, width); for (int i = 0; i < height / 2; i++) //V memcpy(datas[2] + width / 2 * i, frame->data[2] + frame->linesize[2] * i, width); // LOG_E("Repaint->逐行copy数据->end"); } av_frame_free(&frame); // LOG_E("释放AVFrame"); //激活第1层纹理,绑定到创建的opengl纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texts[0]); //替换纹理内容 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, datas[0]); //激活第2层纹理,绑定到创建的opengl纹理 glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_2D, texts[1]); //替换纹理内容 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, datas[1]); //激活第2层纹理,绑定到创建的opengl纹理 glActiveTexture(GL_TEXTURE0 + 2); glBindTexture(GL_TEXTURE_2D, texts[2]); //替换纹理内容 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, datas[2]); //三维绘制 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //窗口显示 renderCallback(); } void EGLVideoShader::Release() { width = 0; height = 0; //材质内存空间 if (datas[0] != nullptr) { // 检查是否为有效指针 delete[] datas[0]; // 释放Y分量数组 delete[] datas[1]; // 释放U分量数组 delete[] datas[2]; // 释放V分量数组 // 释放后重置为nullptr,避免重复释放 datas[0] = datas[1] = datas[2] = nullptr; } // 释放纹理 if (texts[0] != 0) { glDeleteTextures(3, texts); texts[0] = texts[1] = texts[2] = 0; } if (program != 0) { glUseProgram(0); // 分离着色器 if (vsh != 0) { glDetachShader(program, vsh); } if (fsh != 0) { glDetachShader(program, fsh); } glDeleteProgram(program); program = 0; } // 释放着色器 if (vsh != 0) { glDeleteShader(vsh); vsh = 0; } if (fsh != 0) { glDeleteShader(fsh); fsh = 0; } LOG_I("Release释放内存及显存"); }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。