鸿蒙OpenGL ES渲染H264花屏问题

问题现象

问题排查

这个问题的花屏存在规律现象,是横向花屏,但是原因不明,最后的排查方法最后了解到画面的排列存在跨距对齐字节引起的。图像每一行像素的宽度并不一定是是存储在内存的宽度,显示器一般每行数据需要对齐8的字节倍数,但图像像素不一定。所以会存在补充对齐字节的概念。

代码

原代码

cpp 复制代码
void EGLCore::LoadPhoneYuv(int width, int height, webrtc::I420BufferInterface *buffer) {
      // Texture ID.
    GLuint texts[3] = { 0 };
    // Create several texture objects and get the texture ID.
    glGenTextures(3, texts);

    // Bound texture. The following settings and loadings all apply to the currently bound texture object.
    // GL_TEXTURE0, GL_TEXTURE1, and GL_TEXTURE2 are texture units.
    // GL_Texture_1D, GL_Texture_2D, and CUBE_MAP are texture targets.
    // After the texture target is bound to the texture through the glBindTexture function, 
    // the operations performed on the texture target are reflected on the texture.
    glBindTexture(GL_TEXTURE_2D, texts[0]);
    // Shrinking filters.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // A magnified filter.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D,
                 0,                // Details are basically 0 by default.
                 GL_LUMINANCE,     // GPU internal format luminance, grayscale image.
                 width,            // Width of the loaded texture.
                 height,           // Height of the loaded texture.
                 0,                // Textured border.
                 GL_LUMINANCE,     // Data pixel format luminance, grayscale image.
                 GL_UNSIGNED_BYTE, // Data type for storing pixels.
                 NULL              // Data for the texture.
    );

    // Bind the texture.
    glBindTexture(GL_TEXTURE_2D, texts[1]);
    // Shrinking filters.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // Sets the format and size of the texture.
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_LUMINANCE,
                 width / 2,        // The amount of u data is 1/4 of the screen.
                 height / 2,
                 0,                // Borders.
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE,
                 NULL
    );

    // Bind the texture.
    glBindTexture(GL_TEXTURE_2D, texts[2]);
    // Shrinking filters.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // Sets the format and size of the texture.
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_LUMINANCE,
                 width / 2,        //  The amount of v data is 1/4 of the screen.
                 height / 2,
                 0,
                 GL_LUMINANCE,
                 GL_UNSIGNED_BYTE,
                 NULL
    );

    // Activates the first layer of texture, bound to the created texture.
    glActiveTexture(GL_TEXTURE0);
    // Binds the texture corresponding to y.
    glBindTexture(GL_TEXTURE_2D, texts[0]);
    // Replace the texture.
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, // Offset of the original texture.
                    width, height,          // Width and height of the loaded texture.
                    GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer->DataY());

    // Activates the second layer of texture, which is bound to the created texture.
    glActiveTexture(GL_TEXTURE1);
    // Binds the texture corresponding to u.
    glBindTexture(GL_TEXTURE_2D, texts[1]);
    // Replace the texture.
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer->DataU());
    // Activates the third layer of texture, which is bound to the created texture.
    glActiveTexture(GL_TEXTURE2);
    // Binds the texture corresponding to v.
    glBindTexture(GL_TEXTURE_2D, texts[2]);
    // Replace the texture.
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer->DataV());
    FinishLoad();
}

修改后的代码

cpp 复制代码
void EGLCore::LoadPhoneYuv(int width, int height, webrtc::I420BufferInterface *buffer) {
    int yStride = buffer->StrideY();
    int uvStride = buffer->StrideU();
    // Texture IDs for Y, U, V
    GLuint textures[3];
    glGenTextures(3, textures);

    // Uniform texture parameters
    for (int i = 0; i < 3; ++i) {
        glBindTexture(GL_TEXTURE_2D, textures[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }

    // Set unpack row length (stride)
    glPixelStorei(GL_UNPACK_ROW_LENGTH, yStride); // Set stride for Y plane
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, yStride, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer->DataY());

    glPixelStorei(GL_UNPACK_ROW_LENGTH, uvStride); // Set stride for U plane
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, uvStride, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
                 buffer->DataU());

    glPixelStorei(GL_UNPACK_ROW_LENGTH, uvStride); // Set stride for V plane
    glBindTexture(GL_TEXTURE_2D, textures[2]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, uvStride, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
                 buffer->DataV());

    // Reset unpack row length to default
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

    // Activate and bind textures (if necessary in the rendering pipeline)
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textures[0]);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, textures[1]);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, textures[2]);

    // Signal that textures are loaded (e.g., any additional OpenGL operations)
    FinishLoad();

    // Delete textures if they are temporary
    glDeleteTextures(3, textures);
}
相关推荐
xq95273 小时前
HDC Assistant 插件横空出世
harmonyos
OH_TPC10 小时前
【鸿蒙优选三方库】@ohos/aki:一行代码让 ArkTS 调 C++
harmonyos
wenyiyiyiyiyi11 小时前
我用鸿蒙 ArkTS 写了个自己天天用的备忘录:待办、课表和长期目标,全塞进一块桌面卡片
harmonyos
承渊政道13 小时前
鸿蒙设备远控电脑实测:ToDesk蓝牙键鼠、双模式鼠标、跨端剪贴板,远控电脑更顺手了
计算机外设·电脑·harmonyos·远程工作·todesk
CV工程师丁Sir16 小时前
ArkWeb 手记 04|DevTools 调试与缓存清理
java·spring·缓存·harmonyos
程序猿追1 天前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos
程序猿追1 天前
HarmonyOS 6 音视频实战:用 AVPlayer 做一个本地音乐播放器
华为·音视频·harmonyos
威哥爱编程1 天前
HarmonyOS 7 多设备 UX 自动检测实战:AppAnalyzer 多设备体检 + 一多工程底线,提前拦截截断重叠大图大字
harmonyos
威哥爱编程1 天前
HarmonyOS 7 安全相机 2.0 实战:数字内容溯源,为拍摄内容提供来源保护
harmonyos
威哥爱编程1 天前
HarmonyOS 7 弱网优化实战:Network Boost Kit 场景加速 + QUIC 长连接 + 弱网直播优化
harmonyos