SDL实现overlay方式双屏显示的应用流程分析(thinkvd开发日志)

由于在参与开发 thinkvd video converter 遇到释放SDL内存的问题,应用中需要在预览、全屏、双屏及CLIP之间来回切换,再次看了SDL相关的源代码,把SDL实现的过程简单说一下。

SDL开发包中自带的样例:testsprite2.c中就是一个实现多屏显示的例子。
简化它来说大概这几步:
1。SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) //初始化
2. windows[i]=SDL_CreateWindow(wm_title, window_x, window_y, width, height, window_flags);
3. SDL_CreateRenderer(windows[i], -1, SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD) < 0)
4. SDL_SelectRenderer(windows[i]); //选择哪个窗口在绑定数据
5. texture[i] = SDL_CreateTexture(desired_format, SDL_TEXTUREACCESS_STREAMING, width, height);
6. COPY(texture[i]) //要显示的数据.
7. while(1){ SDL_DisplayYUVOverlay(overlay, &overlayrect); }
8. SDL_Quit.

      也许有人有疑问,它怎么没有显示要用的SDL_Surface,事实上个人参与thinkvd 视频开发时是这样用的,这些SDL流程代码完全是从SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)中COPY出来的(除了COPY data之后的),也就是说SDL_SetVideoMode把SDL实现应用的环境造就好了只需要COPY数据到texture显示出来即可,而testsprite2实现与它类似。

      在overlay方式下,SDL的simple到window, overlay.也就是用户(开发者)只关心在哪个窗口下显示数据。真正的核心Renderer则交给SDL来处理了。

     由于关注的是视频显示问题,就没有SDL_Surface更多的研究,但从它的结构来看,与SDL_Overlay一样,用来存储数据用的。
typedef struct SDL_Overlay
{
    Uint32 format;              /**< Read-only */
    int w, h;                   /**< Read-only */
    int planes;                 /**< Read-only */
    Uint16 *pitches;            /**< Read-only */
    Uint8 **pixels;             /**< Read-write */

    /**
     *  /name Hardware-specific surface info
     */
    /*@{*/
    struct private_yuvhwfuncs *hwfuncs;
    struct private_yuvhwdata *hwdata;
    /*@}*//*Hardware-specific surface info*/

    /**
     *  /name Special flags
     */
    /*@{*/
    Uint32 hw_overlay:1;        /**< Flag: This overlay hardware accelerated? */
    Uint32 UnusedBits:31;
    /*@}*//*Special flags*/
} SDL_Overlay;


typedef struct SDL_Surface
{
    Uint32 flags;               /**< Read-only */
    SDL_PixelFormat *format;    /**< Read-only */
    int w, h;                   /**< Read-only */
    int pitch;                  /**< Read-only */
    void *pixels;               /**< Read-write */

    /** Application data associated with the surface */
    void *userdata;             /**< Read-write */

    /** information needed for surfaces requiring locks */
    int locked;                 /**< Read-only */
    void *lock_data;            /**< Read-only */

    /** clipping information */
    SDL_Rect clip_rect;         /**< Read-only */

    /** info for fast blit mapping to other surfaces */
    struct SDL_BlitMap *map;    /**< Private */

    /** format version, bumped at every change to invalidate blit maps */
    unsigned int format_version;        /**< Private */

    /** Reference count -- used when freeing surface */
    int refcount;               /**< Read-mostly */
} SDL_Surface;


 开始用SDL时个人由于对SDL认识不够,不太明白SDL_Surface, SDL_Window, SDL_Overlay, SDL_Render之间的关系及SDL实现的程序,由此造成了对SDL调用的误解。
SDL_Window: 实现消息控制
SDL_Overlay:数据存储
SDL_Render:数据显示
它们的关系从CreateTexture中可看出:(用directx来说明:D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture))
  SDL_Window *window = renderer->window;
  D3D_TextureData *data; //数据存储与显示。overlay的lock与unlock实际上指向的内存也是data->texture, 里面有个小技巧,自己看源代码更能体会。
  texture->driverdata = data;
  data->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
  IDirect3DDevice9_CreateTexture(renderdata->device, texture->w,
                                       texture->h, 1, 0,
                                       PixelFormatToD3DFMT(data->format),
                                       D3DPOOL_SDL, &data->texture, NULL);
 
实现不同大小的视频显示时,只需要更改overlay数据存储的大小即可.
在实现多个窗口之间切换时,SDL有不足之处,它没有实现window与render的分离(或者说叫组合).今后再研究看如何实现。

你可能感兴趣的:(C语言,C++)