当前位置:   article > 正文

HarmonyOS通过OpenGL渲染显示yuv数据_鸿蒙 camera 通过opegl 渲染

鸿蒙 camera 通过opegl 渲染

一、UI页面render_page.ets

  1. Column() {
  2. XComponent({
  3. id: "XComponent88",
  4. type: XCompentConstants.XCOMPONENT_TYPE,
  5. libraryname: XCompentConstants.XCOMPONENT_LIBRARY_NAME
  6. }).width(640).height(360)
  7. .onLoad((xComponentContext?: object | Record<string, () => void>) => {
  8. if (xComponentContext) {
  9. SRLog.i(TAG, "xComponentContext======")
  10. this.xComponentContext = xComponentContext as Record<string, (userid: number, streamid: number) => void>;
  11. this.xComponentContext.setBindUser(123, 1);
  12. }
  13. })
  14. }

 二、通过NAPI创建RenderManager管理Xcompent的windows窗口

1、NAPI初始化:init_napi.cpp

  1. #include "util/Log.h"
  2. #include "napi/native_api.h"
  3. #include "rtc/SRRtcVideoEngineNapi.h"
  4. #include "SRWindowManager.h"
  5. #include "net/SRHttpManager.h"
  6. EXTERN_C_START
  7. static napi_value Init(napi_env env, napi_value exports) {
  8. napi_property_descriptor desc[] = {
  9. {"testRender", nullptr, SRRtcVideoEngineNapi::testRender, nullptr, nullptr, nullptr, napi_default, nullptr},
  10. {"getNativeLifeCycle", nullptr, SRWindowManager::getNativeLifeCycle, nullptr, nullptr, nullptr, napi_default,
  11. nullptr}
  12. };
  13. if (napi_ok != napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)) {
  14. LogE("init_napi===napi_define_properties failed");
  15. return nullptr;
  16. }
  17. SRWindowManager::GetInstance()->Export(env, exports);
  18. return exports;
  19. }
  20. EXTERN_C_END
  21. static napi_module demoModule = {
  22. .nm_version = 1,
  23. .nm_flags = 0,
  24. .nm_filename = nullptr,
  25. .nm_register_func = Init,
  26. .nm_modname = "rtcvideo",
  27. .nm_priv = ((void *)0),
  28. .reserved = {0},
  29. };
  30. extern "C" __attribute__((constructor)) void RegisterRtcvideoModule(void) { napi_module_register(&demoModule); }

2、绑定XCompendNative的实现:SRWindowManager.cpp

  1. std::unordered_map<std::string, OH_NativeXComponent *> SRWindowManager::m_nativeXComponentMap;
  2. std::unordered_map<std::string, SRGLRender *> SRWindowManager::m_SRGLRenderMap;
  3. void SRWindowManager::Export(napi_env env, napi_value exports) {
  4. LogE("PluginManager::Export====");
  5. if ((nullptr == env) || (nullptr == exports)) {
  6. LogE("PluginManager::Export: env or exports is null");
  7. return;
  8. }
  9. napi_value exportInstance = nullptr;
  10. if (napi_ok != napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) {
  11. LogE("PluginManager::Export: napi_get_named_property fail");
  12. return;
  13. }
  14. OH_NativeXComponent *nativeXComponent = nullptr;
  15. if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) {
  16. LogE("PluginManager::Export: napi_unwrap fail");
  17. return;
  18. }
  19. char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
  20. uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
  21. if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) {
  22. LogE("Export: OH_NativeXComponent_GetXComponentId fail");
  23. return;
  24. }
  25. std::string id(idStr);
  26. auto context = SRWindowManager::GetInstance();
  27. if ((nullptr != context) && (nullptr != nativeXComponent)) {
  28. context->SetNativeXComponent(id, nativeXComponent);
  29. auto render = context->GetRender(id);
  30. OH_NativeXComponent_RegisterCallback(nativeXComponent, &SRGLRender::m_callback);
  31. if (nullptr != render) {
  32. render->Export(env, exports);
  33. }
  34. }
  35. }
  36. void SRWindowManager::SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent) {
  37. if (nullptr == nativeXComponent) {
  38. return;
  39. }
  40. if (m_nativeXComponentMap.find(id) == m_nativeXComponentMap.end()) {
  41. m_nativeXComponentMap[id] = nativeXComponent;
  42. return;
  43. }
  44. if (m_nativeXComponentMap[id] != nativeXComponent) {
  45. OH_NativeXComponent *tmp = m_nativeXComponentMap[id];
  46. delete tmp;
  47. tmp = nullptr;
  48. m_nativeXComponentMap[id] = nativeXComponent;
  49. }
  50. }
  51. SRGLRender *SRWindowManager::GetRender(std::string &id) {
  52. if (m_SRGLRenderMap.find(id) == m_SRGLRenderMap.end()) {
  53. SRGLRender *instance = SRGLRender::GetInstance(id);
  54. m_SRGLRenderMap[id] = instance;
  55. return instance;
  56. }
  57. return m_SRGLRenderMap[id];
  58. }

三、OpenGL渲染模块

1、定义Shader

  1. const char VERTEX_SHADER11[] = "attribute vec4 vPosition;\n"
  2. "attribute vec2 a_texCoord;\n"
  3. "varying vec2 tc;\n"
  4. " uniform mat4 uMVPMatrix;\n"
  5. "void main() {\n"
  6. "gl_Position =uMVPMatrix * vPosition ;\n"
  7. "tc = a_texCoord;\n"
  8. "}\n";
  9. const char FRAGMENT_SHADER11[] = "precision mediump float;\n"
  10. "uniform sampler2D tex_y;\n"
  11. "uniform sampler2D tex_u;\n"
  12. "uniform sampler2D tex_v;\n"
  13. "varying vec2 tc;\n"
  14. "void main() {\n"
  15. "vec4 c = vec4((texture2D(tex_y, tc).r - 16./255.) * 1.164);\n"
  16. "vec4 U = vec4(texture2D(tex_u, tc).r - 128./255.);\n"
  17. "vec4 V = vec4(texture2D(tex_v, tc).r - 128./255.);\n"
  18. "c += V * vec4(1.596, -0.813, 0, 0);\n"
  19. "c += U * vec4(0, -0.392, 2.017, 0);\n"
  20. "c.a = 1.0;\n"
  21. "gl_FragColor = c;\n"
  22. "}\n";

2、初始化EglContextInit

  1. bool EGLCore::EglContextInit(void *window, int width, int height) {
  2. LogE("EGLCore::EglContextInit execute===width:%d,height:%d", width, height);
  3. if (nullptr == window) {
  4. LogE("EGLCore::EglContextInit window=nullptr");
  5. }
  6. if ((nullptr == window) || (0 >= width) || (0 >= height)) {
  7. LogE("EGLCore::EglContextInit: param error");
  8. return false;
  9. }
  10. w_width = width;
  11. w_height = height;
  12. LogE("EGLCore::EglContextInit: param m_width:%d;%d", w_width, w_height);
  13. m_eglWindow = reinterpret_cast<EGLNativeWindowType>(window);
  14. // Init display.
  15. m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  16. if (EGL_NO_DISPLAY == m_eglDisplay) {
  17. LogE("EGLCore:: eglGetDisplay: unable to get EGL display");
  18. return false;
  19. }
  20. EGLint majorVersion;
  21. EGLint minorVersion;
  22. if (!eglInitialize(m_eglDisplay, &majorVersion, &minorVersion)) {
  23. LogE("EGLCore:: eglInitialize: unable to get initialize EGL display");
  24. return false;
  25. }
  26. // Select configuration.
  27. const EGLint maxConfigSize = 1;
  28. EGLint numConfigs;
  29. if (!eglChooseConfig(m_eglDisplay, ATTRIB_LIST, &m_eglConfig, maxConfigSize, &numConfigs)) {
  30. LogE("EGLCore::eglChooseConfig: unable to choose configs");
  31. return false;
  32. }
  33. bool isCreateEnvironment = CreateEnvironment();
  34. if (isCreateEnvironment) {
  35. glClearColor(0.0, 0.0, 0.0, 0.0);
  36. GLuint textures[1];
  37. glGenTextures(1, &textures[0]);
  38. }
  39. return isCreateEnvironment;
  40. }
  41. bool EGLCore::CreateEnvironment() {
  42. // Create surface.
  43. m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_eglWindow, NULL);
  44. if (nullptr == m_eglSurface) {
  45. LogE("EGLCore:: eglCreateWindowSurface: unable to create surface");
  46. return false;
  47. }
  48. // Create context.
  49. m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
  50. if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) {
  51. LogE("EGLCore::eglMakeCurrent failed");
  52. return false;
  53. }
  54. // Create program.
  55. m_program = CreateProgram(VERTEX_SHADER11, FRAGMENT_SHADER11);
  56. if (PROGRAM_ERROR == m_program) {
  57. LogE("EGLCore::CreateProgram: unable to create program");
  58. return false;
  59. }
  60. // 获取着色器的aPostion和a_textCoord
  61. _positionHandle = glGetAttribLocation(m_program, "vPosition");
  62. mMatrixHandle = glGetUniformLocation(m_program, "uMVPMatrix");
  63. _coordHandle = glGetAttribLocation(m_program, "a_texCoord");
  64. _yhandle = glGetUniformLocation(m_program, "tex_y");
  65. _uhandle = glGetUniformLocation(m_program, "tex_u");
  66. _vhandle = glGetUniformLocation(m_program, "tex_v");
  67. LogE("EGLCore::CreateProgram: "
  68. "_positionHandle:%d;mMatrixHandle:%d;_coordHandle:%d;_yhandle:%d;_uhandle:%d;_vhandle:%d",
  69. _positionHandle, mMatrixHandle, _coordHandle, _yhandle, _uhandle, _vhandle);
  70. _textureI = GL_TEXTURE0;
  71. _textureII = GL_TEXTURE1;
  72. _textureIII = GL_TEXTURE2;
  73. LogE("EGLCore::CreateProgram: _textureI:%d;_textureII:%d;_textureIII:%d", _textureI, _textureII, _textureIII);
  74. return true;
  75. }
  76. GLuint EGLCore::CreateProgram(const char *vertexShader, const char *fragShader) {
  77. if ((nullptr == vertexShader) || (nullptr == fragShader)) {
  78. LogE("EGLCore:: createProgram: vertexShader or fragShader is null");
  79. return PROGRAM_ERROR;
  80. }
  81. GLuint vertex_shader;
  82. vertex_shader = LoadShader(GL_VERTEX_SHADER, vertexShader);
  83. if (PROGRAM_ERROR == vertex_shader) {
  84. LogE("EGLCore:: createProgram vertex error");
  85. return PROGRAM_ERROR;
  86. }
  87. GLuint fragment_shader;
  88. fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragShader);
  89. if (PROGRAM_ERROR == fragment_shader) {
  90. LogE("EGLCore:: createProgram fragment error");
  91. return PROGRAM_ERROR;
  92. }
  93. GLint vCompiled[4] = {0};
  94. // glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, vCompiled);
  95. // if (vCompiled[0] == 0) {
  96. // glDeleteShader(vertex_shader);
  97. // }
  98. glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, vCompiled);
  99. if (vCompiled[0] != GL_TRUE) {
  100. LogE("EGLCore:: createProgram vertex_shader error");
  101. // DeleteProgram();
  102. return PROGRAM_ERROR;
  103. }
  104. glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, vCompiled);
  105. if (vCompiled[0] != GL_TRUE) {
  106. LogE("EGLCore:: createProgram fragment_shader error");
  107. // DeleteProgram();
  108. return PROGRAM_ERROR;
  109. }
  110. GLuint program;
  111. program = glCreateProgram();
  112. if (PROGRAM_ERROR == program) {
  113. LogE("EGLCore:: createProgram program error");
  114. glDeleteShader(vertex_shader);
  115. glDeleteShader(fragment_shader);
  116. return PROGRAM_ERROR;
  117. } else {
  118. LogE("EGLCore:: createProgram 加载着色器");
  119. glAttachShader(program, vertex_shader);
  120. glAttachShader(program, fragment_shader);
  121. glLinkProgram(program);
  122. // 存放链接成功的program的数组
  123. GLint linkedStatus[4] = {0};
  124. glGetProgramiv(program, GL_LINK_STATUS, linkedStatus);
  125. if (linkedStatus[0] != GL_TRUE) {
  126. LogE("EGLCore:: createProgram linkedStatus==error=linkedStatus[0]:%d", linkedStatus[0]);
  127. glDeleteShader(program);
  128. return PROGRAM_ERROR;
  129. }
  130. glUseProgram(program);
  131. }
  132. glDeleteShader(vertex_shader);
  133. glDeleteShader(fragment_shader);
  134. LogE("EGLCore:: createProgram linked success");
  135. return program;
  136. }
  137. GLuint EGLCore::LoadShader(GLenum type, const char *shaderSrc) {
  138. if ((0 >= type) || (nullptr == shaderSrc)) {
  139. LogE("EGLCore:: glCreateShader type or shaderSrc error");
  140. return PROGRAM_ERROR;
  141. }
  142. GLuint shader;
  143. shader = glCreateShader(type);
  144. if (0 == shader) {
  145. LogE("EGLCore:: glCreateShader unable to load shader");
  146. return PROGRAM_ERROR;
  147. }
  148. // The gl function has no return value.
  149. glShaderSource(shader, 1, &shaderSrc, nullptr);
  150. glCompileShader(shader);
  151. return shader;
  152. }

3、渲染实现

  1. void EGLCore::onRenderData(void *yData, void *uData, void *vData, int width, int height) {
  2. if ((nullptr == m_eglDisplay) || (nullptr == m_eglSurface) || (nullptr == m_eglContext) ||
  3. (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))) {
  4. LogE("EGLCore:: PrepareDraw: param error");
  5. return;
  6. }
  7. // The gl function has no return value.
  8. LogE("EGLCore:: PrepareDraw: param m_height:%d,m_width:%d", w_height, w_width);
  9. glViewport(0, 0, w_width, w_height);
  10. glClearColor(0, 0, 0, 1.0);
  11. glClear(GL_COLOR_BUFFER_BIT);
  12. glUseProgram(m_program);
  13. // 开始渲染
  14. LogE("EGLCore::draw: "
  15. "_positionHandle:%d;mMatrixHandle:%d;_coordHandle:%d;_yhandle:%d;_uhandle:%d;_vhandle:%d",
  16. _positionHandle, mMatrixHandle, _coordHandle, _yhandle, _uhandle, _vhandle);
  17. // y
  18. if (m_glTexture[0] < 0) {
  19. glGenTextures(1, &m_glTexture[0]);
  20. LogE("EGLCore::CreateProgram: _ytid ", m_glTexture[0]);
  21. }
  22. glBindTexture(GL_TEXTURE_2D, m_glTexture[0]);
  23. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yData);
  24. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  25. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  26. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  27. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  28. // u
  29. if (m_glTexture[1] < 0) {
  30. glGenTextures(1, &m_glTexture[1]);
  31. LogE("EGLCore::draw: _utid ", m_glTexture[1]);
  32. }
  33. int w1 = (width + 1) / 2;
  34. int h1 = (height + 1) / 2;
  35. glBindTexture(GL_TEXTURE_2D, m_glTexture[1]);
  36. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w1, h1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uData);
  37. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  38. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  39. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  40. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  41. // v
  42. if (m_glTexture[2] < 0) {
  43. glGenTextures(1, &m_glTexture[2]);
  44. LogE("EGLCore::CreateProgram: _vtid ", m_glTexture[2]);
  45. }
  46. glBindTexture(GL_TEXTURE_2D, m_glTexture[2]);
  47. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w1, h1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vData);
  48. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  49. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  50. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  51. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  52. // draw
  53. // 使用shader程序
  54. glUseProgram(m_program);
  55. // 将最终变换矩阵传入shader程序
  56. glUniformMatrix4fv(mMatrixHandle, 1, false, mMMatrix);
  57. // 顶点位置数据传入着色器
  58. glVertexAttribPointer(_positionHandle, 2, GL_FLOAT, false, 8, vertices);
  59. glEnableVertexAttribArray(_positionHandle);
  60. glVertexAttribPointer(_coordHandle, 2, GL_FLOAT, false, 8, texCoords);
  61. // 允许使用顶点坐标数组
  62. glEnableVertexAttribArray(_coordHandle);
  63. // bind textures
  64. LogE("EGLCore::draw: _textureI:%d;_textureII:%d;_textureIII:%d", _textureI, _textureII, _textureIII);
  65. // 绑定纹理
  66. glActiveTexture(_textureI);
  67. glBindTexture(GL_TEXTURE_2D, m_glTexture[0]);
  68. glUniform1i(_yhandle, _tIindex);
  69. glActiveTexture(_textureII);
  70. glBindTexture(GL_TEXTURE_2D, m_glTexture[1]);
  71. glUniform1i(_uhandle, _tIIindex);
  72. glActiveTexture(_textureIII);
  73. glBindTexture(GL_TEXTURE_2D, m_glTexture[2]);
  74. glUniform1i(_vhandle, _tIIIindex);
  75. // 图形绘制
  76. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  77. // glFinish();
  78. glDisableVertexAttribArray(_positionHandle);
  79. glDisableVertexAttribArray(_coordHandle);
  80. glFlush();
  81. glFinish();
  82. eglSwapBuffers(m_eglDisplay, m_eglSurface);
  83. }

4、测试代码实现

  1. std::string id(idStr);
  2. SRGLRender *render = SRGLRender::GetInstance(id);
  3. if (nullptr != render) {
  4. int width = 960;
  5. int height = 540;
  6. int uWidth = width / 2;
  7. int uHeight = height / 2;
  8. unsigned char *yData = new unsigned char[width * height];
  9. unsigned char *uData = new unsigned char[(width * height) / 2];
  10. unsigned char *vData = new unsigned char[(width * height) / 2];
  11. for (int i = 0; i < width * height; ++i) {
  12. yData[i] = color;
  13. }
  14. // 填充Y数据为红色
  15. for (int i = 0; i < (uWidth * uHeight); ++i) {
  16. uData[i] = color;
  17. vData[i] = color;
  18. }
  19. render->m_eglCore->onRenderData(yData, uData, vData, width, height);
  20. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/314868
推荐阅读
相关标签
  

闽ICP备14008679号