01、YUV数据渲染到SDL窗口

1、什么是YUV

YUV是一种表示颜色的模型。

通常我们说的YUV是指YCbCr,Y:亮度分量,Cb:蓝色色度分量,Cr:红色色度分量,是标准YUV的一个翻版

2、YUV的分类标准

        由于人眼对 Y 的敏感度远超于对 U 和 V 的敏感,所以有时候可以多个 Y 分量共用一组 UV,这样既可以极大得节省空间,又可以不太损失质量。这三种格式就是按照人眼的特性制定的。

具体的细分种类看这个

 https://www.jianshu.com/p/538ee63f4c1c

YUV各格式详解和所占的空间大小总结 YUV420P YUV420P YUV420SP YUV420SP packed planar I420 YV12 NV12 NV21区别_Aero Auto的博客-CSDN博客_yuv大小计算

444:每个Y有一个U,一个V。
422: 每两个Y有一个U,一个V。 水平方向2:1,UV缩减一半。
420: 每4个Y才有一个U和V。在422基础上,垂直方向也缩减一半。

P:
Planar,按平面分开放,先把U存放完后,再存放V。U是连续的,V也是连续的。YYYYYUUUUUVVVV
SP:
semi-Planar 半平面,只有Y数据一个平面,UV数据合用一个平面。YYYYYUVUVUV…

Packed:
打包,YUV不各自成平面,而是形成YUV YUV这样的一个个包。
Interleaved:
YUV全部由分开交错存放,YUV YUV YUV
个人理解Packed和Interleaved是一回事。

空间占用的示例代码

以上了解之后,大小计算就没有悬念了。
RGBA8888:长x宽x4 每点有ARGB四个量: (长x宽)x4
YUV444:长x宽x3 每点有YUV三个量: (长x宽)x3
YUV422:长x宽x2 每点有Y三个量:UV要除2,长x宽+(长x宽+长x宽)/2=长x宽x2
YUV420:长x宽x3/2 每点有Y三个量:UV要除4,长x宽+(长x宽+长x宽)/2/2=长x宽+(长x宽)/2=长x宽x3/2


typedef enum PixelFmt
{
    PIXEL_YUV420SP,
    PIXEL_YVU420SP,
    PIXEL_YUV420P,
    PIXEL_YVU420P,
    PIXEL_YUV422SP,
    PIXEL_YVU422SP,
    PIXEL_YUV422P,
    PIXEL_YVU422P,
    PIXEL_YUYV422,
    PIXEL_UYVY422,
    PIXEL_YVYU422,
    PIXEL_VYUY422,
    PIXEL_ARGB,
    PIXEL_RGBA,
    PIXEL_ABGR,
    PIXEL_BGRA,
} PixelFmt;

int getFrameBitSize(int w,int h,PixelFmt fmt)
{
    int pixelNum = w*h;
    int frameBitSize = 0;
    switch(fmt)
    {
        case PIXEL_YUV420SP...PIXEL_YVU420P:
            frameBitSize = pixelNum*3/2;
            break;
        case PIXEL_YUV422SP...PIXEL_VYUY422:
            frameBitSize = pixelNum*2;
            break;
        case PIXEL_ARGB...PIXEL_BGRA:
            frameBitSize = pixelNum*4;
            break;
    }
    return frameBitSize;
}

 3、SDL视频显示

3.1 显示流程图

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SDL2.0 支持渲染 YUV4:2:0 格式的视频,需要使用 SDL_Texture 和 SDL_RenderCopy 函数来实现。 以下是一个简单的示例代码: ```c #include <SDL2/SDL.h> #include <stdio.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; int main(int argc, char* argv[]) { SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Texture* texture = NULL; if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); return 1; } window = SDL_CreateWindow("YUV4:2:0 Video", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == NULL) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); return 1; } renderer = SDL_CreateRenderer(window, -1, 0); if (renderer == NULL) { printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError()); return 1; } texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT); if (texture == NULL) { printf("Texture could not be created! SDL_Error: %s\n", SDL_GetError()); return 1; } // YUV data Uint8* yPlane = NULL; Uint8* uPlane = NULL; Uint8* vPlane = NULL; int yPitch = 0; int uPitch = 0; int vPitch = 0; int w = 0; int h = 0; // read YUV file FILE* fp = fopen("video.yuv", "rb"); if (fp == NULL) { printf("Could not open YUV file!\n"); return 1; } // allocate memory for YUV data int bufferSize = SCREEN_WIDTH * SCREEN_HEIGHT * 3 / 2; Uint8* buffer = (Uint8*)malloc(bufferSize); // main loop SDL_Event event; bool quit = false; while (!quit) { while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { quit = true; } } // read YUV data if (fread(buffer, 1, bufferSize, fp) != bufferSize) { // end of file rewind(fp); } // set YUV data yPlane = buffer; uPlane = yPlane + SCREEN_WIDTH * SCREEN_HEIGHT; vPlane = uPlane + SCREEN_WIDTH * SCREEN_HEIGHT / 4; yPitch = SCREEN_WIDTH; uPitch = SCREEN_WIDTH / 2; vPitch = SCREEN_WIDTH / 2; w = SCREEN_WIDTH; h = SCREEN_HEIGHT; // update texture SDL_UpdateYUVTexture(texture, NULL, yPlane, yPitch, uPlane, uPitch, vPlane, vPitch); // clear screen SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); // render texture SDL_RenderCopy(renderer, texture, NULL, NULL); // update screen SDL_RenderPresent(renderer); } // free memory free(buffer); // cleanup SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; } ``` 在代码中,我们首先创建一个 SDL 窗口渲染器。然后,使用 SDL_CreateTexture 函数创建一个 YV12 格式的纹理。接下来,读取 YUV 文件,并将数据设置到纹理中。在主循环中,使用 SDL_RenderCopy 函数将纹理渲染到屏幕上。最后,记得在程序结束前释放所有内存和资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值