source: mediastreamer2/linphone/mediastreamer2/src/videoout.c @ 0:5a6e836a86a3

Last change on this file since 0:5a6e836a86a3 was 0:5a6e836a86a3, checked in by aymeric <aymeric@…>, 5 years ago

Initial import

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@1 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 20.9 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#ifdef HAVE_CONFIG_H
21#include "mediastreamer-config.h"
22#endif
23
24#include "mediastreamer2/msfilter.h"
25#include "mediastreamer2/msvideo.h"
26#include "mediastreamer2/msvideoout.h"
27
28#include "ffmpeg-priv.h"
29
30static int video_out_handle_resize(MSFilter *f, void *arg);
31
32bool_t ms_display_poll_event(MSDisplay *d, MSDisplayEvent *ev){
33        if (d->desc->pollevent)
34                return d->desc->pollevent(d,ev);
35        else return FALSE;
36}
37
38#ifndef WIN32
39
40#include <SDL/SDL.h>
41#include <SDL/SDL_video.h>
42
43static bool_t sdl_initialized=FALSE;
44
45static ms_mutex_t sdl_mutex;
46
47static SDL_Surface *sdl_screen=0;
48
49#ifdef HAVE_X11_XLIB_H
50
51#include <SDL/SDL_syswm.h>
52
53static void sdl_show_window(bool_t show){
54        SDL_SysWMinfo info;
55        SDL_VERSION(&info.version);
56        if ( SDL_GetWMInfo(&info) ) {
57                if ( info.subsystem == SDL_SYSWM_X11 ) {
58                        Display *display;
59                        Window window;
60               
61                        info.info.x11.lock_func();
62                        display = info.info.x11.display;
63                        window = info.info.x11.wmwindow;
64                        if (show)
65                                XMapWindow(display,window);
66                        else
67                                XUnmapWindow(display,window);
68                        info.info.x11.unlock_func();
69                }
70        }
71}
72
73#else
74
75static void sdl_show_window(bool_t show){
76        ms_warning("SDL window show/hide not implemented");
77}
78
79#endif
80
81static SDL_Overlay * sdl_create_window(int w, int h){
82        SDL_Overlay *lay;
83        sdl_screen = SDL_SetVideoMode(w,h, 0,SDL_SWSURFACE|SDL_RESIZABLE);
84        if (sdl_screen == NULL ) {
85                ms_warning("Couldn't set video mode: %s\n",
86                                                SDL_GetError());
87                return NULL;
88        }
89        if (sdl_screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware");
90        SDL_WM_SetCaption("Linphone Video", NULL);
91        ms_message("Using yuv overlay.");
92        lay=SDL_CreateYUVOverlay(w,h,SDL_YV12_OVERLAY,sdl_screen);
93        if (lay==NULL){
94                ms_warning("Couldn't create yuv overlay: %s\n",
95                                                SDL_GetError());
96                return NULL;
97        }else{
98                if (lay->hw_overlay) ms_message("YUV overlay using hardware acceleration.");
99        }
100        return lay;
101}
102
103static bool_t sdl_display_init(MSDisplay *obj, MSPicture *fbuf){
104        SDL_Overlay *lay;
105        if (!sdl_initialized){
106                /* Initialize the SDL library */
107                if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
108                        ms_error("Couldn't initialize SDL: %s", SDL_GetError());
109                        return FALSE;
110                }
111                /* Clean up on exit */
112                atexit(SDL_Quit);
113                sdl_initialized=TRUE;
114                ms_mutex_init(&sdl_mutex,NULL);
115        }
116        if (obj->data!=NULL)
117                SDL_FreeYUVOverlay((SDL_Overlay*)obj->data);
118       
119        lay=sdl_create_window(fbuf->w, fbuf->h);
120        if (lay){
121                fbuf->planes[0]=lay->pixels[0];
122                fbuf->planes[1]=lay->pixels[2];
123                fbuf->planes[2]=lay->pixels[1];
124                fbuf->strides[0]=lay->pitches[0];
125                fbuf->strides[1]=lay->pitches[2];
126                fbuf->strides[2]=lay->pitches[1];
127                obj->data=lay;
128                sdl_show_window(TRUE);
129                return TRUE;
130        }
131        return FALSE;
132}
133
134static void sdl_display_lock(MSDisplay *obj){
135        ms_mutex_lock(&sdl_mutex);
136        SDL_LockYUVOverlay((SDL_Overlay*)obj->data);
137        ms_mutex_unlock(&sdl_mutex);
138}
139
140static void sdl_display_unlock(MSDisplay *obj){
141        SDL_Overlay *lay=(SDL_Overlay*)obj->data;
142        ms_mutex_lock(&sdl_mutex);
143        SDL_UnlockYUVOverlay(lay);
144        ms_mutex_unlock(&sdl_mutex);
145}
146
147static void sdl_display_update(MSDisplay *obj){
148        SDL_Rect rect;
149        SDL_Overlay *lay=(SDL_Overlay*)obj->data;
150        rect.x=0;
151        rect.y=0;
152        rect.w=lay->w;
153        rect.h=lay->h;
154        ms_mutex_lock(&sdl_mutex);
155        SDL_DisplayYUVOverlay(lay,&rect);
156        ms_mutex_unlock(&sdl_mutex);
157}
158
159static bool_t sdl_poll_event(MSDisplay *obj, MSDisplayEvent *ev){
160        SDL_Event event;
161        static MSDisplayEvent last_ev;
162        static struct timeval tv;
163        static bool_t got_rs_ev=FALSE;
164        struct timeval cur;
165        int elapsed;
166        bool_t ret=FALSE;
167        ms_mutex_lock(&sdl_mutex);
168        if (SDL_PollEvent(&event)){
169                ms_mutex_unlock(&sdl_mutex);
170                switch(event.type){
171                        case SDL_VIDEORESIZE:
172                                last_ev.evtype=MS_DISPLAY_RESIZE_EVENT;
173                                last_ev.w=event.resize.w;
174                                last_ev.h=event.resize.h;
175                                got_rs_ev=TRUE;
176                                gettimeofday(&tv,NULL);
177                        break;
178                        default:
179                        break;
180                }
181        }else ms_mutex_unlock(&sdl_mutex);
182        if (got_rs_ev){
183                gettimeofday(&cur,NULL);
184                elapsed=((cur.tv_sec-tv.tv_sec)*1000) + ((cur.tv_usec-tv.tv_usec)/1000);
185                if (elapsed>1000){
186                        got_rs_ev=FALSE;
187                        *ev=last_ev;
188                        ret=TRUE;
189                }
190        }
191        return ret;
192}
193
194static void sdl_display_uninit(MSDisplay *obj){
195        SDL_Overlay *lay=(SDL_Overlay*)obj->data;
196        if (lay==NULL)
197                return;
198        if (lay!=NULL)
199                SDL_FreeYUVOverlay(lay);
200        if (sdl_screen!=NULL){
201                SDL_FreeSurface(sdl_screen);
202                sdl_screen=NULL;
203        }
204        sdl_show_window(FALSE);
205}
206
207MSDisplayDesc ms_sdl_display_desc={
208        .init=sdl_display_init,
209        .lock=sdl_display_lock,
210        .unlock=sdl_display_unlock,
211        .update=sdl_display_update,
212        .uninit=sdl_display_uninit,
213        .pollevent=sdl_poll_event
214};
215
216#else
217
218#include <Vfw.h>
219
220
221typedef struct _WinDisplay{
222        HWND window;
223        HDRAWDIB ddh;
224        MSPicture fb;
225        MSDisplayEvent last_rsz;
226        uint8_t *rgb;
227        int rgb_len;
228        bool_t new_ev;
229}WinDisplay;
230
231static LRESULT CALLBACK window_proc(
232    HWND hwnd,        // handle to window
233    UINT uMsg,        // message identifier
234    WPARAM wParam,    // first message parameter
235    LPARAM lParam)    // second message parameter
236{
237        switch(uMsg){
238                case WM_DESTROY:
239                break;
240                case WM_SIZE:
241                        if (wParam==SIZE_RESTORED){
242                                int h=(lParam>>16) & 0xffff;
243                                int w=lParam & 0xffff;
244                                MSDisplay *obj;
245                                WinDisplay *wd;
246                                ms_message("Resized to %i,%i",w,h);
247                                obj=(MSDisplay*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
248                                if (obj!=NULL){
249                                        wd=(WinDisplay*)obj->data;
250                                        wd->last_rsz.evtype=MS_DISPLAY_RESIZE_EVENT;
251                                        wd->last_rsz.w=w;
252                                        wd->last_rsz.h=h;
253                                        wd->new_ev=TRUE;
254                                }else{
255                                        ms_error("Could not retrieve MSDisplay from window !");
256                                }
257                        }
258                break;
259                default:
260                        return DefWindowProc(hwnd, uMsg, wParam, lParam);
261        }
262        return 0;
263}
264
265static HWND create_window(int w, int h)
266{
267        WNDCLASS wc;
268        HINSTANCE hInstance = GetModuleHandle(NULL);
269        HWND hwnd;
270        RECT rect;
271        wc.style = 0 ;
272        wc.lpfnWndProc = window_proc;
273        wc.cbClsExtra = 0;
274        wc.cbWndExtra = 0;
275        wc.hInstance = NULL;
276        wc.hIcon = NULL;
277        wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
278        wc.hbrBackground = NULL;
279        wc.lpszMenuName =  NULL;
280        wc.lpszClassName = "Video Window";
281       
282        if(!RegisterClass(&wc))
283        {
284                /* already registred! */
285        }
286        rect.left=100;
287        rect.top=100;
288        rect.right=rect.left+w;
289        rect.bottom=rect.top+h;
290        if (!AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW|WS_VISIBLE /*WS_CAPTION WS_TILED|WS_BORDER*/,FALSE)){
291                ms_error("AdjustWindowRect failed.");
292        }
293        ms_message("AdjustWindowRect: %li,%li %li,%li",rect.left,rect.top,rect.right,rect.bottom);
294        hwnd=CreateWindow("Video Window", "Video window", WS_OVERLAPPEDWINDOW|WS_VISIBLE ,
295                                                CW_USEDEFAULT, CW_USEDEFAULT, rect.right-rect.left,rect.bottom-rect.top,
296                                                                                                        NULL, NULL, hInstance, NULL);
297        if (hwnd==NULL){
298                ms_error("Fail to create video window");
299        }
300        return hwnd;
301}
302
303static bool_t win_display_init(MSDisplay *obj, MSPicture *fbuf){
304        WinDisplay *wd=(WinDisplay*)obj->data;
305        int ysize,usize;
306
307        if (wd!=NULL)
308        {
309                if (wd->ddh) DrawDibClose(wd->ddh);
310                wd->ddh=NULL;
311                if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
312                wd->fb.planes[0]=NULL;
313                wd->fb.planes[1]=NULL;
314                wd->fb.planes[2]=NULL;
315                if (wd->rgb) ms_free(wd->rgb);
316                wd->rgb=NULL;
317                wd->rgb_len=0;
318        }
319        else
320                wd=(WinDisplay*)ms_new0(WinDisplay,1);
321       
322        obj->data=wd;
323       
324        wd->fb.w=fbuf->w;
325        wd->fb.h=fbuf->h;
326       
327        if (wd->window==NULL){
328                if (obj->window_id!=0){
329                        void *p;
330                        wd->window=(HWND)obj->window_id;
331                        p=(void*)GetWindowLongPtr(wd->window,GWLP_USERDATA);
332                        if (p!=NULL){
333                                ms_error("Gulp: this externally supplied windows seems to "
334                                        "already have a userdata ! resizing will crash !");
335                        }else SetWindowLongPtr(wd->window,GWLP_USERDATA,(LONG_PTR)obj);
336                }else{
337                        wd->window=create_window(wd->fb.w,wd->fb.h);
338                        if (wd->window!=NULL) SetWindowLongPtr(wd->window,GWLP_USERDATA,(LONG_PTR)obj);
339                        else return FALSE;
340                }
341        }
342       
343        if (wd->ddh==NULL) wd->ddh=DrawDibOpen();
344        if (wd->ddh==NULL){
345                ms_error("DrawDibOpen() failed.");
346                return FALSE;
347        }
348        /*allocate yuv and rgb buffers*/
349        if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
350        if (wd->rgb) ms_free(wd->rgb);
351        ysize=wd->fb.w*wd->fb.h;
352        usize=ysize/4;
353        fbuf->planes[0]=wd->fb.planes[0]=(uint8_t*)ms_malloc0(ysize+2*usize);
354        fbuf->planes[1]=wd->fb.planes[1]=wd->fb.planes[0]+ysize;
355        fbuf->planes[2]=wd->fb.planes[2]=wd->fb.planes[1]+usize;
356        fbuf->strides[0]=wd->fb.strides[0]=wd->fb.w;
357        fbuf->strides[1]=wd->fb.strides[1]=wd->fb.w/2;
358        fbuf->strides[2]=wd->fb.strides[2]=wd->fb.w/2;
359
360        wd->rgb_len=ysize*3;
361        wd->rgb=(uint8_t*)ms_malloc0(wd->rgb_len);
362        return TRUE;
363}
364
365typedef struct rgb{
366        uint8_t r,g,b;
367} rgb_t;
368
369typedef struct yuv{
370        uint8_t y,u,v;
371} yuv_t;
372
373
374
375static void yuv420p_to_rgb(MSPicture *src, uint8_t *rgb){
376        struct SwsContext *sws;
377        int rgb_stride=-src->w*3;
378        uint8_t *p;
379
380        p=rgb+(src->w*3*(src->h-1));
381        sws=sws_getContext(src->w,src->h,PIX_FMT_YUV420P,
382                        src->w,src->h,PIX_FMT_RGB24,
383                        0, NULL, NULL, NULL);
384        if (sws_scale(sws,src->planes,src->strides, 0,
385                                0, &p, &rgb_stride)<0){
386                        ms_error("Error in 420->rgb sws_scale().");
387        }
388        sws_freeContext(sws);
389
390        /*revert colors*/       
391        {
392                int i,j,stride;
393                rgb_t pix;
394                stride=src->w*3;
395                p=rgb;
396                for(i=0;i<src->h;++i){
397                        for(j=0;j<stride;j+=3){
398                                pix.r=p[j];
399                                pix.g=p[j+1];
400                                pix.b=p[j+2];
401                                p[j]=pix.b;
402                                p[j+2]=pix.r;
403                        }
404                        p+=stride;
405                }
406        }
407
408}
409
410static void win_display_update(MSDisplay *obj){
411        WinDisplay *wd=(WinDisplay*)obj->data;
412        HDC hdc;
413        BITMAPINFOHEADER bi;
414        RECT rect;
415        bool_t ret;
416        if (wd->window==NULL) return;
417        hdc=GetDC(wd->window);
418        if (hdc==NULL) {
419                ms_error("Could not get window dc");
420                return;
421        }
422        yuv420p_to_rgb(&wd->fb, wd->rgb);
423        memset(&bi,0,sizeof(bi));
424        bi.biSize=sizeof(bi);
425        GetClientRect(wd->window,&rect);
426        /*
427        bi.biWidth=wd->fb.w;
428        bi.biHeight=wd->fb.h;
429        bi.biPlanes=3;
430        bi.biBitCount=12;
431        bi.biCompression=MAKEFOURCC('I','4','2','0');
432        bi.biSizeImage=(wd->fb.w*wd->fb.h*3)/2;
433        */
434        bi.biWidth=wd->fb.w;
435        bi.biHeight=wd->fb.h;
436        bi.biPlanes=1;
437        bi.biBitCount=24;
438        bi.biCompression=BI_RGB;
439        bi.biSizeImage=wd->rgb_len;
440
441        //if (bi.biHeight>rect.bottom)
442        //      bi.biHeight=rect.bottom;
443        //bi.biSizeImage=(bi.biWidth*bi.biHeight)*3;
444
445        ret=DrawDibDraw(wd->ddh,hdc,0,0,
446                //bi.biWidth,bi.biHeight,
447                rect.right,rect.bottom,
448                &bi,wd->rgb,
449                //0,0,rect.right,rect.bottom,0);
450                0,0,bi.biWidth,bi.biHeight,0);
451       
452        if (!ret) ms_error("DrawDibDraw failed.");
453        ReleaseDC(NULL,hdc);
454}
455
456static void win_display_uninit(MSDisplay *obj){
457        WinDisplay *wd=(WinDisplay*)obj->data;
458        if (wd==NULL)
459                return;
460        if (wd->window && !obj->window_id) DestroyWindow(wd->window);
461        if (wd->ddh) DrawDibClose(wd->ddh);
462        if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
463        if (wd->rgb) ms_free(wd->rgb);
464        ms_free(wd);
465}
466
467bool_t win_display_pollevent(MSDisplay *d, MSDisplayEvent *ev){
468        WinDisplay *wd=(WinDisplay*)d->data;
469        if (wd->new_ev){
470                wd->new_ev=FALSE;
471                *ev=wd->last_rsz;
472                return TRUE;
473        }
474        return FALSE;
475}
476
477#ifdef _MSC_VER
478
479extern MSDisplayDesc ms_win_display_desc={
480        win_display_init,
481        NULL,
482        NULL,
483        win_display_update,
484        win_display_uninit,
485        win_display_pollevent
486};
487
488#else
489
490MSDisplayDesc ms_win_display_desc={
491        .init=win_display_init,
492        .update=win_display_update,
493        .uninit=win_display_uninit,
494        .pollevent=win_display_pollevent
495};
496
497#endif
498
499#endif
500
501MSDisplay *ms_display_new(MSDisplayDesc *desc){
502        MSDisplay *obj=(MSDisplay *)ms_new0(MSDisplay,1);
503        obj->desc=desc;
504        obj->data=NULL;
505        return obj;
506}
507
508void ms_display_set_window_id(MSDisplay *d, long id){
509        d->window_id=id;
510}
511
512void ms_display_destroy(MSDisplay *obj){
513        obj->desc->uninit(obj);
514        ms_free(obj);
515}
516
517typedef struct VideoOut
518{
519        AVRational ratio;
520        MSPicture fbuf;
521        MSPicture local_pic;
522        MSRect local_rect;
523        mblk_t *local_msg;
524  MSPicture tmp_local_pic;
525  mblk_t *tmp_local_msg;
526        int corner;
527        struct SwsContext *sws1;
528        struct SwsContext *sws2;
529        MSDisplay *display;
530        bool_t own_display;
531        bool_t ready;
532} VideoOut;
533
534
535#define SCALE_FACTOR 6
536
537static void set_corner(VideoOut *s, int corner)
538{
539  s->corner=corner;
540  s->local_pic.w=s->fbuf.w/SCALE_FACTOR;
541  s->local_pic.h=s->fbuf.h/SCALE_FACTOR;
542  s->tmp_local_pic.h = s->local_pic.h;
543  s->tmp_local_pic.w = s->local_pic.w;
544  if (corner==1)
545    {
546      /* top left corner */
547        s->local_rect.x=0;
548        s->local_rect.y=0;
549        s->local_rect.w=s->local_pic.w;
550        s->local_rect.h=s->local_pic.h;
551    }
552  else if (corner==2)
553    {
554      /* top right corner */
555        s->local_rect.x=s->fbuf.w-s->local_pic.w;
556        s->local_rect.y=0;
557        s->local_rect.w=s->local_pic.w;
558        s->local_rect.h=s->local_pic.h;
559    }
560  else if (corner==3)
561    {
562      /* bottom left corner */
563        s->local_rect.x=0;
564        s->local_rect.y=s->fbuf.h-s->local_pic.h;
565        s->local_rect.w=s->local_pic.w;
566        s->local_rect.h=s->local_pic.h;
567    }
568  else
569    {
570      /* default: bottom right corner */
571      /* corner can be set to -1: to disable the self view... */
572        s->local_rect.x=s->fbuf.w-s->local_pic.w;
573        s->local_rect.y=s->fbuf.h-s->local_pic.h;
574        s->local_rect.w=s->local_pic.w;
575        s->local_rect.h=s->local_pic.h;
576    }
577}
578
579static void set_vsize(VideoOut *s, MSVideoSize *sz){
580        if (s->ratio.num!=0){
581                sz->width=sz->width & (~0x1);
582                sz->height=sz->width*s->ratio.den/s->ratio.num;
583        }
584        s->fbuf.w=sz->width;
585        s->fbuf.h=sz->height;
586        set_corner(s, s->corner);
587}
588
589static void video_out_init(MSFilter  *f){
590        VideoOut *obj=(VideoOut*)ms_new(VideoOut,1);
591        MSVideoSize def_size;
592        obj->ratio.num=11;
593        obj->ratio.den=9;
594        def_size.width=MS_VIDEO_SIZE_CIF_W;
595        def_size.height=MS_VIDEO_SIZE_CIF_H;
596        obj->local_msg=NULL;
597  obj->tmp_local_msg=NULL;
598        obj->corner=0;
599        obj->sws1=NULL;
600        obj->sws2=NULL;
601        obj->display=NULL;
602        obj->own_display=FALSE;
603        obj->ready=FALSE;
604        set_vsize(obj,&def_size);
605        f->data=obj;
606}
607
608
609static void video_out_uninit(MSFilter *f){
610        VideoOut *obj=(VideoOut*)f->data;
611        if (obj->display!=NULL && obj->own_display)
612                ms_display_destroy(obj->display);
613        if (obj->sws1!=NULL){
614                sws_freeContext(obj->sws1);
615                obj->sws1=NULL;
616        }
617        if (obj->sws2!=NULL){
618                sws_freeContext(obj->sws2);
619                obj->sws2=NULL;
620        }
621        ms_free(obj);
622}
623
624
625static void video_out_preprocess(MSFilter *f){
626        VideoOut *obj=(VideoOut*)f->data;
627        if (obj->display==NULL){
628#ifndef WIN32
629                obj->display=ms_display_new(&ms_sdl_display_desc);
630#else
631                obj->display=ms_display_new(&ms_win_display_desc);
632#endif
633                obj->own_display=TRUE;
634        }
635        if (!ms_display_init(obj->display,&obj->fbuf)){
636                if (obj->own_display) ms_display_destroy(obj->display);
637                obj->display=NULL;
638        }
639        if (obj->sws1!=NULL){
640                sws_freeContext(obj->sws1);
641                obj->sws1=NULL;
642        }
643        if (obj->sws2!=NULL){
644                sws_freeContext(obj->sws2);
645                obj->sws2=NULL;
646        }
647        if (obj->local_msg!=NULL) {
648                freemsg(obj->local_msg);
649                obj->local_msg=NULL;
650        }
651        if (obj->tmp_local_msg!=NULL) {
652                freemsg(obj->tmp_local_msg);
653                obj->tmp_local_msg=NULL;
654        }
655        obj->ready=TRUE;
656}
657
658static void video_out_postprocess(MSFilter *f){
659}
660
661static void mirror(unsigned char* dst,unsigned char* src,int dststride,int srcstride,int w,int h){
662    int y;
663    for(y=0;y<h;y++){
664      int x;
665      for(x=0;x<w;x++)
666        dst[x]=src[w-x-1];
667      src+=srcstride;
668      dst+=dststride;
669    }
670}
671
672
673static void video_out_process(MSFilter *f){
674        VideoOut *obj=(VideoOut*)f->data;
675        mblk_t *inm;
676
677#ifdef WIN32
678        video_out_handle_resize(f, NULL);
679#endif
680
681        ms_filter_lock(f);
682        if (obj->display==NULL){
683                ms_filter_unlock(f);
684                if (f->inputs[0]!=NULL)
685                  ms_queue_flush(f->inputs[0]);
686                if (f->inputs[1]!=NULL)
687                  ms_queue_flush(f->inputs[1]);
688                return;
689        }
690        /*get most recent message and draw it*/
691        if (f->inputs[1]!=NULL && (inm=ms_queue_peek_last(f->inputs[1]))!=0) {
692
693          if (obj->corner==-1)
694            {
695        if (obj->tmp_local_msg!=NULL) {
696          freemsg(obj->tmp_local_msg);
697          obj->tmp_local_msg=NULL;
698        }
699              if (obj->local_msg!=NULL) {
700                      freemsg(obj->local_msg);
701                      obj->local_msg=NULL;
702              }
703            }
704          else
705            {
706              MSPicture src;
707              if (yuv_buf_init_from_mblk(&src,inm)==0){
708
709                      if (obj->sws2==NULL){
710                        obj->sws2=sws_getContext(src.w,src.h,PIX_FMT_YUV420P,
711                                                 obj->local_pic.w,obj->local_pic.h,PIX_FMT_YUV420P,
712                                                 SWS_FAST_BILINEAR, NULL, NULL, NULL);
713                      }
714          obj->tmp_local_pic.h = obj->local_pic.h;
715          obj->tmp_local_pic.w = obj->local_pic.w;
716                if (obj->tmp_local_msg==NULL){
717                  obj->tmp_local_msg=yuv_buf_alloc(&obj->tmp_local_pic,
718                                               obj->tmp_local_pic.w,obj->tmp_local_pic.h);
719          }
720                if (obj->local_msg==NULL){
721                  obj->local_msg=yuv_buf_alloc(&obj->local_pic,
722                                               obj->local_pic.w,obj->local_pic.h);
723                }
724          if (sws_scale(obj->sws2,src.planes,src.strides, 0,
725                              src.h, obj->tmp_local_pic.planes, obj->tmp_local_pic.strides)<0){
726                  ms_error("Error in sws_scale().");
727                }
728
729          mirror(obj->local_pic.planes[0],obj->tmp_local_pic.planes[0],
730             obj->local_pic.strides[0],obj->tmp_local_pic.strides[0],
731             obj->local_pic.w,obj->local_pic.h);
732          mirror(obj->local_pic.planes[1],obj->tmp_local_pic.planes[1],
733             obj->local_pic.strides[1],obj->tmp_local_pic.strides[1],
734             obj->local_pic.w>>1,obj->local_pic.h>>1);
735          mirror(obj->local_pic.planes[2],obj->tmp_local_pic.planes[2],
736             obj->local_pic.strides[2],obj->tmp_local_pic.strides[2],
737             obj->local_pic.w>>1,obj->local_pic.h>>1);
738            }
739          }
740          ms_queue_flush(f->inputs[1]);
741        }
742       
743        if (f->inputs[0]!=NULL && (inm=ms_queue_peek_last(f->inputs[0]))!=0) {
744                MSPicture src;
745                if (yuv_buf_init_from_mblk(&src,inm)==0){
746                        if (obj->sws1==NULL){
747                                obj->sws1=sws_getContext(src.w,src.h,PIX_FMT_YUV420P,
748                                obj->fbuf.w,obj->fbuf.h,PIX_FMT_YUV420P,
749                                SWS_FAST_BILINEAR, NULL, NULL, NULL);
750                        }
751                        ms_display_lock(obj->display);
752                        if (sws_scale(obj->sws1,src.planes,src.strides, 0,
753                                src.h, obj->fbuf.planes, obj->fbuf.strides)<0){
754                                ms_error("Error in sws_scale().");
755                        }
756                        ms_display_unlock(obj->display);
757                }
758                ms_queue_flush(f->inputs[0]);
759        }
760        /*copy resized local view into main buffer, at bottom left corner:*/
761        if (obj->local_msg!=NULL){
762                MSPicture corner=obj->fbuf;
763                MSVideoSize roi;
764                roi.width=obj->local_pic.w;
765                roi.height=obj->local_pic.h;
766                corner.w=obj->local_pic.w;
767                corner.h=obj->local_pic.h;
768                corner.planes[0]+=obj->local_rect.x+(obj->local_rect.y*corner.strides[0]);
769                corner.planes[1]+=(obj->local_rect.x/2)+((obj->local_rect.y/2)*corner.strides[1]);
770                corner.planes[2]+=(obj->local_rect.x/2)+((obj->local_rect.y/2)*corner.strides[2]);
771                ms_display_lock(obj->display);
772                yuv_buf_copy(obj->local_pic.planes,obj->local_pic.strides,
773                                corner.planes,corner.strides,roi);
774                ms_display_unlock(obj->display);
775        }
776       
777        ms_display_update(obj->display);
778        ms_filter_unlock(f);
779}
780
781static int video_out_set_vsize(MSFilter *f,void *arg){
782        VideoOut *s=(VideoOut*)f->data;
783        bool_t reconfigure;
784        ms_filter_lock(f);
785        reconfigure=s->ready;
786        set_vsize(s,(MSVideoSize*)arg);
787        if (reconfigure) video_out_preprocess(f);
788        ms_filter_unlock(f);
789        return 0;
790}
791
792static int video_out_set_display(MSFilter *f,void *arg){
793        VideoOut *s=(VideoOut*)f->data;
794        s->display=(MSDisplay*)arg;
795        return 0;
796}
797
798static int video_out_handle_resize(MSFilter *f, void *arg){
799        VideoOut *s=(VideoOut*)f->data;
800        MSDisplay *disp=s->display;
801        if (disp!=NULL){
802                MSDisplayEvent ev;
803                if (ms_display_poll_event(disp,&ev)){
804                        if (ev.evtype==MS_DISPLAY_RESIZE_EVENT){
805                                MSVideoSize sz;
806                                sz.width=ev.w;
807                                sz.height=ev.h;
808#ifndef WIN32
809                                video_out_set_vsize(f,&sz);
810#endif
811                        }
812                }
813        }
814        return 0;
815}
816
817static int video_out_set_corner(MSFilter *f,void *arg){
818        VideoOut *s=(VideoOut*)f->data;
819        set_corner(s, *(int*)arg);
820#if 1
821        ms_filter_lock(f);
822        ms_display_lock(s->display);
823        {
824          int w=s->fbuf.w;
825          int h=s->fbuf.h;
826          int ysize=w*h;
827          int usize=ysize/4;
828         
829          memset(s->fbuf.planes[0], 0, ysize);
830          memset(s->fbuf.planes[1], 0, usize);
831          memset(s->fbuf.planes[2], 0, usize);
832        }
833        ms_display_unlock(s->display);
834        ms_filter_unlock(f);
835#endif
836        return 0;
837}
838
839static MSFilterMethod methods[]={
840        {       MS_FILTER_SET_VIDEO_SIZE        ,       video_out_set_vsize },
841        {       MS_VIDEO_OUT_SET_DISPLAY        ,       video_out_set_display},
842        {       MS_VIDEO_OUT_HANDLE_RESIZING    ,       video_out_handle_resize},
843        {       MS_VIDEO_OUT_SET_CORNER         ,       video_out_set_corner},
844        {       0       ,NULL}
845};
846
847#ifdef _MSC_VER
848
849MSFilterDesc ms_video_out_desc={
850        MS_VIDEO_OUT_ID,
851        "MSVideoOut",
852        "A generic video display",
853        MS_FILTER_OTHER,
854        NULL,
855        2,
856        0,
857        video_out_init,
858        video_out_preprocess,
859        video_out_process,
860        video_out_postprocess,
861        video_out_uninit,
862        methods
863};
864
865#else
866
867MSFilterDesc ms_video_out_desc={
868        .id=MS_VIDEO_OUT_ID,
869        .name="MSVideoOut",
870        .text="A generic video display",
871        .category=MS_FILTER_OTHER,
872        .ninputs=2,
873        .noutputs=0,
874        .init=video_out_init,
875        .preprocess=video_out_preprocess,
876        .process=video_out_process,
877        .postprocess=video_out_postprocess,
878        .uninit=video_out_uninit,
879        .methods=methods
880};
881
882#endif
883
884MS_FILTER_DESC_EXPORT(ms_video_out_desc)
Note: See TracBrowser for help on using the repository browser.