使用SDL显示YUV数据
宏定义
extern "C" {
#include <libavutil/imgutils.h>
}
#define RET(judge, func) \
if (judge) { \
qDebug() << #func << "error" << SDL_GetError(); \
return; \
}
static const std::map<AVPixelFormat, SDL_PixelFormatEnum>
PIXEL_FORMAT_MAP = {
{AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV},
{AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2},
{AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN}
};
变量定义
SDL_Window *_window = nullptr;
SDL_Renderer *_renderer = nullptr;
SDL_Texture *_texture = nullptr;
QFile _file;
int _timerId = 0;
State _state = Stopped;
Yuv _yuv;
bool _playing;
创建窗口
// 创建窗口
_window = SDL_CreateWindowFrom((void *)winId());
RET(!_window, SDL_CreateWindow);
创建渲染上下文
// 创建渲染上下文
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!_renderer) {
_renderer = SDL_CreateRenderer(_window, -1, 0);
RET(!_renderer, SDL_CreateRenderer);
}
创建纹理
// 创建纹理
_texture = SDL_CreateTexture(_renderer,
PIXEL_FORMAT_MAP.find(yuv.pixelFormat)->second,
SDL_TEXTUREACCESS_STREAMING,
yuv.width,
yuv.height);
RET(!_texture, SDL_CreateTextureFromSurface);
打开文件
// 打开文件
_file.setFileName(yuv.filename);
if (!_file.open(QFile::ReadOnly)) {
qDebug() << "file open error" << yuv.filename;
}
渲染
// 图片大小
int imgSize = av_image_get_buffer_size(_yuv.pixelFormat,
_yuv.width,
_yuv.height,
1);
char data[imgSize];
if (_file.read(data, imgSize) > 0) {
// 将YUV的像素数据填充到texture
RET(SDL_UpdateTexture(_texture, nullptr, data, _yuv.width), SDL_UpdateTexture);
// 设置绘制颜色 (画笔颜色)
RET(SDL_SetRenderDrawColor(_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE), SDL_SetRenderDrawColor);
//用绘制颜色 (画笔颜色) 清除渲染目标
RET(SDL_RenderClear(_renderer), SDL_RenderClear);
// 拷贝纹理数据到渲染目标(默认是window)
RET(SDL_RenderCopy(_renderer, _texture, nullptr, nullptr), SDL_RenderCopy);
// 更新所有的渲染操作到屏幕上
SDL_RenderPresent(_renderer);
} else {
// 文件数据已经读取
killTimer(_timerId);
}
对应的播放、暂停、播放状态
void YuvPlayer::play() {
_timerId = startTimer(1000 / _yuv.fps);
_state = YuvPlayer::Playing;
}
void YuvPlayer::pause() {
if (_timerId) {
killTimer(_timerId);
}
_state = YuvPlayer::Paused;
}
void YuvPlayer::stop() {
if (_timerId) {
killTimer(_timerId);
}
_state = YuvPlayer::Stopped;
}
bool YuvPlayer::isPlaying() {
return _state == YuvPlayer::Playing;
}
YuvPlayer::State YuvPlayer::getstate() {
return _state;
}
释放资源
YuvPlayer::~YuvPlayer() {
_file.close();
SDL_DestroyTexture(_texture);
SDL_DestroyRenderer(_renderer);
SDL_DestroyWindow(_window);
}