YUV格式讲解并使用ffmpeg生产YUV文件

YUV 格式分析

Y、U、V 各占一个字节

YUV444 : 每4个像素点为一组,这4个像素点包含4个Y、4个U、4个V,每个像素点占用3个字节。

YUV422 : 每4个像素点为一组,这4个像素点包含4个Y、2个U、2个V,每个像素点占用2个字节。

YUV420 : 每4个像素点为一组,这4个像素点包含4个Y、1个U、1个V,每个像素点占用1.5个字节。

H264 和 H265 中默认使用的像素点格式为 YUV420。

ffmpeg工具生成YUV格式的视频素材

SDL播放YUV文件直接渲染 

代码 

SdlQtRgb.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_SdlQtRGB.h"

class SdlQtRGB : public QWidget
{
    Q_OBJECT

public:
    SdlQtRGB(QWidget *parent = Q_NULLPTR);
    ~SdlQtRGB();

private:
    Ui::SdlQtRGBClass ui;

    void timerEvent(QTimerEvent* evt) override;
};

SdlQtRgb.cpp

#include "SdlQtRGB.h"
#include "sdl/SDL.h"
#include <iostream>
#include <fstream>
#include <QMessageBox>

#pragma comment(lib, "SDL2.lib")
using namespace std;

static SDL_Window* sdl_win = nullptr;
static SDL_Renderer* sdl_render = nullptr;
static SDL_Texture* sdl_texture = nullptr;
static unsigned char* yuv = nullptr;
static int sdl_width = 0;
static int sdl_height = 0;
static int pixel_size = 2;
static ifstream yuv_file;

void SdlQtRGB::timerEvent(QTimerEvent* evt)
{
    SDL_Rect rect;

    rect.x = 0;
    rect.y = 0;
    rect.w = sdl_width;
    rect.h = sdl_height;

    yuv_file.read((char*)yuv, sdl_width * sdl_height * 1.5);  // 读取一帧数据

    SDL_RenderClear(sdl_render);
    // YUV 平面存储方式, RGB 交叉存储方式
    // YYYYYYYY UU VV
    SDL_UpdateTexture(sdl_texture, nullptr, yuv,   
        sdl_width  // 一行 Y 的字节数
    );
    SDL_RenderCopy(sdl_render, sdl_texture, nullptr, &rect);
    SDL_RenderPresent(sdl_render);
}

SdlQtRGB::SdlQtRGB(QWidget *parent)
    : QWidget(parent)
{
    yuv_file.open("400_300_25.yuv", ios::in | ios::binary);

    if (!yuv_file)
    {
        QMessageBox::information(this, "information", "open 400_300_25.yuv failed!");

        return;
    }

    ui.setupUi(this);
 
    sdl_width = 400;
    sdl_height = 300;

    ui.label->resize(400, 300);

    // 初始化 SDL
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        cout << SDL_GetError() << endl;
    }

    // 创建窗口
    sdl_win = SDL_CreateWindowFrom((void*)ui.label->winId());  // 通过 Qt 控件中的句柄来创建窗口

    if (!sdl_win)
    {
        cout << SDL_GetError() << endl;
    }

    // 创建渲染器
    sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED);

    if (!sdl_render)
    {
        cout << SDL_GetError() << endl;
    }

    // 创建材质
    sdl_texture = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, sdl_width, sdl_height);

    if (!sdl_texture)
    {
        cout << SDL_GetError() << endl;
    }

    yuv = new unsigned char[sdl_width * sdl_height * pixel_size];

    startTimer(10);  // 每过10ms就会调用一次 timerEvent,1s大约有100帧的图像
}

SdlQtRGB::~SdlQtRGB()
{
    delete[] yuv;
}

注意:YUV 和 RGB 的存储方式不同,YUV 为平面存储,RGB 为交叉存储。

显示效果如下:

 以 YUV 的方式一帧一帧的方式显示了图片。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值