鸿蒙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);
}
相关推荐
Goway_Hui13 分钟前
【KMP for OpenHarmony】-- 在鸿蒙工程中使用 Apollo-Kotlin
华为·kotlin·harmonyos
正在走向自律2 小时前
HarmonyOS 手机/平板远程控制 Windows 电脑实践指南
智能手机·电脑·harmonyos·todesk·远程工具
熊猫钓鱼>_>3 小时前
鸿蒙 PC 三方库适配复盘:libfvad 1.0 —— 把 WebRTC VAD 做成能装进采集链路的静态库
服务器·开发语言·华为·harmonyos·openharmony·适配·鸿蒙pc
aqi003 小时前
AI编程让鸿蒙开发电子书APP更加快捷
android·华为·harmonyos·鸿蒙·harmony
熊猫钓鱼>_>4 小时前
鸿蒙PC高分屏与键鼠交互适配:DPI缩放、右键菜单一次讲清
开发语言·笔记·华为·ai编程·harmonyos·鸿蒙·鸿蒙心迹
Goway_Hui4 小时前
【KMP for OpenHarmony】Cache4k 0.14.0 鸿蒙适配
华为·kotlin·harmonyos
SZYSK5 小时前
OpenHarmony 上读卡、推理和双屏刷新抢 CPU:核验机与消费机的调度差
物联网·算法·harmonyos·1024程序员节
lqj_本人5 小时前
开源鸿蒙平台 KMP_CMP 三方库「URI KMP」适配全流程
华为·开源·harmonyos
hhhjhl6 小时前
React Native 三方库「react-native-sha256」的鸿蒙化适配指南
react native·华为·harmonyos