source: mediastreamer2/src/sdlout.c @ 856:3d8054c9c0b4

Last change on this file since 856:3d8054c9c0b4 was 856:3d8054c9c0b4, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

expurge everything but mediastreamer2

File size: 8.8 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20
21#include "mediastreamer2/msfilter.h"
22#include "mediastreamer2/msvideo.h"
23
24#include <SDL/SDL.h>
25#include <SDL/SDL_video.h>
26
27typedef struct SdlOut
28{
29        MSVideoSize size;
30        MSVideoSize local_size; /*size of local preview */
31        MSPixFmt format;
32        SDL_Surface *screen;
33        SDL_Overlay *overlay;
34        mblk_t *smallb;
35        int scale_factor;
36        bool_t lsize_init;
37} SdlOut;
38
39
40#define SCALE_FACTOR 6
41
42static bool_t sdl_initialized=FALSE;
43
44static void sdl_out_init(MSFilter  *f){
45        SdlOut *obj=ms_new(SdlOut,1);
46        obj->size.width = MS_VIDEO_SIZE_CIF_W;
47        obj->size.height = MS_VIDEO_SIZE_CIF_H;
48        obj->local_size.width = MS_VIDEO_SIZE_CIF_W;
49        obj->local_size.height = MS_VIDEO_SIZE_CIF_H;
50        obj->lsize_init=FALSE;
51        obj->scale_factor=SCALE_FACTOR;
52        obj->format=MS_RGB24;
53        obj->screen=NULL;
54        obj->overlay=NULL;
55        obj->smallb=NULL;
56
57#if !defined(WIN32) && !defined(__APPLE__)
58        if (!sdl_initialized){
59
60                /* Initialize the SDL library */
61                if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
62                        ms_error("Couldn't initialize SDL: %s", SDL_GetError());
63                        return;
64                }
65                /* Clean up on exit */
66                atexit(SDL_Quit);
67                sdl_initialized=TRUE;
68        }
69#endif
70        f->data=obj;
71}
72
73static void sdl_destroy_window(SdlOut *obj){
74        if (obj->overlay!=NULL){
75                SDL_FreeYUVOverlay(obj->overlay);
76                obj->overlay=NULL;
77        }
78        if (obj->screen!=NULL){
79                SDL_FreeSurface(obj->screen);
80                obj->screen=NULL;
81        }
82}
83
84static void sdl_out_uninit(MSFilter *f){
85        SdlOut *s=(SdlOut*)f->data;
86        sdl_destroy_window(s);
87        if (s->smallb!=NULL) freemsg(s->smallb);
88        ms_free(s);
89}
90
91static void sdl_create_window(SdlOut *obj){
92        obj->screen = SDL_SetVideoMode(obj->size.width, obj->size.height, 0,SDL_SWSURFACE);
93        if ( obj->screen == NULL ) {
94                ms_warning("Couldn't set video mode: %s\n",
95                                                SDL_GetError());
96                return ;
97        }
98        if (obj->screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware");
99        SDL_WM_SetCaption("Linphone Video", NULL);
100       
101        if (obj->format==MS_YUV420P){
102                ms_message("Using yuv overlay.");
103                obj->overlay=SDL_CreateYUVOverlay(obj->size.width,obj->size.height,SDL_YV12_OVERLAY,obj->screen);
104                if (obj->overlay==NULL){
105                        ms_warning("Couldn't create yuv overlay: %s\n",
106                                                        SDL_GetError());
107                        return;
108                }else{
109                        if (obj->overlay->hw_overlay) ms_message("YUV overlay using hardware acceleration.");
110                }
111        }
112}
113
114mblk_t * resize_yuv_small(unsigned char *pict, int w, int h, int scale){
115        int i,j,id,jd;
116        int nh,nw;
117        unsigned char *smallpict;
118        int ysize,usize,ydsize,udsize;
119        int smallpict_sz;
120        unsigned char *dptr,*sptr;
121        mblk_t *smallb;
122        nw=w/scale;
123        nh=h/scale;
124        ysize=w*h;
125        usize=ysize/4;
126        ydsize=nw*nh;
127        udsize=ydsize/4;
128        smallpict_sz=(ydsize*3)/2;
129        smallb=allocb(smallpict_sz,0);
130        smallpict=smallb->b_wptr;
131        smallb->b_wptr+=smallpict_sz;
132       
133        dptr=smallpict;
134        sptr=pict;
135        for (j=0,jd=0;j<nh;j++,jd+=scale){
136                for (i=0,id=0;i<nw;i++,id+=scale){
137                        dptr[(j*nw) + i]=sptr[(jd*w)+id];
138                }
139        }
140       
141        nh=nh/2;
142        nw=nw/2;
143        w=w/2;
144        h=h/2;
145        dptr+=ydsize;
146        sptr+=ysize;
147        for (j=0,jd=0;j<nh;j++,jd+=scale){
148                for (i=0,id=0;i<nw;i++,id+=scale){
149                        dptr[(j*nw) + i]=sptr[(jd*w)+id];
150                }
151        }
152        dptr+=udsize;
153        sptr+=usize;
154        for (j=0,jd=0;j<nh;j++,jd+=scale){
155                for (i=0,id=0;i<nw;i++,id+=scale){
156                        dptr[(j*nw) + i]=sptr[(jd*w)+id];
157                }
158        }
159       
160        return smallb;
161}
162
163static void fill_overlay_at_pos(SDL_Overlay *lay, mblk_t *m, int x, int y, int w, int h){
164        unsigned char *data=m->b_rptr;
165        int i,j;
166        int jlim,ilim;
167        int off;
168        unsigned char *dptr;
169       
170        ilim=MIN(x+w,lay->w);
171        jlim=MIN(y+h,lay->h);
172        SDL_LockYUVOverlay(lay);
173        /* set Y */
174        dptr=lay->pixels[0];
175        for (j=y;j<jlim;j++){
176                off=j*lay->w;
177                for (i=x;i<ilim;i++){
178                        dptr[off + i]=*data;
179                        data++;
180                }
181        }
182        /*set U and V*/
183        ilim=ilim/2;
184        jlim=jlim/2;
185        dptr=lay->pixels[2];
186        for (j=y/2;j<jlim;j++){
187                off=j*(lay->w/2);
188                for (i=x/2;i<ilim;i++){
189                        dptr[off + i]=*data;
190                        data++;
191                }
192        }
193        dptr=lay->pixels[1];
194        for (j=y/2;j<jlim;j++){
195                off=j*(lay->w/2);
196                for (i=x/2;i<ilim;i++){
197                        dptr[off + i]=*data;
198                        data++;
199                }
200        }
201        SDL_UnlockYUVOverlay(lay);
202}
203
204static void fill_overlay(SDL_Overlay *lay,mblk_t *m){
205       
206        int w2,h2;
207        char *data=(char*)m->b_rptr;
208        int ysize=lay->pitches[0]*lay->h;
209        int usize;
210        w2=lay->w/2;
211        h2=lay->h/2;
212        usize=w2*h2;
213        SDL_LockYUVOverlay(lay);
214        memcpy(lay->pixels[0],data,ysize);
215        memcpy(lay->pixels[2],data+ysize,usize);
216        memcpy(lay->pixels[1],data+ysize+usize,usize);
217        SDL_UnlockYUVOverlay(lay);
218}
219
220static void sdl_out_process(MSFilter *f){
221        SdlOut *obj=(SdlOut*)f->data;
222        mblk_t *inm0=NULL;
223        mblk_t *inm1=NULL;
224        int err;
225        SDL_Rect smallrect;
226        SDL_Rect rect;
227        bool_t got_preview=FALSE;
228       
229#if defined(WIN32) || defined(__APPLE__)
230        if (!sdl_initialized){
231
232                /* Initialize the SDL library */
233                if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
234                        ms_error("Couldn't initialize SDL: %s", SDL_GetError());
235                        return;
236                }
237                /* Clean up on exit */
238                atexit(SDL_Quit);
239                sdl_initialized=TRUE;
240        }
241#endif
242
243        if (obj->screen==NULL){
244                sdl_create_window(obj);
245        }
246
247        rect.w=obj->size.width;
248        rect.h=obj->size.height;
249        rect.x=0;
250        rect.y=0;
251        smallrect.w=obj->size.width/SCALE_FACTOR;
252        smallrect.h=obj->size.height/SCALE_FACTOR;
253        smallrect.x=obj->size.width - smallrect.w ;
254        smallrect.y=obj->size.height -smallrect.h;
255       
256       
257        while (f->inputs[0]!=NULL && (inm0=ms_queue_get(f->inputs[0]))!=NULL){
258                SDL_Surface *surf;
259                if  (obj->format==MS_YUV420P){
260                        fill_overlay(obj->overlay,inm0);
261                }else {
262                        surf=SDL_CreateRGBSurfaceFrom(inm0->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);
263
264                        err=SDL_BlitSurface(surf,NULL,obj->screen,NULL);
265                        if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError());
266                        SDL_FreeSurface(surf);
267                }
268                freemsg(inm0);
269        }
270        while (f->inputs[1]!=NULL && (inm1=ms_queue_get(f->inputs[1]))!=NULL){
271                /* this message is blitted on the right,bottom corner of the screen */
272                SDL_Surface *surf;
273                got_preview=TRUE;
274                if (!obj->lsize_init){
275                        /*attempt to guess the video size of the local preview buffer*/
276                        int bsize=msgdsize(inm1);
277                        if (bsize<(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3/2)){
278                                /*surely qcif ?*/
279                                obj->local_size.width=MS_VIDEO_SIZE_QCIF_W;
280                                obj->local_size.height=MS_VIDEO_SIZE_QCIF_H;
281                                ms_message("preview is in QCIF.");
282                                obj->scale_factor=SCALE_FACTOR/2;
283                        }
284                        obj->lsize_init=TRUE;
285                }
286                if  (obj->format==MS_YUV420P){
287                        if (obj->smallb!=NULL) {
288                                freemsg(obj->smallb);
289                        }
290                        obj->smallb=resize_yuv_small(inm1->b_rptr,obj->local_size.width,obj->local_size.height,obj->scale_factor);
291                        fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h);
292                        freemsg(inm1);
293                }else {
294                        surf=SDL_CreateRGBSurfaceFrom(inm1->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);
295
296                        err=SDL_BlitSurface(surf,NULL,obj->screen,&smallrect);
297                        if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError());
298                        SDL_FreeSurface(surf);
299                }
300        }
301        if (!got_preview){
302                /* this is the case were we have only inm0, we have to redisplay inm1 */
303                if  (obj->format==MS_YUV420P){
304                        if (obj->smallb!=NULL){
305                                fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h);
306                        }
307                }
308        }
309       
310        if (obj->format==MS_YUV420P) SDL_DisplayYUVOverlay(obj->overlay,&rect);
311        else SDL_UpdateRect(obj->screen,0,0,obj->size.width,obj->size.height);
312       
313#if defined(WIN32) || defined(__APPLE__)
314        {
315                SDL_Event event;
316                SDL_PollEvent(&event);
317        }
318#endif
319}
320
321static int sdl_out_set_pix_fmt(MSFilter *f,void *arg){
322        SdlOut *s=(SdlOut*)f->data;
323        s->format=*(MSPixFmt*)arg;
324        return 0;
325}
326
327static int sdl_out_set_vsize(MSFilter *f,void *arg){
328        SdlOut *s=(SdlOut*)f->data;
329        s->size=*(MSVideoSize*)arg;
330        s->local_size=*(MSVideoSize*)arg;
331        return 0;
332}
333
334static MSFilterMethod methods[]={
335        {       MS_FILTER_SET_PIX_FMT   ,       sdl_out_set_pix_fmt},
336        {       MS_FILTER_SET_VIDEO_SIZE        ,       sdl_out_set_vsize },
337        {       0       ,NULL}
338};
339
340#ifdef _MSC_VER
341
342MSFilterDesc ms_sdl_out_desc={
343        MS_SDL_OUT_ID,
344        "MSSdlOut",
345        N_("A video display window using SDL"),
346        MS_FILTER_OTHER,
347        NULL,
348        2,
349        0,
350        sdl_out_init,
351        NULL,
352        sdl_out_process,
353        NULL,
354        sdl_out_uninit,
355        methods
356};
357
358#else
359
360MSFilterDesc ms_sdl_out_desc={
361        .id=MS_SDL_OUT_ID,
362        .name="MSSdlOut",
363        .text=N_("A video display window using SDL"),
364        .category=MS_FILTER_OTHER,
365        .ninputs=2,
366        .noutputs=0,
367        .init=sdl_out_init,
368        .process=sdl_out_process,
369        .uninit=sdl_out_uninit,
370        .methods=methods
371};
372
373#endif
374
375MS_FILTER_DESC_EXPORT(ms_sdl_out_desc)
Note: See TracBrowser for help on using the repository browser.