由于在参与开发 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的分离(或者说叫组合).今后再研究看如何实现。