Qt+SDL播放YUV视频文件

播放一个yuv420p格式的文件
yuv的格式与rgb格式的存储方式不同
yuv数据是 yyyyyyyy uu vv 的存储
rgb是rgba rgba rgba 存储
同样一帧图像 yuv420会比rgb数据更小
读取时就要注意数据存储格式不同,数据大小也不同
直接上代码
sdl_qt_play_yuv.h

#include <QtWidgets/QWidget>
#include <SDL2/SDL.h>
#include <fstream>
#include "ui_sdl_qt_play_yuv.h"

class sdl_qt_play_yuv : public QWidget
{
    Q_OBJECT

public:
    sdl_qt_play_yuv(QWidget *parent = Q_NULLPTR);
    void timerEvent(QTimerEvent* ev) override;

private:
    Ui::sdl_qt_rgbClass ui;
    SDL_Window* sdl_window;
    SDL_Renderer* sdl_render;
    SDL_Texture* sdl_texture;
    unsigned char* yuv_data;
    std::ifstream yuv_file;
};

sdl_qt_play_yuv.cpp

#include "sdl_qt_play_yuv.h"
#include <QMessageBox>
#include <QDebug>
#define PIX_SIZE 2
#pragma comment(lib, "SDL2.lib")
void sdl_qt_play_yuv::timerEvent(QTimerEvent* ev)
{
    yuv_file.read((char*)yuv_data, ui.label->width() * ui.label->height()*1.5);//一帧图像的yuv420的数据量就是像素的1.5倍
    //数据复制到材质 yuv平面存储 yyyyyyyy  uu  vv
    SDL_UpdateTexture(sdl_texture, nullptr, yuv_data, ui.label->width());
    SDL_RenderClear(sdl_render);
    //材质写入渲染
    SDL_Rect sdl_rect;
    sdl_rect.x = 0;
    sdl_rect.y = 0;
    sdl_rect.w = ui.label->width();
    sdl_rect.h = ui.label->height();
    SDL_RenderCopy(sdl_render, sdl_texture,
        nullptr,//原图位置和尺寸
        &sdl_rect//目标位置和尺寸
    );
    //开始渲染
    SDL_RenderPresent(sdl_render);
    if (yuv_file.eof()) {
        yuv_file.clear();
        yuv_file.seekg(0);
    }    
}
sdl_qt_play_yuv::sdl_qt_play_yuv(QWidget *parent)
    : QWidget(parent)
{
    yuv_file.open("input.yuv", std::ios_base::binary);//打开一个400*300的yuv视频文件
    if (!yuv_file) {
        QMessageBox::information(this, "", "open yuv failed!");
        return;
    }
    ui.setupUi(this);
    ui.label->resize(400, 300);//yuv文件并没有视频的宽高数据, 这里手动指定

    SDL_Init(SDL_INIT_VIDEO);
    //创建窗口
    sdl_window = SDL_CreateWindowFrom((void*)ui.label->winId());
    if (!sdl_window) {
        exit(-1);
    }
    //创建渲染器
    sdl_render = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED);
    if (!sdl_render) {
        exit(-2);
    }
    //创建材质 设置成支持yuv格式
    sdl_texture = SDL_CreateTexture(sdl_render,
        SDL_PIXELFORMAT_IYUV,
        SDL_TEXTUREACCESS_STREAMING,
        ui.label->width(),
        ui.label->height());
    if (!sdl_texture) {
        exit(-3);
    }
    //清屏
    SDL_RenderClear(sdl_render);
    
    yuv_data = new unsigned char[ui.label->width() * ui.label->height() * PIX_SIZE];
    startTimer(5);//利用定时器粗略控制帧率
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值