SDL2学习:一、视频播放流程及相关api

SDL简单介绍

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。用下面这张图可以很明确地说明SDL的位置。SDL实际上封装了Direct3D,DirectSound这类的底层API。

SDL实际上并不限于视音频的播放,它将功能分成下列数个子系统(subsystem):

  • Video(图像):图像控制以及线程(thread)和事件管理(event)。
  • Audio(声音):声音控制
  • Joystick(摇杆):游戏摇杆控制
  • CD-ROM(光盘驱动器):光盘媒体控制
  • Window Management(视窗管理):与视窗程序设计集成
  • Event(事件驱动):处理事件驱动

在Windows下,SDL与DirectX的对应关系如下。

SDL DirectX
SDL_Video、SDL_Image DirectDraw、Direct3D
SDL_Audio、SDL_Mixer DirectSound
SDL_Joystick、SDL_Base DirectInput
SDL_Net DirectPlay

SDL播放视频的流程

1、初始化
  1.     初始化SDL
    
  2.     创建窗口(Window)
    
  3.     基于窗口创建渲染器(Render)
    
  4.     创建纹理(Texture)
    
2、循环显示画面
  1.     设置纹理的数据
    
  2.     纹理复制给渲染目标
    
  3.     显示
    
3、api调用流程图如下

image

从图中可以看出,整体的流程可以概括为如下步骤:

  1. 初始化:SDL_Init()
  2. 创建SDL_Window:SDL_CreateWindow()
  3. 创建SDL_Render:SDL_CreateRenderer()
  4. 创建SDL_Texture:SDL_CreateTexture()
  5. 更新SDL_Texture:SDL_UpdateTexture()
  6. 渲染SDL_Texture:SDL_RenderCopy()
  7. 显示:SDL_RenderPresent()
  8. 返回步骤4继续执行
    上图中显示了SDL播放视频的时候API的调用流程。

SDL2播放视频涉及的结构体

SDL显示视频涉及到下列结构体:

  • SDL_Window:代表了窗口
  • SDL_Renderer:代表了渲染器
  • SDL_Texture:代表了纹理
  • SDL_Rect:一个矩形框,用于确定纹理显示的位置。

上述几个结构体之间的关系如下图所示:
image
由图可见,YUV/RGB像素数据首先加载至SDL_Texture,然后通过SDL_Render渲染至SDL_Window。其中SDL_Rect可以指定显示的位置。

相关api和结构体详细介绍

【一、初始化】SDL_Init()

【函数介绍】
该函数可以确定希望激活的子系统。SDL_Init()函数原型如下:

int SDLCALL SDL_Init(Uint32 flags)

其中,flags可以取下列值:

  • SDL_INIT_TIMER:定时器
  • SDL_INIT_AUDIO:音频
  • SDL_INIT_VIDEO:视频
  • SDL_INIT_JOYSTICK:摇杆
  • SDL_INIT_HAPTIC:触摸屏
  • SDL_INIT_GAMECONTROLLER:游戏控制器
  • SDL_INIT_EVENTS:事件
  • SDL_INIT_NOPARACHUTE:不捕获关键信号(这个不理解)
  • SDL_INIT_EVERYTHING:包含上述所有选项
【二、窗口】SDL_Window

SDL_Window结构体定义了一个SDL2中的窗口,定义如下:

点击查看代码
/* Define the SDL window structure, corresponding to toplevel windows */
struct SDL_Window
{
    const void *magic;
    Uint32 id;
    char *title;
    SDL_Surface *icon;
    int x, y;
    int w, h;
    int min_w, min_h;
    int max_w, max_h;
    Uint32 flags;
    Uint32 last_fullscreen_flags;
 
 
    /* Stored position and size for windowed mode */
    SDL_Rect windowed;
 
 
    SDL_DisplayMode fullscreen_mode;
 
 
    float brightness;
    Uint16 *gamma;
    Uint16 *saved_gamma;        /* (just offset into gamma) */
 
 
    SDL_Surface *surface;
    SDL_bool surface_valid;
 
 
    SDL_bool is_destroying;
 
 
    SDL_WindowShaper *shaper;
 
 
    SDL_WindowUserData *data;
 
 
    void *driverdata;
 
 
    SDL_Window *prev;
    SDL_Window *next;
};
可以看出其中包含了一个“窗口”应该包含的各种属性。这个结构体中的各个变量还没有深入研究,暂不详细分析。下面来看看如何创建这个SDL_Window。
【创建窗口】SDL_CreateWindow()

【函数简介】
SDL_CreateWindow()用于创建一个视频播放的窗口。SDL_CreateWindow()的原型如下:

SDL_Window * SDLCALL SDL_CreateWindow(const char *title,
                                                      int x, int y, int w,
                                                      int h, Uint32 flags);

【参数分析】

  • title:窗口标题
  • x:窗口位置x坐标。也可以设置为 SDL_WINDOWPOS_CENTERED 或 SDL_WINDOWPOS_UNDEFINED
  • y:窗口位置 y 坐标,同上
  • w:窗口的宽
  • h:窗口的高
  • flags:支持下列标识。包括了窗口的是否最大化、最小化,能否调整边界等等属性
    • SDL_WINDOW_FULLSCREEN:全屏
    • SDL_WINDOW_OPENGL:opengl
    • SDL_WINDOW_HIDDEN:最小化
    • SDL_WINDOW_BORDERLESS:无边界
    • SDL_WINDOW_RESIZABLE:可调整大小
    • SDL_WINDOW_MAXIMIZED:最大化
    • SDL_WINDOW_MINIMIZED:最小化
    • SDL_WINDOW_INPUT_GRABBED:可拖拽?
    • SDL_WINDOW_ALLOW_HIGHDPI:高DPI

【返回值】
返回创建完成的窗口的ID。如果创建失败则返回0。

【三、渲染器】SDL_Renderer

【定义】
SDL_Renderer结构体定义了一个SDL2中的渲染器。定义如下:

点击查看代码
/* Define the SDL renderer structure */
struct SDL_Renderer
{
    const void *magic;
 
 
    void (*WindowEvent) (SDL_Renderer * renderer, const SDL_WindowEvent *event);
    int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
    int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
    int (*SetTextureColorMod) (SDL_Renderer * renderer,
                               SDL_Texture * texture);
    int (*SetTextureAlphaMod) (SDL_Renderer * renderer,
                               SDL_Texture * texture);
    int (*SetTextureBlendMode) (SDL_Renderer * renderer,
                                SDL_Texture * texture);
    int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
                          const SDL_Rect * rect, const void *pixels,
                          int pitch);
    int (*UpdateTextureYUV) (SDL_Renderer * renderer, SDL_Texture * texture,
                            const SDL_Rect * rect,
                            const Uint8 *Yplane, int Ypitch,
                            const Uint8 *Uplane, int Upitch,
                            const Uint8 *Vplane, int Vpitch);
    int (*LockTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
                        const SDL_Rect * rect, void **pixels, int *pitch);
    void (*UnlockTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
    int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture);
    int (*UpdateViewport) (SDL_Renderer * renderer);
    int (*UpdateClipRect) (SDL_Renderer * renderer);
    int (*RenderClear) (SDL_Renderer * renderer);
    int (*RenderDrawPoints) (SDL_Renderer * renderer, const SDL_FPoint * points,
                             int count);
    int (*RenderDrawLines) (SDL_Renderer * renderer, const SDL_FPoint * points,
                            int count);
    int (*RenderFillRects) (SDL_Renderer * renderer, const SDL_FRect * rects,
                            int count);
    int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
                       const SDL_Rect * srcrect, const SDL_FRect * dstrect);
    int (*RenderCopyEx) (SDL_Renderer * renderer, SDL_Texture * texture,
                       const SDL_Rect * srcquad, const SDL_FRect * dstrect,
                       const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
    int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
                             Uint32 format, void * pixels, int pitch);
    void (*RenderPresent) (SDL_Renderer * renderer);
    void (*DestroyTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
 
 
    void (*DestroyRenderer) (SDL_Renderer * renderer);
 
 
    int (*GL_BindTexture) (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
    int (*GL_UnbindTexture) (SDL_Renderer * renderer, SDL_Texture *texture);
 
 
    /* The current renderer info */
    SDL_RendererInfo info;
 
 
    /* The window associated with the renderer */
    SDL_Window *window;
    SDL_bool hidden;
 
 
    /* The logical resolution for rendering */
    int logical_w;
    int logical_h;
    int logical_w_backup;
    int logical_h_backup;
 
 
    /* The drawable area within the window */
    SDL_Rect viewport;
    SDL_Rect viewport_backup;
 
 
    /* The clip rectangle within the window */
    SDL_Rect clip_rect;
    SDL_Rect clip_rect_backup;
 
 
    /* The render output coordinate scale */
    SDL_FPoint scale;
    SDL_FPoint scale_backup;
 
 
    /* The list of textures */
    SDL_Texture *textures;
    SDL_Texture *target;
 
 
    Uint8 r, g, b, a;                   /**< Color for drawing operations values */
    SDL_BlendMode blendMode;            /**< The drawing blend mode */
 
 
    void *driverdata;
};

通过代码可以看出其中包含了一个“渲染器”应该包含的各种属性。这个结构体中的各个变量还没有深入研究,暂不详细分析。下面来看看如何创建这个SDL_Renderer

【创建渲染器】SDL_CreateRenderer()

【函数介绍】
SDL中使用 SDL_CreateRenderer()基于窗口创建渲染器。原型如下

SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,
                                               int index, Uint32 flags);

【参数分析】

  • window : 渲染的目标窗口。
  • index :打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。
  • flags :支持以下值(位于SDL_RendererFlags定义中)
    • SDL_RENDERER_SOFTWARE :使用软件渲染
    • SDL_RENDERER_ACCELERATED :使用硬件加速
    • SDL_RENDERER_PRESENTVSYNC:和显示器的刷新率同步
    • SDL_RENDERER_TARGETTEXTURE :渲染器支持渲染到纹理

【返回值】

  • SDL_Renderer*:返回创建完成的渲染器的ID。如果创建失败则返回NULL。
【四、纹理】SDL_Texture

【结构体定义】
SDL_Texture结构定义了一个SDL中的纹理。定义如下:

点击查看代码
/* Define the SDL texture structure */
struct SDL_Texture
{
    const void *magic;
    Uint32 format;              /**< The pixel format of the texture */
    int access;                 /**< SDL_TextureAccess */
    int w;                      /**< The width of the texture */
    int h;                      /**< The height of the texture */
    int modMode;                /**< The texture modulation mode */
    SDL_BlendMode blendMode;    /**< The texture blend mode */
    Uint8 r, g, b, a;           /**< Texture modulation values */
 
 
    SDL_Renderer *renderer;
 
 
    /* Support for formats not supported directly by the renderer */
    SDL_Texture *native;
    SDL_SW_YUVTexture *yuv;
    void *pixels;
    int pitch;
    SDL_Rect locked_rect;
 
 
    void *driverdata;           /**< Driver specific texture representation */
 
 
    SDL_Texture *prev;
    SDL_Texture *next;
};
其中包含了一个“纹理”所具备的各种属性。下面来看看如何创建这个SDL_Texture
【创建纹理】SDL_CreateTexture()

【函数声明】
使用SDL_CreateTexture()基于渲染器创建一个纹理。SDL_CreateTexture()的原型如下:

SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
                                                        Uint32 format,
                                                        int access, int w,
                                                        int h);

【参数分析】

  • renderer:目标渲染器
  • format:纹理的格式
  • access:可以取以下值(一般都会使用第三个)
    • SDL_TEXTUREACCESS_STATIC :很少改变的texture
    • SDL_TEXTUREACCESS_STREAMING :变化频繁
    • SDL_TEXTUREACCESS_TARGET :可以被设置为render的目标的
  • w:纹理的宽
  • h:纹理的高
    【返回值】
    创建成功则返回纹理的ID,失败返回0。
【五、更新纹理】SDL_UpdateTexture()

【函数介绍】
SDL使用SDL_UpdateTexture()设置纹理的像素数据。SDL_UpdateTexture()的原型如下。

int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,
                                          const SDL_Rect * rect,
                                              const void *pixels, int pitch);

【参数分析】

  • texture:目标纹理
  • rect:更新像素的矩形区域。设置为NULL时将更新整个区域
  • pixels:像素数据
  • pitch:一行像素数据的字节数

【返回值】
成功的话返回0,失败的话返回-1

【六、复制到渲染器】SDL_RenderCopy()

【函数简介】
SDL使用SDL_RenderCopy()将纹理数据复制给渲染目标。SDL_RenderCopy()的原型如下:

int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
                                           SDL_Texture * texture,
                                           const SDL_Rect * srcrect,
                                           const SDL_Rect * dstrect);

【参数分析】

  • renderer:渲染目标
  • texture:输入纹理
  • srcreat:选择输入纹理的一块矩形区域作为输入,设置为NULL时将整个纹理作为输入
  • dstrect:选择渲染目标的一块举行区域作为输出。设置为NULL时将整个渲染目标作为输出。

【返回值】
成功返回0,失败返回-1.

【七、显示】SDL_RenderPresent()

【函数简介】
SDL使用SDL_RenderPresent()显示画面。SDL_RenderPresent()的原型如下

void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);

【参数分析】

  • renderer:用于指定渲染器

参考

SDL2初始化函数
二、窗口
三、渲染器
四、纹理
五、更新纹理
六、复制到渲染器
七、显示
视频显示总结

posted @ 2022-08-01 15:29  小超不挑食  阅读(1105)  评论(0编辑  收藏  举报