📄 sdlout.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "mediastreamer2/msfilter.h"#include "mediastreamer2/msvideo.h"#include <SDL/SDL.h>#include <SDL/SDL_video.h>typedef struct SdlOut{ MSVideoSize size; MSVideoSize local_size; /*size of local preview */ MSPixFmt format; SDL_Surface *screen; SDL_Overlay *overlay; mblk_t *smallb; int scale_factor; bool_t lsize_init;} SdlOut;#define SCALE_FACTOR 6static bool_t sdl_initialized=FALSE;static void sdl_out_init(MSFilter *f){ SdlOut *obj=ms_new(SdlOut,1); obj->size.width = MS_VIDEO_SIZE_CIF_W; obj->size.height = MS_VIDEO_SIZE_CIF_H; obj->local_size.width = MS_VIDEO_SIZE_CIF_W; obj->local_size.height = MS_VIDEO_SIZE_CIF_H; obj->lsize_init=FALSE; obj->scale_factor=SCALE_FACTOR; obj->format=MS_RGB24; obj->screen=NULL; obj->overlay=NULL; obj->smallb=NULL;#if !defined(WIN32) && !defined(__APPLE__) if (!sdl_initialized){ /* Initialize the SDL library */ if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { ms_error("Couldn't initialize SDL: %s", SDL_GetError()); return; } /* Clean up on exit */ atexit(SDL_Quit); sdl_initialized=TRUE; }#endif f->data=obj;}static void sdl_destroy_window(SdlOut *obj){ if (obj->overlay!=NULL){ SDL_FreeYUVOverlay(obj->overlay); obj->overlay=NULL; } if (obj->screen!=NULL){ SDL_FreeSurface(obj->screen); obj->screen=NULL; }}static void sdl_out_uninit(MSFilter *f){ SdlOut *s=(SdlOut*)f->data; sdl_destroy_window(s); if (s->smallb!=NULL) freemsg(s->smallb); ms_free(s);}static void sdl_create_window(SdlOut *obj){ obj->screen = SDL_SetVideoMode(obj->size.width, obj->size.height, 0,SDL_SWSURFACE); if ( obj->screen == NULL ) { ms_warning("Couldn't set video mode: %s\n", SDL_GetError()); return ; } if (obj->screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware"); SDL_WM_SetCaption("Linphone Video", NULL); if (obj->format==MS_YUV420P){ ms_message("Using yuv overlay."); obj->overlay=SDL_CreateYUVOverlay(obj->size.width,obj->size.height,SDL_YV12_OVERLAY,obj->screen); if (obj->overlay==NULL){ ms_warning("Couldn't create yuv overlay: %s\n", SDL_GetError()); return; }else{ if (obj->overlay->hw_overlay) ms_message("YUV overlay using hardware acceleration."); } }}mblk_t * resize_yuv_small(unsigned char *pict, int w, int h, int scale){ int i,j,id,jd; int nh,nw; unsigned char *smallpict; int ysize,usize,ydsize,udsize; int smallpict_sz; unsigned char *dptr,*sptr; mblk_t *smallb; nw=w/scale; nh=h/scale; ysize=w*h; usize=ysize/4; ydsize=nw*nh; udsize=ydsize/4; smallpict_sz=(ydsize*3)/2; smallb=allocb(smallpict_sz,0); smallpict=smallb->b_wptr; smallb->b_wptr+=smallpict_sz; dptr=smallpict; sptr=pict; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } nh=nh/2; nw=nw/2; w=w/2; h=h/2; dptr+=ydsize; sptr+=ysize; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } dptr+=udsize; sptr+=usize; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } return smallb;}static void fill_overlay_at_pos(SDL_Overlay *lay, mblk_t *m, int x, int y, int w, int h){ unsigned char *data=m->b_rptr; int i,j; int jlim,ilim; int off; unsigned char *dptr; ilim=MIN(x+w,lay->w); jlim=MIN(y+h,lay->h); SDL_LockYUVOverlay(lay); /* set Y */ dptr=lay->pixels[0]; for (j=y;j<jlim;j++){ off=j*lay->w; for (i=x;i<ilim;i++){ dptr[off + i]=*data; data++; } } /*set U and V*/ ilim=ilim/2; jlim=jlim/2; dptr=lay->pixels[2]; for (j=y/2;j<jlim;j++){ off=j*(lay->w/2); for (i=x/2;i<ilim;i++){ dptr[off + i]=*data; data++; } } dptr=lay->pixels[1]; for (j=y/2;j<jlim;j++){ off=j*(lay->w/2); for (i=x/2;i<ilim;i++){ dptr[off + i]=*data; data++; } } SDL_UnlockYUVOverlay(lay);}static void fill_overlay(SDL_Overlay *lay,mblk_t *m){ int w2,h2; char *data=(char*)m->b_rptr; int ysize=lay->pitches[0]*lay->h; int usize; w2=lay->w/2; h2=lay->h/2; usize=w2*h2; SDL_LockYUVOverlay(lay); memcpy(lay->pixels[0],data,ysize); memcpy(lay->pixels[2],data+ysize,usize); memcpy(lay->pixels[1],data+ysize+usize,usize); SDL_UnlockYUVOverlay(lay);}static void sdl_out_process(MSFilter *f){ SdlOut *obj=(SdlOut*)f->data; mblk_t *inm0=NULL; mblk_t *inm1=NULL; int err; SDL_Rect smallrect; SDL_Rect rect; bool_t got_preview=FALSE; #if defined(WIN32) || defined(__APPLE__) if (!sdl_initialized){ /* Initialize the SDL library */ if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { ms_error("Couldn't initialize SDL: %s", SDL_GetError()); return; } /* Clean up on exit */ atexit(SDL_Quit); sdl_initialized=TRUE; }#endif if (obj->screen==NULL){ sdl_create_window(obj); } rect.w=obj->size.width; rect.h=obj->size.height; rect.x=0; rect.y=0; smallrect.w=obj->size.width/SCALE_FACTOR; smallrect.h=obj->size.height/SCALE_FACTOR; smallrect.x=obj->size.width - smallrect.w ; smallrect.y=obj->size.height -smallrect.h; while (f->inputs[0]!=NULL && (inm0=ms_queue_get(f->inputs[0]))!=NULL){ SDL_Surface *surf; if (obj->format==MS_YUV420P){ fill_overlay(obj->overlay,inm0); }else { surf=SDL_CreateRGBSurfaceFrom(inm0->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0); err=SDL_BlitSurface(surf,NULL,obj->screen,NULL); if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError()); SDL_FreeSurface(surf); } freemsg(inm0); } while (f->inputs[1]!=NULL && (inm1=ms_queue_get(f->inputs[1]))!=NULL){ /* this message is blitted on the right,bottom corner of the screen */ SDL_Surface *surf; got_preview=TRUE; if (!obj->lsize_init){ /*attempt to guess the video size of the local preview buffer*/ int bsize=msgdsize(inm1); if (bsize<(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3/2)){ /*surely qcif ?*/ obj->local_size.width=MS_VIDEO_SIZE_QCIF_W; obj->local_size.height=MS_VIDEO_SIZE_QCIF_H; ms_message("preview is in QCIF."); obj->scale_factor=SCALE_FACTOR/2; } obj->lsize_init=TRUE; } if (obj->format==MS_YUV420P){ if (obj->smallb!=NULL) { freemsg(obj->smallb); } obj->smallb=resize_yuv_small(inm1->b_rptr,obj->local_size.width,obj->local_size.height,obj->scale_factor); fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h); freemsg(inm1); }else { surf=SDL_CreateRGBSurfaceFrom(inm1->b_rptr,obj->size.width,obj->size.height,24,obj->size.width*3,0,0,0,0); err=SDL_BlitSurface(surf,NULL,obj->screen,&smallrect); if (err<0) ms_warning("Fail to blit surface: %s",SDL_GetError()); SDL_FreeSurface(surf); } } if (!got_preview){ /* this is the case were we have only inm0, we have to redisplay inm1 */ if (obj->format==MS_YUV420P){ if (obj->smallb!=NULL){ fill_overlay_at_pos(obj->overlay,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h); } } } if (obj->format==MS_YUV420P) SDL_DisplayYUVOverlay(obj->overlay,&rect); else SDL_UpdateRect(obj->screen,0,0,obj->size.width,obj->size.height); #if defined(WIN32) || defined(__APPLE__) { SDL_Event event; SDL_PollEvent(&event); }#endif}static int sdl_out_set_pix_fmt(MSFilter *f,void *arg){ SdlOut *s=(SdlOut*)f->data; s->format=*(MSPixFmt*)arg; return 0;}static int sdl_out_set_vsize(MSFilter *f,void *arg){ SdlOut *s=(SdlOut*)f->data; s->size=*(MSVideoSize*)arg; s->local_size=*(MSVideoSize*)arg; return 0;}static MSFilterMethod methods[]={ { MS_FILTER_SET_PIX_FMT , sdl_out_set_pix_fmt}, { MS_FILTER_SET_VIDEO_SIZE , sdl_out_set_vsize }, { 0 ,NULL}};#ifdef _MSC_VERMSFilterDesc ms_sdl_out_desc={ MS_SDL_OUT_ID, "MSSdlOut", "A video display window using SDL", MS_FILTER_OTHER, NULL, 2, 0, sdl_out_init, NULL, sdl_out_process, NULL, sdl_out_uninit, methods};#elseMSFilterDesc ms_sdl_out_desc={ .id=MS_SDL_OUT_ID, .name="MSSdlOut", .text="A video display window using SDL", .category=MS_FILTER_OTHER, .ninputs=2, .noutputs=0, .init=sdl_out_init, .process=sdl_out_process, .uninit=sdl_out_uninit, .methods=methods};#endifMS_FILTER_DESC_EXPORT(ms_sdl_out_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -