2
mediastreamer2 library - modular sound and video processing and streaming
3
Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
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.
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.
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.
21
#include "mediastreamer2/msfilter.h"
22
#include "mediastreamer2/msvideo.h"
25
#include <SDL/SDL_video.h>
30
MSVideoSize local_size; /*size of local preview */
40
#define SCALE_FACTOR 6
42
static bool_t sdl_initialized=FALSE;
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;
57
#if !defined(WIN32) && !defined(__APPLE__)
58
if (!sdl_initialized){
60
/* Initialize the SDL library */
61
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
62
ms_error("Couldn't initialize SDL: %s", SDL_GetError());
65
/* Clean up on exit */
73
static void sdl_destroy_window(SdlOut *obj){
74
if (obj->overlay!=NULL){
75
SDL_FreeYUVOverlay(obj->overlay);
78
if (obj->screen!=NULL){
79
SDL_FreeSurface(obj->screen);
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);
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",
98
if (obj->screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware");
99
SDL_WM_SetCaption("Linphone Video", NULL);
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",
109
if (obj->overlay->hw_overlay) ms_message("YUV overlay using hardware acceleration.");
114
mblk_t * resize_yuv_small(unsigned char *pict, int w, int h, int scale){
117
unsigned char *smallpict;
118
int ysize,usize,ydsize,udsize;
120
unsigned char *dptr,*sptr;
128
smallpict_sz=(ydsize*3)/2;
129
smallb=allocb(smallpict_sz,0);
130
smallpict=smallb->b_wptr;
131
smallb->b_wptr+=smallpict_sz;
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];
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];
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];
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;
170
ilim=MIN(x+w,lay->w);
171
jlim=MIN(y+h,lay->h);
172
SDL_LockYUVOverlay(lay);
175
for (j=y;j<jlim;j++){
177
for (i=x;i<ilim;i++){
186
for (j=y/2;j<jlim;j++){
188
for (i=x/2;i<ilim;i++){
194
for (j=y/2;j<jlim;j++){
196
for (i=x/2;i<ilim;i++){
201
SDL_UnlockYUVOverlay(lay);
204
static void fill_overlay(SDL_Overlay *lay,mblk_t *m){
207
char *data=(char*)m->b_rptr;
208
int ysize=lay->pitches[0]*lay->h;
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);
220
static void sdl_out_process(MSFilter *f){
221
SdlOut *obj=(SdlOut*)f->data;
227
bool_t got_preview=FALSE;
229
#if defined(WIN32) || defined(__APPLE__)
230
if (!sdl_initialized){
232
/* Initialize the SDL library */
233
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
234
ms_error("Couldn't initialize SDL: %s", SDL_GetError());
237
/* Clean up on exit */
239
sdl_initialized=TRUE;
243
if (obj->screen==NULL){
244
sdl_create_window(obj);
247
rect.w=obj->size.width;
248
rect.h=obj->size.height;
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;
257
while (f->inputs[0]!=NULL && (inm0=ms_queue_get(f->inputs[0]))!=NULL){
259
if (obj->format==MS_YUV420P){
260
fill_overlay(obj->overlay,inm0);
262
surf=SDL_CreateRGBSurfaceFrom(inm0->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);
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);
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 */
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)){
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;
284
obj->lsize_init=TRUE;
286
if (obj->format==MS_YUV420P){
287
if (obj->smallb!=NULL) {
288
freemsg(obj->smallb);
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);
294
surf=SDL_CreateRGBSurfaceFrom(inm1->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0);
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);
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);
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);
313
#if defined(WIN32) || defined(__APPLE__)
316
SDL_PollEvent(&event);
321
static int sdl_out_set_pix_fmt(MSFilter *f,void *arg){
322
SdlOut *s=(SdlOut*)f->data;
323
s->format=*(MSPixFmt*)arg;
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;
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 },
342
MSFilterDesc ms_sdl_out_desc={
345
"A video display window using SDL",
360
MSFilterDesc ms_sdl_out_desc={
363
.text="A video display window using SDL",
364
.category=MS_FILTER_OTHER,
368
.process=sdl_out_process,
369
.uninit=sdl_out_uninit,
375
MS_FILTER_DESC_EXPORT(ms_sdl_out_desc)