~ubuntu-branches/ubuntu/quantal/linphone/quantal

« back to all changes in this revision

Viewing changes to mediastreamer2/src/sdlout.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Elie Mamane, Kilian Krause, Lionel Elie Mamane
  • Date: 2009-05-27 11:39:51 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090527113951-jd525e5rlwluh617
[ Kilian Krause ]
* Remove -N from wget args in get-orig-source target as -O is already
  used.

[ Lionel Elie Mamane ]
* linphone: Fix file conflict with linphone-common (<= 3.1.2-1)
  (Closes: #528076)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
mediastreamer2 library - modular sound and video processing and streaming
3
 
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
 
 
5
 
This program is free software; you can redistribute it and/or
6
 
modify it under the terms of the GNU General Public License
7
 
as published by the Free Software Foundation; either version 2
8
 
of the License, or (at your option) any later version.
9
 
 
10
 
This program is distributed in the hope that it will be useful,
11
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
GNU General Public License for more details.
14
 
 
15
 
You should have received a copy of the GNU General Public License
16
 
along with this program; if not, write to the Free Software
17
 
Foundation, 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
 
 
27
 
typedef 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
 
 
42
 
static bool_t sdl_initialized=FALSE;
43
 
 
44
 
static 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
 
 
73
 
static 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
 
 
84
 
static 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
 
 
91
 
static 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
 
 
114
 
mblk_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
 
 
163
 
static 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
 
 
204
 
static 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
 
 
220
 
static 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
 
 
321
 
static 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
 
 
327
 
static 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
 
 
334
 
static 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
 
 
342
 
MSFilterDesc ms_sdl_out_desc={
343
 
        MS_SDL_OUT_ID,
344
 
        "MSSdlOut",
345
 
        "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
 
 
360
 
MSFilterDesc ms_sdl_out_desc={
361
 
        .id=MS_SDL_OUT_ID,
362
 
        .name="MSSdlOut",
363
 
        .text="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
 
 
375
 
MS_FILTER_DESC_EXPORT(ms_sdl_out_desc)