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