FFmpeg入门详解之120:SDL2.0的编程回顾总结并操练
4.SDL2.0的编程回顾总结并操练
参考课程:“FFmpeg4.3--系列8--SDL2.0小白入门”
SDL2.0知识框架体系
SDL 视频渲染主要涉及到四个对象:
SDL_Window
SDL_Surface
SDL_Render
SDL_Texture
SDL_Event
SDL 视频渲染主要涉及到相关API:
初始化:
SDL_Init(): 初始化SDL。
SDL_CreateWindow(): 创建窗口(Window)。
SDL_CreateRenderer(): 基于窗口创建渲染器(Render)。
SDL_CreateTexture(): 创建纹理(Texture)。
循环渲染数据:
SDL_UpdateTexture(): 设置纹理的数据。
SDL_RenderCopy(): 纹理复制给渲染器。
SDL_RenderPresent(): 显示。
退出:
SDL_DestroyWindow()
SDL_DestroyRenderer();
SDL_DestroyTexture();
SDL_Quit();
SDL 主要涉及到几个扩展库:
SDL_image
SDL_mixer
SDL_ttf
SDL2.0显示一个跳动的方块
1. SDL 视频渲染相关对象
SDL 视频渲染主要涉及到四个对象:SDL_Window、SDL_Render、SDL_Texture和SDL_Surface。
SDL_Window代表的是窗口的逻辑概念,它是存放在主内存中的一个对象。当我们调用SDL API 创建窗口后,它并不会被显示出来。
SDL_Render 是渲染器,它也是主存中的一个对象。对Render操作时实际上分为两个阶段:
渲染阶段。在该阶段,用户可以画各种图形渲染到SDL_Surface或SDL_Texture 中;
显示阶段。参SDL_Texture为数据,通过OpenGL操作GPU,最终将 SDL_Surfce 或SDL_Texture中的数据输出到显示器上。
SDL_Render对象中有一个视频缓冲区,该缓冲区我们称之为SDL_Surface,它是按照像素存放图像的。我们一般把真彩色的像素称为RGB24数据。也就是说,每一个像素由24位组成,每8位代表一种颜色,像素的最终颜色是由RGB三种颜色混合而成的。
SDL_Texture 与SDL_Surface 相似,也是一种缓冲区。只不过它存放的不是真正的像素数据,而是存放的图像的描述信息。这些描述信息通过OpenGL、D3D 或 Metal等技术操作GPU,从而绘制出与SDL_Surface一样的图形,且效率更高。
2. 使用 SDL_Texute 渲染纹理的步骤
SDL提供了操作SDL_Texture的方法,使用SDL_Texute的基本步骤为:
创建一个 SDL_Texture。
渲染 Texture
Destory Texture
3. 使用SDL渲染纹理的核心API
a). 创建 SDL_Texture
SDL_Texture* SDL_CreateTexture(SDL_Renderer* renderer, // 渲染器
Uint32 format,// 渲染数据的格式,如YUV、RGB
int access,// Texture 类型,target、stream
int w,
int h)
下面说明一下重要参数:
format: 指明像素格式,可以是YUV,也可以是RGB
access: 指明Texture的类型。可以是 Stream(视频),也可以是Target一般的类型。
b). 渲染
int SDL_RenderCopy(SDL_Renderer* renderer,
SDL_Texture* texture,
const SDL_Rect* srcrect,
const SDL_Rect* dstrect)
下面说明一下重要参数:
srcrect: 指定 Texture 中要渲染的一部分。如果将 Texture全部输出,可以设置它为 NULL。
dstrect: 指定输出的空间大小。
c). 销毁 SDL_Texture
void SDL_DestroyTexture(SDL_Texture* texture)
纹理渲染实战:
复制代码
// SDL.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
extern "C" {
#include "SDL.h"
}
int main(int argc, char* argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Event event;
SDL_Rect r;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
return 3;
}
window = SDL_CreateWindow("SDL_CreateTexture",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
1024, 768,
SDL_WINDOW_RESIZABLE);
r.w = 100;
r.h = 50;
renderer = SDL_CreateRenderer(window, -1, 0);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1024, 768);
// 跳来跳去的方块
while (1) {
SDL_PollEvent(&event);
if (event.type == SDL_QUIT)
break;
r.x = rand() % 500;
r.y = rand() % 500;
SDL_SetRenderTarget(renderer, texture);
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(renderer);
SDL_RenderDrawRect(renderer, &r);
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0x00);
SDL_RenderFillRect(renderer, &r);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
SDL2.0的事件处理机制与案例实战
各位学员:
非常抱歉,这节课录制到最后两分钟的时候,家里的小宝宝突然跑进来,叫了几声。
给您带来了不便,影响了您的体验,敬请谅解。
梅会东
2021.1.6
事件循环
大多数多媒体程序依靠事件系统来处理输入。
SDL为处理输入事件提供了灵活的API。
本质上,SDL将来自设备(如键盘,鼠标或控制器)的输入记录为事件,将它们存储在“事件队列”中。
您可以将此结构视为等待线 - 事件在线的后面排队并从线的前面取出。
在您的程序中,您将始终拥有一个事件(或“游戏”或“主”)循环来处理这些事件并根据输入运行您的程序。每次运行事件循环时,必须从事件队列中拉出每个事件(按顺序)以处理输入。这是通过函数SDL_PollEvent()完成的。此函数从队列中删除第一个事件,将值复制到SDL_Event类型的参数中。如果事件队列为空,则该函数将返回0。
轮询事件后,您可以在逻辑链中使用它来推断输入内容和响应方式。
SDL_Event ev;
bool running = true;
// Main loop
while ( running ) {
// Event loop
while ( SDL_PolLEvent( &ev ) != 0 ) {
// Test members of ev
}
// Wait before next frame
SDL_Delay(100);
}
SDL_Event
SDL_Event包含任何子事件之一。这可以通过使用联合来实现。union描述了结构中的几个互斥数据成员。这意味着子事件类型都存储在同一个内存中,因此SDL_Event可以灵活而不浪费空间。但是,这个系统使语法稍微笨拙 - 访问子事件数据,首先必须访问SDL_Event中的子事件。
例如,访问SDL_KeyboardEvent ..
SDL_Event evt;
SDL_PollEvent( &evt );
if (evt.type == SDL_KEYDOWN) {
switch ( evt.key.sym.sym ) { // Note evt.key accesses the real data,
// the SDL_KeyboardEvent
// ...
}
}
退出
当用户希望关闭程序时, 您的事件循环将收到SDL_QUIT类型的事件。这包括按下窗口上的“x”,按ALT + F4,或以其他方式请求程序结束。这不包括结束进程或将CTRL + C发送到控制台 - 这些是不受控制的,立即中止。
因此,当您的程序收到SDL_QUIT事件时,它应该正常关闭(或提示用户提供更多信息)。事件的类型可通过其“类型”成员访问。
SDL_Event ev;
bool running = true;
// Main loop
while ( running ) {
// Event loop
while ( SDL_PolLEvent( &ev ) != 0 ) {
// check event type
switch (ev.type) {
case SDL_QUIT:
// shut down
running = false;
break;
}
}
// Wait before next frame
SDL_Delay(100);
}
#include <stdio.h>
#include <SDL.h>
#undef main
int main(int, char**)///main__event2
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("yx3sxmeng", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* surface = SDL_LoadBMP("./Hello_world.bmp");
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
///1. window-->render(GPU, window), surface内存信息(bitmap), texture描述信息(render, bitmap|surface);
///2. SDL事件循环机制
bool quit = false;
SDL_Event ev;
SDL_Rect rect = { 0,0,800,600 };///目标位置大小(x,y, w,h);
int sx = 0, sy = 0;
while (!quit)
{
while (SDL_PollEvent(&ev))
{
switch (ev.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONDOWN:
sx = ev.button.x + rect.x;
sy = ev.button.y + rect.y;
break;
case SDL_MOUSEMOTION:
if (ev.motion.state & SDL_BUTTON_LMASK)
{
rect.x = ev.motion.x - sx;
rect.y = ev.motion.y - sy;
}
break;
case SDL_KEYDOWN:
if (ev.key.keysym.sym == SDLK_LEFT)
{
rect.x -= 10;
printf("SDLK_LEFT...");
}
else if (ev.key.keysym.sym == SDLK_RIGHT)
{
printf("SDLK_RIGHT...");
rect.x += 10;
}
else if (ev.key.keysym.sym == SDLK_UP)
{
printf("SDLK_UP...");
rect.w += 10;
rect.h += 10;
}
else if (ev.key.keysym.sym == SDLK_DOWN)
{
printf("SDLK_DOWN...");
rect.w -= 10;
rect.h -= 10;
}
printf("scancode=%d\n", ev.key.keysym.scancode);
break;
case SDL_MOUSEWHEEL:
if (ev.wheel.y > 0)
{
rect.h *= 1.1;
rect.w *= 1.1;
}
if (ev.wheel.y < 0)
{
rect.w /= 1.1;
rect.h /= 1.1;
}
break;
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_RenderPresent(renderer);
SDL_Delay(16);
}
//释放资源
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
大家好,我的第一本书正式出版了,可以在京东各大店铺抢购哦。
出书过程非常艰辛,来回校正了好几遍,后续还有FFmpeg系列的其它图书。
第一本:FFmpeg入门详解--音视频原理及应用--梅会东--清华大学出版社
第二本:FFmpeg入门详解--流媒体直播原理及应用--梅会东--清华大学出版社
第三本:FFmpeg入门详解--命令行及音视频特效原理及应用--梅会东--清华大学出版社
第四本:FFmpeg入门详解--SDK二次开发及直播美颜原理及应用--梅会东--清华大学出版社






浙公网安备 33010602011771号