惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
I
InfoQ
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
美团技术团队
小众软件
小众软件
Blog — PlanetScale
Blog — PlanetScale
Jina AI
Jina AI
aimingoo的专栏
aimingoo的专栏
H
Help Net Security
Last Week in AI
Last Week in AI
博客园_首页
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LangChain Blog
云风的 BLOG
云风的 BLOG
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
G
Google Developers Blog
博客园 - 叶小钗
博客园 - Franky

博客园 - 飘杨......

为ZLMediaKit在windows10编译srtp Windows10安装部署ZLMediaKit SurfaceView+ANativeWindow+ffmpeg播放视频并解决花屏问题 SDL播放音频工具类封装 Qt QWidget中dropEvent(QDropEvent* e)拖拽放开不接收事件/不执行,且拖拽到目标后鼠标显示禁用符号 ffmpeg视频转码遇到H264黑屏问题 ffmpeg根据输入的参数截取视频 ffmpeg将视频流录制下来并保存到本地 ffmpeg解封装mp4并解码渲染(SDL2) Qt+ffmpeg+SDL硬件解码并渲染 ffmpeg+sdl播放H264/H265文件 FFmpeg实战:录制Windows屏幕并用FFmpeg压缩成H.264/H.265并保存 ffmpeg SwsContext像素格式转换BGRA转YUV420P H264/H265 NALU的nalu_unit_type解析 ffmpeg码率控制模式详解 ffmpeg-H264/H265常用编解码预设参数 Qt+FFmpeg+SDL 实现多路多格式原始视频播放工具:从像素处理到实时渲染 Qt+SDL 实战:多格式视频播放工具开发 —— 支持 RGBA/ARGB/RGB24/YUV420P 的完整实现 SDL将YUV视频渲染到Qt窗口播放
SurfaceView+EGL+OpenGL ES+ffmpeg播放视频并解决黑屏不显示...
飘杨...... · 2025-07-15 · via 博客园 - 飘杨......
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释放内存及显存");
}