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的分離(或者說叫組合).今後再研究看如何實現。

發佈了8 篇原創文章 · 獲贊 11 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章