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
主线程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
类来实现。该类提供了创建和管理图形表面的功能,适用于视频播放、相机预览等场景。
具体步骤如下:
- 创建
Surface
对象并设置格式和分辨率。 - 获取
BufferProducer
接口并申请GraphicBuffer
。 - 将YUV数据写入
GraphicBuffer
。 - 调用
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数据。通过Surface
和BufferProducer
接口,可以高效地将YUV数据渲染到屏幕上。