ffmpeg之显示一个yuv照片

显示YUV图片的步骤

1.初始化SDL库

  • 目的:确保SDL库正确初始化,以便可以使用其窗口、渲染和事件处理功能。
  • 操作:调用 ·SDL_Init(SDL_INIT_VIDEO) 来初始化SDL的视频子系统。

2.创建窗口用于显示YUV图像:

  • 目的:创建一个窗口作为显示YUV图像的目标。
  • 操作:使用 SDL_CreateWindow 创建一个SDL窗口,并指定窗口的位置、大小和标志(如是否全屏等)。你可以根据需要自定义窗口的属性。
  1. 创建渲染器:
  • 目的:创建一个渲染器,用于在窗口中绘制图像。
  • 操作:使用 SDL_CreateRenderer 创建一个渲染器。可以选择硬件加速和垂直同步选项以提高性能和视觉质量。
  1. 读取YUV文件并准备数据:
  • 目的:从YUV文件中读取原始像素数据,并准备好这些数据以便后续处理。
  • 操作:打开YUV文件,读取Y、U、V平面的数据到内存中。这一步骤通常包括分配适当的缓冲区来存储YUV数据。
  1. 创建纹理并设置颜色格式:
  • 目的:创建一个纹理对象,用于在GPU中存储图像数据,并设置纹理的颜色格式(如YUV420P)。
  • 操作:使用 SDL_CreateTexture 创建一个纹理,指定像素格式(例如 SDL_PIXELFORMAT_YV12 或 SDL_PIXELFORMAT_IYUV),以及访问模式(如 SDL_TEXTUREACCESS_STREAMING)。
  1. 将YUV数据更新到纹理:
  • 目的:将读取的YUV数据复制到纹理中,以便可以在渲染时使用。
  • 操作:使用 SDL_UpdateYUVTexture 函数将Y、U、V平面的数据分别更新到纹理中。
  1. 渲染纹理到屏幕上:
  • 目的:将纹理绘制到窗口的渲染层上,完成图像的显示。
  • 操作:调用 SDL_RenderClear 清除渲染目标,然后使用 SDL_RenderCopy 将纹理复制到渲染器的目标区域,最后调用 SDL_RenderPresent 刷新屏幕以显示图像。
  1. 处理事件和清理资源:
  • 目的:处理用户输入或事件,并释放所有分配的资源。
  • 操作:使用 SDL_PollEvent 处理事件(如关闭窗口),并在程序结束时调用相应的销毁函数(如 SDL_DestroyTexture、SDL_DestroyRenderer 和 SDL_DestroyWindow),最后调用 SDL_Quit 退出SDL库。

代码用例:

cpp 复制代码
void playThread::run()
{
    //创建窗口
    SDL_Window *window = nullptr;

    //渲染上下文
    SDL_Renderer *renderer = nullptr;

    //纹理(直接跟特定驱动程序相关的像素数据)
    SDL_Texture *texture = nullptr;

    //文件
    QFile file(FILENAME);

    //初始化子系统
    END(SDL_Init(SDL_INIT_VIDEO),SDL_Init);

    //创建一个窗口
    //标题-X-Y-width-height
    window = SDL_CreateWindow("SDL显示YUV图片",
                              SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED,
                              IMG_W,IMG_H,
                              SDL_WINDOW_SHOWN);
    END(!window,SDL_CreateWindow);

    //创建渲染上下文--用于渲染图形到窗口
    //这SDL_RENDERER_ACCELERATED -- 个标志告诉 SDL 尝试创建一个使用硬件加速的渲染器
    //SDL_RENDERER_PRESENTVSYNC -- 这个标志使渲染器的呈现操作同步到显示器的垂直同步(VSync)
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    //如果创建失败
    if(!renderer)
    {
        renderer = SDL_CreateRenderer(window,-1,0);
        END(!renderer,SDL_CreateRenderer);
    }

    //创建纹理t
    texture = SDL_CreateTexture(renderer,
                                PIXEL_FORMAT,
                                SDL_TEXTUREACCESS_STREAMING,
                                IMG_W,IMG_H);
    END(!texture,SDL_CreateTextureFromSurface);


    //打开YUV文件
    if(!file.open(QFile::ReadOnly))
    {
        qDebug() << "file open error" << FILENAME;
        goto end;
    }

    //将YUV的像素数据填充到texture -- nullptr空表示整个texture都是
    END(SDL_UpdateTexture(texture,nullptr,file.readAll().data(),IMG_W),SDL_UpdateTexture);

    //设置绘制颜色(画笔颜色)
    SDL_SetRenderDrawColor(renderer,0,0,0,SDL_ALPHA_OPAQUE);

    //用绘制颜色(画笔颜色)清除渲染目标---也就是覆盖
    SDL_RenderClear(renderer);

    //拷贝纹理数据到渲染目标(默认时window)
    END(SDL_RenderCopy(renderer,texture,nullptr,nullptr),SDL_RenderCopy);

    //更新所有的渲染操作到屏幕上
    SDL_RenderPresent(renderer);
    SDL_Delay(2000);

    end:
    file.close();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyTexture(texture);
    SDL_DestroyWindow(window);
    SDL_Quit();//初始化子系统后必须做一个退出操作
}

用例输出图:

如何自定义显示窗口呢?

首先我们在create窗口的时候,我们可以通过winId来设置的它的显示窗口,如下例子所示:

在进行点击按钮显示的时候,将显示窗口目标的winId传给create窗口。

cpp 复制代码
void MainWindow::on_pushButton_clicked()
{
    //playThread * pt = new playThread((void *)ui->label->winId(),this);
    playThread * pt = new playThread((void *)_widget->winId(),this);
    pt->start();

}
cpp 复制代码
oid playThread::run()
{
    //创建窗口
    SDL_Window *window = nullptr;

    //渲染上下文
    SDL_Renderer *renderer = nullptr;

    //纹理(直接跟特定驱动程序相关的像素数据)
    SDL_Texture *texture = nullptr;

    //文件
    QFile file(FILENAME);

    //初始化子系统
    END(SDL_Init(SDL_INIT_VIDEO),SDL_Init);

    //创建一个窗口
    //标题-X-Y-width-height
    window = SDL_CreateWindowFrom(_winId);
    END(!window,SDL_CreateWindow);

    //创建渲染上下文--用于渲染图形到窗口
    //这SDL_RENDERER_ACCELERATED -- 个标志告诉 SDL 尝试创建一个使用硬件加速的渲染器
    //SDL_RENDERER_PRESENTVSYNC -- 这个标志使渲染器的呈现操作同步到显示器的垂直同步(VSync)
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    //如果创建失败
    if(!renderer)
    {
        renderer = SDL_CreateRenderer(window,-1,0);
        END(!renderer,SDL_CreateRenderer);
    }

    //创建纹理t
    texture = SDL_CreateTexture(renderer,
                                PIXEL_FORMAT,
                                SDL_TEXTUREACCESS_STREAMING,
                                IMG_W,IMG_H);
    END(!texture,SDL_CreateTextureFromSurface);


    //打开YUV文件
    if(!file.open(QFile::ReadOnly))
    {
        qDebug() << "file open error" << FILENAME;
        goto end;
    }

    //将YUV的像素数据填充到texture -- nullptr空表示整个texture都是
    END(SDL_UpdateTexture(texture,nullptr,file.readAll().data(),IMG_W),SDL_UpdateTexture);

    //设置绘制颜色(画笔颜色)
    SDL_SetRenderDrawColor(renderer,0,0,0,SDL_ALPHA_OPAQUE);

    //用绘制颜色(画笔颜色)清除渲染目标---也就是覆盖
    SDL_RenderClear(renderer);

    //拷贝纹理数据到渲染目标(默认时window)
    END(SDL_RenderCopy(renderer,texture,nullptr,nullptr),SDL_RenderCopy);

    //更新所有的渲染操作到屏幕上
    SDL_RenderPresent(renderer);
    SDL_Delay(2000);

    end:
    file.close();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyTexture(texture);
    SDL_DestroyWindow(window);
    SDL_Quit();//初始化子系统后必须做一个退出操作
}

用例输出图:

相关推荐
可乐鸡翅yeah_2 小时前
HLS 业务 Referer‑Policy 网页元标签引发播放异常排错
前端·javascript·网络·ffmpeg·php·音视频
开开心心就好1 天前
本地文件搜索工具推荐,占用小速度还快
智能手机·ffmpeg·ocr·word·音视频·网络攻击模型·安全架构
我科绝伦(Huanhuan Zhou)1 天前
oracle坏块导致备份不了
数据库·oracle·ffmpeg
RS迷途小书童1 天前
Python+FFmpeg提取大疆无人机MP4内嵌mov_text遥测SRT字幕并做完整性校验
python·ffmpeg·大疆·srt字幕·dji
开开心心就好1 天前
视频压缩工具推荐,画质效果很能打
智能手机·ffmpeg·ocr·word·排序算法·音视频·散列表
可乐鸡翅yeah_2 天前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
redfred2 天前
HyperFrames 部署教程:5.6 万 Star 开源「写 HTML 出视频」框架,Windows 从零上手(CLI 三条命令 + 7 个避坑)
ffmpeg·开源·自动化·html·音视频
Arcai10242 天前
PostgreSQL数据备份和恢复完全指南
数据库·postgresql·ffmpeg·备份一体机·备份软件·smartstor·智备科技
可乐鸡翅yeah_3 天前
FFmpeg 生成 HLS 独立分片 independent‑segments 参数到底有什么用
javascript·ffmpeg·音视频·safari·m3u8
企业数字化笔记3 天前
视觉处理为什么会慢?解码、预处理、模型推理、后处理和编码的性能拆解
ffmpeg·gpu算力