视频解码器输出 YUV420P 格式,XGE 提供专用纹理类型直接在 GPU 端完成 YUV→RGB 转换,避免 CPU 转换开销。
YUV420P 是视频编码的标准像素格式:Y 平面(亮度)+ U/V 平面(色度,各为 Y 的 1/4 尺寸)。 XGE 的 YUV 纹理在 GPU shader 中完成色彩空间转换,每帧只需上传三个平面数据。
| 函数 | 说明 |
|---|---|
int xgeTextureCreateYUV420P(xge_texture pTexture, int iWidth, int iHeight) | 创建 YUV420P 纹理 |
int xgeTextureUpdateYUV420P(xge_texture pTexture, const void* pY, int iStrideY, const void* pU, int iStrideU, const void* pV, int iStrideV) | 更新三平面数据 |
gcc -O2 -I. -o ch94.exe ch94_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch94.exe
// 创建 YUV 纹理(视频分辨率)
xge_texture_t videoTex;
xgeTextureCreateYUV420P(&videoTex, 1920, 1080);
// 每帧:从解码器获取 YUV 平面
const uint8_t* pY = frame->data[0];
const uint8_t* pU = frame->data[1];
const uint8_t* pV = frame->data[2];
int strideY = frame->linesize[0];
int strideU = frame->linesize[1];
int strideV = frame->linesize[2];
// 上传到 GPU(内部完成 YUV→RGB)
xgeTextureUpdateYUV420P(&videoTex,
pY, strideY, pU, strideU, pV, strideV);
// 绘制视频帧
xgeDraw(&videoTex, 0, 0);将以下代码保存为 ch94_main.c,编译后运行即可看到 YUV 纹理更新与渲染效果(模拟视频帧):
#include "xge.h"
#include <stdlib.h>
#include <math.h>
#define VID_W 320
#define VID_H 240
static xge_texture_t g_videoTex;
static float g_time = 0.0f;
static xge_font g_font = NULL;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
g_time += 0.016f;
// 模拟生成 YUV 平面数据(彩条动画)
static uint8_t planeY[VID_H * VID_W];
static uint8_t planeU[VID_H/2 * VID_W/2];
static uint8_t planeV[VID_H/2 * VID_W/2];
int shift = (int)(g_time * 60.0f) % VID_W;
for (int y = 0; y < VID_H; y++)
for (int x = 0; x < VID_W; x++)
planeY[y * VID_W + x] =
(uint8_t)((x + shift) % 256);
for (int y = 0; y < VID_H/2; y++)
for (int x = 0; x < VID_W/2; x++) {
planeU[y * VID_W/2 + x] = 128;
planeV[y * VID_W/2 + x] =
(uint8_t)(128 + 80 * sinf(g_time + x*0.05f));
}
// 上传 YUV 数据到 GPU
xgeTextureUpdateYUV420P(&g_videoTex,
planeY, VID_W,
planeU, VID_W/2,
planeV, VID_W/2);
// 绘制视频帧(放大到窗口)
xgeDraw(&g_videoTex, 0.0f, 0.0f);
xgeTextDraw(g_font, "YUV420P Video Simulation",
10.0f, 10.0f, 0xFFFFFFFF)
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch94 - YUV Video Texture";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);
// 创建 YUV420P 纹理
xgeTextureCreateYUV420P(&g_videoTex, VID_W, VID_H);
xgeRun(onFrame, NULL);
xgeTextureFree(&g_videoTex);
xgeFontFree(g_font);
xgeUnit();
return 0;
}