1、什么是SDL
2、SDL视频显示流程如下:
3、SDL视频显示函数
SDL_Init(): 初始化SDL系统
SDL_CreateWindow(): 创建窗口 SDL_Window
SDL_CreateRenderer(): 创建渲染器 SDL_Renderer
SDL_CreateTexture(): 创建纹理 SDL_Texture
SDL_UpdateTexture(): 设置纹理的数据
SDL_RenderClear(): 清除渲染器的内容
SDL_RenderCopy(): 将纹理的数据拷贝给渲染器
SDL_RenderPresent(): 显示
SDL_Delay(): 工具函数,用于延时。
SDL_Quit(): 退出SDL系统
4、SDL数据结构
SDL_Window: 代表了一个“窗口”
SDL_Renderer: 代表了一个“渲染器”
SDL_Texture: 代表了一个“纹理”
SDL_Rect: 一个简单的矩形结构
5、QT实现
5.1 UI设计
在UI中拖入一个label 重命名为videoLabel
更改大小为400*300
6、代码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <SDL.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
//重载
void timerEvent(QTimerEvent *ev) override;
int testSDL();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
//报错提示,需要加入这个文件
#define __STDC_CONSTANT_MACROS
extern "C"{
//指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/avconfig.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
//引入SDL2的头文件
#include <SDL.h>
}
//在头文件的下面要加入这条语句:#undef main,这是因为SDL中的 SDL_main.h已经定义了main
#undef main
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
//显示当前ffmpeg的版本号--用来测试环境是否搭建成功
qDebug() << av_version_info();
/*测试代码*/
// if(SDL_Init(SDL_INIT_VIDEO)){
// qDebug() << "Could not initialize SDL"<<SDL_GetError();
// }else{
// qDebug() <<"Success init SDL";
// }
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
//绘制图像
#include <QPainter>
//使用QPaint绘制QImage
#include <QImage>
//定义窗口大小
static int sdl_width = 0;
static int sdl_height = 0;
//SDL 窗口
static SDL_Window *sdl_win = NULL;
//渲染器
static SDL_Renderer *sdl_render = NULL;
//材质
static SDL_Texture *sdl_texture = NULL;
//存放材质的地方
static unsigned char *rgb = NULL;
//像素的大小
static unsigned int pix_size = 4;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
sdl_width = ui->videoLabel->width();
sdl_height = ui->videoLabel->height();
//改变窗口大小
//resize(sdl_width,sdl_height);
testSDL();
}
MainWindow::~MainWindow()
{
delete ui;
}
//定时器
void MainWindow::timerEvent(QTimerEvent *ev)
{
static unsigned char tmp = 255;
tmp--;
for (int j = 0; j < sdl_height; j++)
{
int b = j * sdl_width * pix_size;
for (int i = 0; i < sdl_width*pix_size; i += pix_size)
{
rgb[b + i] = 0; //B
rgb[b + i + 1] = 0; //G
rgb[b + i + 2] = tmp; //R
rgb[b + i + 3] = 0; //A
}
}
//5 内存数据写入材质
SDL_UpdateTexture(sdl_texture, NULL, rgb, sdl_width * pix_size/*一行的大小*/);
//6 清理屏幕
SDL_RenderClear(sdl_render);
SDL_Rect sdl_rect;
sdl_rect.x = 0;
sdl_rect.y = 0;
sdl_rect.w = sdl_width;
sdl_rect.h = sdl_height;
//7 复制材质到渲染器
SDL_RenderCopy(sdl_render, sdl_texture,
NULL,//原图位置和尺寸
&sdl_rect//目标位置和尺寸
);
//8 渲染
SDL_RenderPresent(sdl_render);
}
int MainWindow::testSDL()
{
/*******************************SDL*************************************/
//1 初始化SDL video库
if (SDL_Init(SDL_INIT_VIDEO))
{
//qDebug() << SDL_GetError();
return -1;
}
//2 生成SDL并渲染到QT的label
//ui->videoLabel->winId():代表窗口句柄
sdl_win = SDL_CreateWindowFrom((void*)ui->videoLabel->winId());
if (!sdl_win)
{
//qDebug() << SDL_GetError();
return -2;
}
//3 生成渲染器
sdl_render = SDL_CreateRenderer(sdl_win/*SDL 窗口*/, -1/*渲染指定的设备 -1:使用默认的*/, SDL_RENDERER_ACCELERATED/*渲染类型:硬件加速*/);
if (!sdl_render)
{
//qDebug() << SDL_GetError();
return -3;
}
//4 生成材质,材质大小要和控件label大小一致
sdl_texture = SDL_CreateTexture(
sdl_render/*渲染器*/,
SDL_PIXELFORMAT_ARGB8888/*像素格式*/,
SDL_TEXTUREACCESS_STREAMING/*渲染格式:可加锁*/,
sdl_width/*宽,根据label进行创建的*/,
sdl_height/*高*/
);
if (!sdl_texture)
{
//qDebug() << SDL_GetError();
return -4;
}
//申请图像的数据控件
rgb = new unsigned char[sdl_height*sdl_width*4];
//开启定时器
startTimer(10);
}