音视频技术应用(8)-SDL渲染RGB数据到Qt的控件,并能够通过定时器刷新
1. 在VS2019中新建一个Qt Widget Application 项目:
右键项目属性,设置所需要的头文件路径,库文件路径,工作目录等,这里省略。
2. 双击sdlqtrgb.ui 文件,打开设计器,为当前窗口添加一个Label:
添加label: 从左侧的Display Widgets 窗口中拖动一个Label标签到当前的窗口中,然后点击该Label, 在右侧的属性编辑器中设置该Label的宽高分别为400*300,未来SDL 渲染的RGB数据将会直接渲染到这个控件上。
注意objectName栏它的名字,它的名字现在为label
3. 打开 sdlqtrgb.cpp, 添加下列code :
sdlqtrgb.h
#pragma once #include <QtWidgets/QWidget> #include "ui_sdlqtrgb.h" class SDLQtRGB : public QWidget { Q_OBJECT public: SDLQtRGB(QWidget *parent = Q_NULLPTR); // 重写QT的一个定时器函数,在该函数里执行定时操作 void timerEvent(QTimerEvent *ev) override; private: Ui::SDLQtRGBClass ui; };
sdlqtrgb.cpp
#include "sdlqtrgb.h" #include <iostream> #include <sdl/SDL.h> #pragma comment(lib, "SDL2.lib") using namespace std; static int sdl_width = 0; static int sdl_height = 0; static SDL_Window* sdl_window = NULL; static SDL_Renderer* sdl_render = NULL; static SDL_Texture* sdl_texture = NULL; static int pixel_size = 4; // 材质的像素格式是ARGB8888, 占4字节 static unsigned char* rgb = NULL; SDLQtRGB::SDLQtRGB(QWidget *parent) : QWidget(parent) { ui.setupUi(this); // 取得label的宽高 sdl_width = ui.label->width(); sdl_height = ui.label->height(); // 1. 初始化SDL if (SDL_Init(SDL_INIT_VIDEO)) { cout << SDL_GetError() << endl; return; } // 2. 创建窗口, 这里取得label所对应的窗口句柄 sdl_window = SDL_CreateWindowFrom((void*)ui.label->winId()); if (!sdl_window) { cout << SDL_GetError() << endl; return; } // 3. 创建渲染器 sdl_render = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED); if (!sdl_render) { cout << SDL_GetError() << endl; return; } // 4. 根据label控件的宽高来创建材质 sdl_texture = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, sdl_width, sdl_height ); if (!sdl_texture) { cout << SDL_GetError() << endl; return; } // 申请一块内存空间用于存放RGB数据 rgb = new unsigned char[sdl_width * sdl_height * pixel_size]; // 每隔10ms调用一次timerEvent函数 startTimer(10); } void SDLQtRGB::timerEvent(QTimerEvent* ev) { static unsigned char tmp = 255; tmp--; // 动态的更新RGB图像 for (int j = 0; j < sdl_height; j++) { int begin = j * sdl_width * pixel_size; for (int i = 0; i < sdl_width * pixel_size; i += 4) { rgb[begin + i] = 0; // B rgb[begin + i + 1] = tmp; // G rgb[begin + i + 2] = 0; // R rgb[begin + i + 3] = 0; // A } } // 5. 动态更新材质信息 if (SDL_UpdateTexture(sdl_texture, NULL, rgb, sdl_width * pixel_size)) { cout << SDL_GetError() << endl; return; } // 6. 清理屏幕 if (SDL_RenderClear(sdl_render)) { cout << SDL_GetError() << endl; return; } // 7. 复制材质到渲染器对象 SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = sdl_width; rect.h = sdl_height; if (SDL_RenderCopy(sdl_render, sdl_texture, NULL, &rect)) { cout << SDL_GetError() << endl; return; } // 8. 执行渲染操作 SDL_RenderPresent(sdl_render); }
运行:
可以看到,已经成功地把绿色的图像渲染到窗口中label控件所在的位置。
<完>