HarmonyOS 鸿蒙Next显示yuv

HarmonyOS 鸿蒙Next显示yuv 我使用Napi XComponent显示相机yuv数据时候,由于需要循环获取相机的yuv数据,写了一个while循环来获取数据,会提示THREAD_BLOCK_6S

部分代码

IndexYUV.ets

XComponent({
  id: Common.YUV_XCOMPONENT_ID,
  type: XComponentType.SURFACE,
  libraryname: Common.LIBRARY_NAME
})
  .onLoad((xComponentContext?: object | Record<string, () => void>) => {
    if (xComponentContext) {
      this.xComponentContext = xComponentContext as Record<string, () => void>;
      this.xComponentContext.loadYuv();
    }
  })

egl_core.cpp

std::thread EGLCore::ReadYuvFile() {
  while (1) {
    libyuv::I420Rotate(r_buf[0], width, r_buf[1], width >> 1, r_buf[2], width >> 1, m_buf[0], height,
                       m_buf[1], height >> 1, m_buf[2], height >> 1, width, height, libyuv::kRotate270);

    YuvRender(height, width);
    FinishLoad();
  }
}
void EGLCore::YuvRender(int width, int height) {
  // 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(
               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(
               0,
               GL_LUMINANCE,
               width / 2,        // The amount of u data is 1/4 of the screen.
               height / 2,
               0,              
bool EGLCore::FinishLoad() {
  // The gl function has no return value.
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  glFlush();
  glFinish();
  // The window displays, swapping double buffers.
  bool swap = eglSwapBuffers(m_eglDisplay, m_eglSurface);
  m_flag = true;
  return swap;
}

更多关于HarmonyOS 鸿蒙Next显示yuv的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

主线程while(1)肯定的啊,开多个线程来读写,

更多关于HarmonyOS 鸿蒙Next显示yuv的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


EGLCore *w = new EGLCore(); std::thread tw1 = w->ReadYuvFile(); tw1.detach();
我在C++里面启动一个线程,绘制的时候报 02-25 08:41:33.905 7827-7827 C01400/OpenGLWrapper com.icar…fication E <198>GetWrapperDisplay: invalid display pointer. 02-25 08:41:33.905 7827-7827 C01400/OpenGLWrapper com.icar…fication E <36>ValidateDisplay: EGLDislay is invalid.

同事也会报 Reason:THREAD_BLOCK_6S

我想Worker启动一个线程来调用xComponentContext.loadYuv(); ,但是不知道这么传递xComponentContext对象,看介绍好像即使可以传递这个xComponentContext对象,里面的方法在Worker里面也不能使用,

启动线程后需要makecurrent将egl环境绑定到子线程里,eg绘制都需要egl上下文的吧。

直接开着线程,用信号量来通知渲染,接收相机数据应该都是用nativeimage或者nativebuffer的吧,nativeimage直接注册回调来通知egl线程更新并渲染,这些官方好像都有最佳例子的,可以找找看,

显示YUV数据

HarmonyOS 鸿蒙Next显示YUV数据通常涉及使用其图形子系统进行渲染。YUV是一种颜色编码系统,常用于视频处理。在鸿蒙系统中,显示YUV数据可以通过OHOS::Media::Surface类来实现。该类提供了创建和管理图形表面的功能,适用于视频播放、相机预览等场景。

具体步骤如下:

  1. 创建Surface对象并设置格式和分辨率。
  2. 获取BufferProducer接口并申请GraphicBuffer
  3. 将YUV数据写入GraphicBuffer
  4. 调用QueueBuffer方法提交缓冲区。

代码示例:

#include <surface.h>
#include <buffer_producer.h>

void DisplayYUV(const uint8_t* yuvData, int width, int height) {
    OHOS::Media::Surface surface;
    surface.SetWidth(width);
    surface.SetHeight(height);
    surface.SetFormat(OHOS::Media::PIXEL_FMT_YUV420_SP);

    OHOS::sptr<OHOS::IBufferProducer> producer = surface.GetBufferProducer();
    OHOS::sptr<OHOS::GraphicBuffer> buffer = producer->RequestBuffer(width, height, OHOS::Media::PIXEL_FMT_YUV420_SP);

    memcpy(buffer->GetVirAddr(), yuvData, width * height * 3 / 2);

    producer->QueueBuffer(buffer);
}

以上代码展示了如何在鸿蒙系统中显示YUV数据。通过SurfaceBufferProducer接口,可以高效地将YUV数据渲染到屏幕上。

回到顶部