source: mediastreamer2/src/videoout.c @ 885:ddc2bd21c6c8

Last change on this file since 885:ddc2bd21c6c8 was 885:ddc2bd21c6c8, checked in by Aymeric Moizard <jack@…>, 3 years ago

Merge branch 'master' of git.linphone.org:mediastreamer2

File size: 33.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
27/*required for dllexport of win_display_desc */
28#define INVIDEOUT_C 1
29#include "mediastreamer2/msvideoout.h"
30
31#include "ffmpeg-priv.h"
32
33#define SCALE_FACTOR 4.0f
34#define SELVIEW_POS_INACTIVE -100.0
35
36static int video_out_set_vsize(MSFilter *f,void *arg);
37
38bool_t ms_display_poll_event(MSDisplay *d, MSDisplayEvent *ev){
39        if (d->desc->pollevent)
40                return d->desc->pollevent(d,ev);
41        else return FALSE;
42}
43
44#ifdef HAVE_SDL
45
46#include <SDL/SDL.h>
47#include <SDL/SDL_video.h>
48
49typedef struct _SdlDisplay{
50        MSFilter *filter;
51        bool_t sdl_initialized;
52        ms_mutex_t sdl_mutex;
53        SDL_Surface *sdl_screen;
54        SDL_Overlay *lay;
55
56        float sv_scalefactor;
57} SdlDisplay;
58
59#ifdef HAVE_X11_XLIB_H
60
61#include <SDL/SDL_syswm.h>
62
63static long sdl_get_native_window_id(){
64        SDL_SysWMinfo info;
65        SDL_VERSION(&info.version);
66        if ( SDL_GetWMInfo(&info) ) {
67                if ( info.subsystem == SDL_SYSWM_X11 ) {
68                        return (long) info.info.x11.wmwindow;
69                }
70        }
71        return 0;
72}
73
74static void sdl_show_window(bool_t show){
75        SDL_SysWMinfo info;
76        SDL_VERSION(&info.version);
77        if ( SDL_GetWMInfo(&info) ) {
78                if ( info.subsystem == SDL_SYSWM_X11 ) {
79                        Display *display;
80                        Window window;
81               
82                        info.info.x11.lock_func();
83                        display = info.info.x11.display;
84                        window = info.info.x11.wmwindow;
85                        if (show)
86                                XMapWindow(display,window);
87                        else
88                                XUnmapWindow(display,window);
89                        info.info.x11.unlock_func();
90                }
91        }
92}
93
94#else
95
96static void sdl_show_window(bool_t show){
97        ms_warning("SDL window show/hide not implemented");
98}
99
100static long sdl_get_native_window_id(){
101        ms_warning("sdl_get_native_window_id not implemented");
102        return 0;
103}
104
105#endif
106
107static void sdl_display_uninit(MSDisplay *obj);
108
109static int sdl_create_window(SdlDisplay *wd, int w, int h){
110        static bool_t once=TRUE;
111       
112        wd->sdl_screen = SDL_SetVideoMode(w,h, 0,SDL_HWSURFACE|SDL_RESIZABLE);
113        if (wd->sdl_screen == NULL ) {
114                ms_warning("no hardware for video mode: %s\n",
115                                                SDL_GetError());
116        }
117        if (wd->sdl_screen == NULL )
118                wd->sdl_screen = SDL_SetVideoMode(w,h, 0,SDL_SWSURFACE|SDL_RESIZABLE);
119        if (wd->sdl_screen == NULL ) {
120                ms_warning("Couldn't set video mode: %s\n",
121                                                SDL_GetError());
122                return -1;
123        }
124        if (wd->sdl_screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware");
125        if (once) {
126                SDL_WM_SetCaption("Video window", NULL);
127                once=FALSE;
128        }
129        ms_message("Using yuv overlay.");
130        wd->lay=SDL_CreateYUVOverlay(w , h ,SDL_YV12_OVERLAY,wd->sdl_screen);
131        if (wd->lay==NULL){
132                ms_warning("Couldn't create yuv overlay: %s\n",
133                                                SDL_GetError());
134                return -1;
135        }else{
136                ms_message("%i x %i YUV overlay created: hw_accel=%i, pitches=%i,%i,%i",wd->lay->w,wd->lay->h,wd->lay->hw_overlay,
137                        wd->lay->pitches[0],wd->lay->pitches[1],wd->lay->pitches[2]);
138                ms_message("planes= %p %p %p  %i %i",wd->lay->pixels[0],wd->lay->pixels[1],wd->lay->pixels[2],
139                        wd->lay->pixels[1]-wd->lay->pixels[0],wd->lay->pixels[2]-wd->lay->pixels[1]);
140        }
141        SDL_ShowCursor(0);//Hide the mouse cursor if was displayed
142        return 0;
143}
144
145static bool_t sdl_display_init(MSDisplay *obj, MSFilter *f, MSPicture *fbuf, MSPicture *fbuf_selfview){
146        SdlDisplay *wd = (SdlDisplay*)obj->data;
147        int i;
148        if (wd==NULL){
149                /* Initialize the SDL library */
150                wd=(SdlDisplay*)ms_new0(SdlDisplay,1);
151                wd->filter = f;
152                obj->data=wd;
153               
154                if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
155                        ms_error("Couldn't initialize SDL: %s", SDL_GetError());
156                        return FALSE;
157                }
158                wd->sdl_initialized=TRUE;
159                ms_mutex_init(&wd->sdl_mutex,NULL);
160                ms_mutex_lock(&wd->sdl_mutex);
161        }else {
162                ms_mutex_lock(&wd->sdl_mutex);
163
164                if (wd->lay!=NULL)
165                        SDL_FreeYUVOverlay(wd->lay);
166                if (wd->sdl_screen!=NULL)
167                        SDL_FreeSurface(wd->sdl_screen);
168                wd->lay=NULL;
169                wd->sdl_screen=NULL;
170        }
171        wd->filter = f;
172       
173        i=sdl_create_window(wd, fbuf->w, fbuf->h);
174        if (i==0){
175                fbuf->planes[0]=wd->lay->pixels[0];
176                fbuf->planes[1]=wd->lay->pixels[2];
177                fbuf->planes[2]=wd->lay->pixels[1];
178                fbuf->planes[3]=NULL;
179                fbuf->strides[0]=wd->lay->pitches[0];
180                fbuf->strides[1]=wd->lay->pitches[2];
181                fbuf->strides[2]=wd->lay->pitches[1];
182                fbuf->strides[3]=0;
183                fbuf->w=wd->lay->w;
184                fbuf->h=wd->lay->h;
185                sdl_show_window(TRUE);
186                obj->window_id=sdl_get_native_window_id();
187                ms_mutex_unlock(&wd->sdl_mutex);
188                return TRUE;
189        }
190        ms_mutex_unlock(&wd->sdl_mutex);
191        return FALSE;
192}
193
194static void sdl_display_lock(MSDisplay *obj){
195        SdlDisplay *wd = (SdlDisplay*)obj->data;
196        ms_mutex_lock(&wd->sdl_mutex);
197        SDL_LockYUVOverlay(wd->lay);
198        ms_mutex_unlock(&wd->sdl_mutex);
199}
200
201static void sdl_display_unlock(MSDisplay *obj){
202        SdlDisplay *wd = (SdlDisplay*)obj->data;
203        ms_mutex_lock(&wd->sdl_mutex);
204        SDL_UnlockYUVOverlay(wd->lay);
205        ms_mutex_unlock(&wd->sdl_mutex);
206}
207
208static void sdl_display_update(MSDisplay *obj, int new_image, int new_selfview){
209        SdlDisplay *wd = (SdlDisplay*)obj->data;
210        SDL_Rect rect;
211        rect.x=0;
212        rect.y=0;
213        ms_mutex_lock(&wd->sdl_mutex);
214        rect.w=wd->lay->w;
215        rect.h=wd->lay->h;
216        SDL_DisplayYUVOverlay(wd->lay,&rect);
217        ms_mutex_unlock(&wd->sdl_mutex);
218}
219
220static bool_t sdl_poll_event(MSDisplay *obj, MSDisplayEvent *ev){
221        SdlDisplay *wd = (SdlDisplay*)obj->data;
222        SDL_Event event;
223        bool_t ret=FALSE;
224        if (wd->sdl_screen==NULL) return FALSE;
225        ms_mutex_lock(&wd->sdl_mutex);
226        if (SDL_PollEvent(&event)){
227                ms_mutex_unlock(&wd->sdl_mutex);
228                switch(event.type){
229                        case SDL_VIDEORESIZE:
230                                ev->evtype=MS_DISPLAY_RESIZE_EVENT;
231                                ev->w=event.resize.w;
232                                ev->h=event.resize.h;
233                                return TRUE;
234                        break;
235                        default:
236                        break;
237                }
238        }else ms_mutex_unlock(&wd->sdl_mutex);
239        return ret;
240}
241
242static void sdl_display_uninit(MSDisplay *obj){
243        SdlDisplay *wd = (SdlDisplay*)obj->data;
244        SDL_Event event;
245        int i;
246        if (wd==NULL)
247                return;
248        if (wd->lay!=NULL)
249                SDL_FreeYUVOverlay(wd->lay);
250        if (wd->sdl_screen!=NULL){
251                SDL_FreeSurface(wd->sdl_screen);
252                wd->sdl_screen=NULL;
253        }
254        wd->lay=NULL;
255        wd->sdl_screen=NULL;
256        ms_free(wd);
257#ifdef __linux
258        /*purge the event queue before leaving*/
259        for(i=0;SDL_PollEvent(&event) && i<100;++i){
260        }
261#endif
262        sdl_show_window(FALSE);
263        SDL_Quit();
264}
265
266MSDisplayDesc ms_sdl_display_desc={
267        .init=sdl_display_init,
268        .lock=sdl_display_lock,
269        .unlock=sdl_display_unlock,
270        .update=sdl_display_update,
271        .uninit=sdl_display_uninit,
272        .pollevent=sdl_poll_event,
273};
274
275#elif defined(WIN32)
276
277#include <Vfw.h>
278
279typedef struct _WinDisplay{
280        MSFilter *filter;
281        HWND window;
282        HDRAWDIB ddh;
283        MSPicture fb;
284        MSPicture fb_selfview;
285        uint8_t *rgb_selfview;
286        int rgb_len_selfview;
287        struct SwsContext *sws_selfview;
288        MSDisplayEvent last_rsz;
289        uint8_t *rgb;
290        int last_rect_w;
291        int last_rect_h;
292        int rgb_len;
293        struct SwsContext *sws;
294        bool_t new_ev;
295}WinDisplay;
296
297static LRESULT CALLBACK window_proc(
298    HWND hwnd,        // handle to window
299    UINT uMsg,        // message identifier
300    WPARAM wParam,    // first message parameter
301    LPARAM lParam)    // second message parameter
302{
303        switch(uMsg){
304                case WM_DESTROY:
305                break;
306                case WM_SIZE:
307                        if (wParam==SIZE_RESTORED){
308                                int h=(lParam>>16) & 0xffff;
309                                int w=lParam & 0xffff;
310                                MSDisplay *obj;
311                                WinDisplay *wd;
312                                ms_message("Resized to %i,%i",w,h);
313                                obj=(MSDisplay*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
314                                if (obj!=NULL){
315                                        wd=(WinDisplay*)obj->data;
316                                        wd->last_rsz.evtype=MS_DISPLAY_RESIZE_EVENT;
317                                        wd->last_rsz.w=w;
318                                        wd->last_rsz.h=h;
319                                        wd->new_ev=TRUE;
320                                }else{
321                                        ms_error("Could not retrieve MSDisplay from window !");
322                                }
323                        }
324                break;
325                default:
326                        return DefWindowProc(hwnd, uMsg, wParam, lParam);
327        }
328        return 0;
329}
330
331static HWND create_window(int w, int h)
332{
333        WNDCLASS wc;
334        HINSTANCE hInstance = GetModuleHandle(NULL);
335        HWND hwnd;
336        RECT rect;
337        wc.style = 0 ;
338        wc.lpfnWndProc = window_proc;
339        wc.cbClsExtra = 0;
340        wc.cbWndExtra = 0;
341        wc.hInstance = NULL;
342        wc.hIcon = NULL;
343        wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
344        wc.hbrBackground = NULL;
345        wc.lpszMenuName =  NULL;
346        wc.lpszClassName = "Video Window";
347       
348        if(!RegisterClass(&wc))
349        {
350                /* already registred! */
351        }
352        rect.left=100;
353        rect.top=100;
354        rect.right=rect.left+w;
355        rect.bottom=rect.top+h;
356        if (!AdjustWindowRect(&rect,WS_OVERLAPPEDWINDOW|WS_VISIBLE /*WS_CAPTION WS_TILED|WS_BORDER*/,FALSE)){
357                ms_error("AdjustWindowRect failed.");
358        }
359        ms_message("AdjustWindowRect: %li,%li %li,%li",rect.left,rect.top,rect.right,rect.bottom);
360        hwnd=CreateWindow("Video Window", "Video window", 
361                WS_OVERLAPPEDWINDOW /*WS_THICKFRAME*/ | WS_VISIBLE ,
362                CW_USEDEFAULT, CW_USEDEFAULT, rect.right-rect.left,rect.bottom-rect.top,
363                                                                                                        NULL, NULL, hInstance, NULL);
364        if (hwnd==NULL){
365                ms_error("Fail to create video window");
366        }
367        return hwnd;
368}
369
370static bool_t win_display_init(MSDisplay *obj, MSFilter *f, MSPicture *fbuf, MSPicture *fbuf_selfview){
371        WinDisplay *wd=(WinDisplay*)obj->data;
372        int ysize,usize;
373
374        if (wd!=NULL)
375        {
376                wd->filter = NULL;
377                if (wd->ddh) DrawDibClose(wd->ddh);
378                wd->ddh=NULL;
379                if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
380                wd->fb.planes[0]=NULL;
381                wd->fb.planes[1]=NULL;
382                wd->fb.planes[2]=NULL;
383                wd->fb.planes[3]=NULL;
384                if (wd->rgb) ms_free(wd->rgb);
385                wd->rgb=NULL;
386                wd->rgb_len=0;
387                sws_freeContext(wd->sws);
388                wd->sws=NULL;
389                if (wd->fb_selfview.planes[0]) ms_free(wd->fb_selfview.planes[0]);
390                wd->fb_selfview.planes[0]=NULL;
391                wd->fb_selfview.planes[1]=NULL;
392                wd->fb_selfview.planes[2]=NULL;
393                wd->fb_selfview.planes[3]=NULL;
394                if (wd->rgb_selfview) ms_free(wd->rgb_selfview);
395                wd->rgb_selfview=NULL;
396                wd->rgb_len_selfview=0;
397                sws_freeContext(wd->sws_selfview);
398                wd->sws_selfview=NULL;
399                wd->last_rect_w=0;
400                wd->last_rect_h=0;
401        }
402        else
403                wd=(WinDisplay*)ms_new0(WinDisplay,1);
404       
405        wd->filter = f;
406        obj->data=wd;
407       
408        wd->fb.w=fbuf->w;
409        wd->fb.h=fbuf->h;
410        wd->fb_selfview.w=fbuf_selfview->w;
411        wd->fb_selfview.h=fbuf_selfview->h;
412
413        if (wd->window==NULL){
414                if (obj->use_external_window && obj->window_id!=0){
415                        void *p;
416                        wd->window=(HWND)obj->window_id;
417                        p=(void*)GetWindowLongPtr(wd->window,GWLP_USERDATA);
418                        if (p!=NULL){
419                                ms_error("Gulp: this externally supplied windows seems to "
420                                        "already have a userdata ! resizing will crash !");
421                        }else SetWindowLongPtr(wd->window,GWLP_USERDATA,(LONG_PTR)obj);
422                }else{
423                        wd->window=create_window(wd->fb.w,wd->fb.h);
424                        obj->window_id=(long)wd->window;
425                        if (wd->window!=NULL) SetWindowLongPtr(wd->window,GWLP_USERDATA,(LONG_PTR)obj);
426                        else return FALSE;
427                }
428        }else if (!obj->use_external_window){
429                /* the window might need to be resized*/
430                RECT cur;
431                GetWindowRect(wd->window,&cur);
432                MoveWindow(wd->window,cur.left, cur.top, wd->fb.w, wd->fb.h,TRUE);
433        }
434       
435        if (wd->ddh==NULL) wd->ddh=DrawDibOpen();
436        if (wd->ddh==NULL){
437                ms_error("DrawDibOpen() failed.");
438                return FALSE;
439        }
440
441        /*allocate yuv and rgb buffers*/
442        if (wd->fb_selfview.planes[0]) ms_free(wd->fb_selfview.planes[0]);
443        if (wd->rgb_selfview) ms_free(wd->rgb_selfview);
444        ysize=wd->fb_selfview.w*wd->fb_selfview.h;
445        usize=ysize/4;
446        fbuf_selfview->planes[0]=wd->fb_selfview.planes[0]=(uint8_t*)ms_malloc0(ysize+2*usize);
447        fbuf_selfview->planes[1]=wd->fb_selfview.planes[1]=wd->fb_selfview.planes[0]+ysize;
448        fbuf_selfview->planes[2]=wd->fb_selfview.planes[2]=wd->fb_selfview.planes[1]+usize;
449        fbuf_selfview->planes[3]=NULL;
450        fbuf_selfview->strides[0]=wd->fb_selfview.strides[0]=wd->fb_selfview.w;
451        fbuf_selfview->strides[1]=wd->fb_selfview.strides[1]=wd->fb_selfview.w/2;
452        fbuf_selfview->strides[2]=wd->fb_selfview.strides[2]=wd->fb_selfview.w/2;
453        fbuf_selfview->strides[3]=0;
454
455        wd->rgb_len_selfview=ysize*3;
456        wd->rgb_selfview=(uint8_t*)ms_malloc0(wd->rgb_len_selfview);
457
458        if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
459        if (wd->rgb) ms_free(wd->rgb);
460        ysize=wd->fb.w*wd->fb.h;
461        usize=ysize/4;
462        fbuf->planes[0]=wd->fb.planes[0]=(uint8_t*)ms_malloc0(ysize+2*usize);
463        fbuf->planes[1]=wd->fb.planes[1]=wd->fb.planes[0]+ysize;
464        fbuf->planes[2]=wd->fb.planes[2]=wd->fb.planes[1]+usize;
465        fbuf->planes[3]=NULL;
466        fbuf->strides[0]=wd->fb.strides[0]=wd->fb.w;
467        fbuf->strides[1]=wd->fb.strides[1]=wd->fb.w/2;
468        fbuf->strides[2]=wd->fb.strides[2]=wd->fb.w/2;
469        fbuf->strides[3]=0;
470
471        wd->rgb_len=ysize*3;
472        wd->rgb=(uint8_t*)ms_malloc0(wd->rgb_len);
473        wd->last_rect_w=0;
474        wd->last_rect_h=0;
475        return TRUE;
476}
477
478typedef struct rgb{
479        uint8_t r,g,b;
480} rgb_t;
481
482typedef struct yuv{
483        uint8_t y,u,v;
484} yuv_t;
485
486
487
488static void yuv420p_to_rgb(WinDisplay *wd, MSPicture *src, uint8_t *rgb){
489        int rgb_stride=-src->w*3;
490        uint8_t *p;
491
492        p=rgb+(src->w*3*(src->h-1));
493        if (wd->sws==NULL){
494                wd->sws=sws_getContext(src->w,src->h,PIX_FMT_YUV420P,
495                        src->w,src->h, PIX_FMT_BGR24,
496                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
497        }
498        if (sws_scale(wd->sws,src->planes,src->strides, 0,
499                                src->h, &p, &rgb_stride)<0){
500                ms_error("Error in 420->rgb sws_scale().");
501        }
502}
503
504static void yuv420p_to_rgb_selfview(WinDisplay *wd, MSPicture *src, uint8_t *rgb){
505        int rgb_stride=-src->w*3;
506        uint8_t *p;
507
508        p=rgb+(src->w*3*(src->h-1));
509        if (wd->sws_selfview==NULL){
510                wd->sws_selfview=sws_getContext(src->w,src->h,PIX_FMT_YUV420P,
511                        src->w,src->h, PIX_FMT_BGR24,
512                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
513        }
514        if (sws_scale(wd->sws_selfview,src->planes,src->strides, 0,
515                                src->h, &p, &rgb_stride)<0){
516                ms_error("Error in 420->rgb sws_scale().");
517        }
518}
519
520static int gcd(int m, int n)
521{
522   if(n == 0)
523     return m;
524   else
525     return gcd(n, m % n);
526}
527   
528static void reduce(int *num, int *denom)
529{
530   int divisor = gcd(*num, *denom);
531   *num /= divisor;
532   *denom /= divisor;
533}
534
535static void win_display_update(MSDisplay *obj, int new_image, int new_selfview){
536        WinDisplay *wd=(WinDisplay*)obj->data;
537        HDC hdc;
538        BITMAPINFOHEADER bi;
539        RECT rect;
540        bool_t ret;
541        int ratiow;
542        int ratioh;
543        int w;
544        int h;
545        int corner;
546        float sv_scalefactor;
547        float sv_pos[3];
548        int color[3];
549
550        HDC dd_hdc;
551        HBITMAP dd_bmp;
552        HBRUSH brush;
553        BOOL dont_draw;
554
555        if (wd->window==NULL) return;
556        hdc=GetDC(wd->window);
557        if (hdc==NULL) {
558                ms_error("Could not get window dc");
559                return;
560        }
561        if (new_image>0)
562                yuv420p_to_rgb(wd, &wd->fb, wd->rgb);
563        memset(&bi,0,sizeof(bi));
564        bi.biSize=sizeof(bi);
565        GetClientRect(wd->window,&rect);
566
567        bi.biWidth=wd->fb.w;
568        bi.biHeight=wd->fb.h;
569        bi.biPlanes=1;
570        bi.biBitCount=24;
571        bi.biCompression=BI_RGB;
572        bi.biSizeImage=wd->rgb_len;
573
574        ratiow=wd->fb.w;
575        ratioh=wd->fb.h;
576        reduce(&ratiow, &ratioh);
577        w = rect.right/ratiow*ratiow;
578        h = rect.bottom/ratioh*ratioh;
579
580        if (h*ratiow>w*ratioh)
581        {
582                w = w;
583                h = w*ratioh/ratiow;
584        }
585        else
586        {
587                h = h;
588                w = h*ratiow/ratioh;
589        }
590
591        if (h*wd->fb.w!=w*wd->fb.h)
592                ms_error("wrong ratio");
593
594        dd_hdc = CreateCompatibleDC(hdc);
595        if (dd_hdc==NULL) {
596                ms_error("Could not get CreateCompatibleDC");
597                return;
598        }
599        dd_bmp = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
600        if (dd_bmp==NULL) {
601                ms_error("Could not get CreateCompatibleBitmap");
602                return;
603        }
604
605        HGDIOBJ old_object = SelectObject(dd_hdc, dd_bmp);
606
607        dont_draw = DrawDibBegin(wd->ddh,dd_hdc, 0, 0, &bi, 0, 0, DDF_BUFFER);
608       
609        /* full screen in background color */
610        color[0]=color[1]=color[2]=0;
611        if (wd->filter)
612                ms_filter_call_method(wd->filter, MS_VIDEO_OUT_GET_BACKGROUND_COLOR, &color);
613       
614        brush = CreateSolidBrush(RGB(color[0],color[1],color[2]));
615        FillRect(dd_hdc, &rect, brush); 
616        DeleteObject(brush);
617
618        corner = 0;
619        sv_scalefactor = SCALE_FACTOR;
620        sv_pos[0] = SELVIEW_POS_INACTIVE;
621        sv_pos[1] = SELVIEW_POS_INACTIVE;
622        sv_pos[2] = 0;
623        if (wd->filter)
624                ms_filter_call_method(wd->filter, MS_VIDEO_OUT_GET_CORNER, &corner);
625        if (wd->filter)
626                ms_filter_call_method(wd->filter, MS_VIDEO_OUT_GET_SCALE_FACTOR, &sv_scalefactor);
627        if (wd->filter)
628                ms_filter_call_method(wd->filter, MS_VIDEO_OUT_GET_SELFVIEW_POS, sv_pos);
629
630        if (wd->rgb_selfview==NULL || corner==-1) {
631                ret=DrawDibDraw(wd->ddh,dd_hdc,
632                        (rect.right-w)/2,
633                        (rect.bottom-h)/2,
634                        w,
635                        h,
636                        &bi,wd->rgb,
637                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
638       
639        } else {
640
641                int w_selfview = rect.right - w;
642                int h_selfview = rect.bottom - h;
643
644                if ((h_selfview < h/sv_scalefactor && w_selfview < w/sv_scalefactor) || corner<=3 || sv_pos[0]!=SELVIEW_POS_INACTIVE)
645                {
646                        ret=DrawDibDraw(wd->ddh,dd_hdc,
647                                (rect.right-w)/2,
648                                (rect.bottom-h)/2,
649                                w,
650                                h,
651                                &bi,wd->rgb,
652                                0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
653
654                        //preserve ratio
655                        ratiow=wd->fb_selfview.w;
656                        ratioh=wd->fb_selfview.h;
657                        reduce(&ratiow, &ratioh);
658
659                        w_selfview = (int)(w/sv_scalefactor);
660                        w_selfview = w_selfview/ratiow*ratiow;
661                        h_selfview = w_selfview*ratioh/ratiow;
662
663                        if (rect.right>100 && rect.bottom>100)
664                        {
665                                int x_sv;
666                                int y_sv;
667                                if (new_selfview>0)
668                                        yuv420p_to_rgb_selfview(wd, &wd->fb_selfview, wd->rgb_selfview);
669
670                                //HPEN hpenDot;
671                                //hpenDot = CreatePen(PS_SOLID, 1, RGB(10, 10, 10));
672                                //SelectObject(dd_hdc, hpenDot);
673                                if (sv_pos[0]!=SELVIEW_POS_INACTIVE)
674                                {
675                                        x_sv = (int)((rect.right*sv_pos[0])/100.0-w_selfview/2);
676                                        y_sv = (int)((rect.bottom*sv_pos[1])/100.0-h_selfview/2);
677                                }
678                                else if (corner==1 || corner==4+1)
679                                {
680                                        /* top left corner */
681                                        x_sv = 20;
682                                        y_sv = 20;
683                                }
684                                else if (corner==2 || corner==4+2)
685                                {
686                                        /* top right corner */
687                                        x_sv = (rect.right-w_selfview-20);
688                                        y_sv = 20;
689                                }
690                                else if (corner==3 || corner==4+3)
691                                {
692                                        /* bottom left corner */
693                                        x_sv = 20;
694                                        y_sv = (rect.bottom-h_selfview-20);
695                                }
696                                else /* corner = 0: default */
697                                {
698                                        /* bottom right corner */
699                                        x_sv = (rect.right-w_selfview-20);
700                                        y_sv = (rect.bottom-h_selfview-20);
701                                }
702
703
704                                Rectangle(dd_hdc, x_sv-2, y_sv-2, x_sv+w_selfview+2, y_sv+h_selfview+2); 
705                                ret=DrawDibDraw(wd->ddh,dd_hdc,
706                                        x_sv,
707                                        y_sv,
708                                        w_selfview,
709                                        h_selfview,
710                                        &bi,wd->rgb_selfview,
711                                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
712                        }
713                }
714                else
715                {
716                        //preserve ratio
717                        ratiow=wd->fb_selfview.w;
718                        ratioh=wd->fb_selfview.h;
719                        reduce(&ratiow, &ratioh);
720
721                        if (new_selfview>0)
722                                yuv420p_to_rgb_selfview(wd, &wd->fb_selfview, wd->rgb_selfview);
723                        if (w_selfview >= w/sv_scalefactor)
724                        {
725                                w_selfview = w_selfview/ratiow*ratiow;
726                                h_selfview = w_selfview*ratioh/ratiow;
727
728                                ret=DrawDibDraw(wd->ddh,dd_hdc,
729                                        0,
730                                        (rect.bottom-h)/2,
731                                        w,
732                                        h,
733                                        &bi,wd->rgb,
734                                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
735
736                                Rectangle(dd_hdc,
737                                        (rect.right-w_selfview)-4-2,
738                                        (rect.bottom-h_selfview)/2-2,
739                                        (rect.right)-4+2,
740                                        (rect.bottom+h_selfview)/2+2);
741
742                                ret=DrawDibDraw(wd->ddh,dd_hdc,
743                                        (rect.right-w_selfview)-4,
744                                        (rect.bottom-h_selfview)/2,
745                                        w_selfview,
746                                        h_selfview,
747                                        &bi,wd->rgb_selfview,
748                                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
749                        }
750                        else
751                        {
752                                h_selfview = h_selfview/ratioh*ratioh;
753                                w_selfview = h_selfview*ratiow/ratioh;
754
755                                ret=DrawDibDraw(wd->ddh,dd_hdc,
756                                        (rect.right-w)/2,
757                                        0,
758                                        w,
759                                        h,
760                                        &bi,wd->rgb,
761                                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
762
763                                Rectangle(dd_hdc,
764                                        (rect.right-w_selfview)/2-2,
765                                        (rect.bottom-h_selfview)-4-2,
766                                        (rect.right+w_selfview)/2+2,
767                                        (rect.bottom)-4+2);
768
769                                ret=DrawDibDraw(wd->ddh,dd_hdc,
770                                        (rect.right-w_selfview)/2,
771                                        (rect.bottom-h_selfview)-4,
772                                        w_selfview,
773                                        h_selfview,
774                                        &bi,wd->rgb_selfview,
775                                        0,0,bi.biWidth,bi.biHeight,dont_draw?DDF_DONTDRAW:0);
776                        }
777                }
778        }
779
780        DrawDibEnd(wd->ddh);
781        BitBlt(hdc, 0, 0, rect.right, rect.bottom, dd_hdc, 0, 0, SRCCOPY);
782        SelectObject(dd_hdc, old_object);
783
784        DeleteObject(dd_bmp);
785        DeleteDC(dd_hdc);
786
787        wd->last_rect_w=rect.right;
788        wd->last_rect_h=rect.bottom;
789
790        if (!ret) ms_error("DrawDibDraw failed.");
791        ReleaseDC(NULL,hdc);
792}
793
794static void win_display_uninit(MSDisplay *obj){
795        WinDisplay *wd=(WinDisplay*)obj->data;
796        if (wd==NULL)
797                return;
798        if (wd->window && !obj->use_external_window) DestroyWindow(wd->window);
799        if (wd->ddh) DrawDibClose(wd->ddh);
800        if (wd->fb_selfview.planes[0]) ms_free(wd->fb_selfview.planes[0]);
801        if (wd->rgb_selfview) ms_free(wd->rgb_selfview);
802        if (wd->sws_selfview) sws_freeContext(wd->sws_selfview);
803        if (wd->fb.planes[0]) ms_free(wd->fb.planes[0]);
804        if (wd->rgb) ms_free(wd->rgb);
805        if (wd->sws) sws_freeContext(wd->sws);
806        ms_free(wd);
807}
808
809bool_t win_display_pollevent(MSDisplay *d, MSDisplayEvent *ev){
810        return FALSE;
811}
812
813#ifdef _MSC_VER
814
815extern MSDisplayDesc ms_win_display_desc={
816        win_display_init,
817        NULL,
818        NULL,
819        win_display_update,
820        win_display_uninit,
821        win_display_pollevent
822};
823
824#else
825
826MSDisplayDesc ms_win_display_desc={
827        .init=win_display_init,
828        .update=win_display_update,
829        .uninit=win_display_uninit,
830        .pollevent=win_display_pollevent
831};
832
833#endif
834
835#endif
836
837MSDisplay *ms_display_new(MSDisplayDesc *desc){
838        MSDisplay *obj=(MSDisplay *)ms_new0(MSDisplay,1);
839        obj->desc=desc;
840        obj->data=NULL;
841        return obj;
842}
843
844void ms_display_set_window_id(MSDisplay *d, long id){
845        d->window_id=id;
846        d->use_external_window=TRUE;
847}
848
849void ms_display_destroy(MSDisplay *obj){
850        obj->desc->uninit(obj);
851        ms_free(obj);
852}
853
854#ifdef HAVE_SDL
855static MSDisplayDesc *default_display_desc=&ms_sdl_display_desc;
856#elif defined(WIN32)
857static MSDisplayDesc *default_display_desc=&ms_win_display_desc;
858#else
859static MSDisplayDesc *default_display_desc=NULL;
860#endif
861
862void ms_display_desc_set_default(MSDisplayDesc *desc){
863        default_display_desc=desc;
864}
865
866MSDisplayDesc * ms_display_desc_get_default(void){
867        return default_display_desc;
868}
869
870void ms_display_desc_set_default_window_id(MSDisplayDesc *desc, long id){
871        desc->default_window_id=id;
872}
873
874typedef struct VideoOut
875{
876        AVRational ratio;
877        MSPicture fbuf;
878        MSPicture fbuf_selfview;
879        MSPicture local_pic;
880        MSRect local_rect;
881        mblk_t *local_msg;
882        MSVideoSize prevsize;
883        int corner; /*for selfview*/
884        float scale_factor; /*for selfview*/
885        float sv_posx,sv_posy;
886        int background_color[3];
887
888        struct SwsContext *sws1;
889        struct SwsContext *sws2;
890        MSDisplay *display;
891        bool_t own_display;
892        bool_t ready;
893        bool_t autofit;
894        bool_t mirror;
895} VideoOut;
896
897static void set_corner(VideoOut *s, int corner)
898{
899        s->corner=corner;
900        s->local_pic.w=((int)(s->fbuf.w/s->scale_factor)) & ~0x1;
901        s->local_pic.h=((int)(s->fbuf.h/s->scale_factor)) & ~0x1;
902        s->local_rect.w=s->local_pic.w;
903        s->local_rect.h=s->local_pic.h;
904        if (corner==1) {
905                /* top left corner */
906                s->local_rect.x=0;
907                s->local_rect.y=0;
908        } else if (corner==2) {
909                /* top right corner */
910                s->local_rect.x=s->fbuf.w-s->local_pic.w;
911                s->local_rect.y=0;
912        } else if (corner==3) {
913                /* bottom left corner */
914                s->local_rect.x=0;
915                s->local_rect.y=s->fbuf.h-s->local_pic.h;
916        } else {
917                /* default: bottom right corner */
918                /* corner can be set to -1: to disable the self view... */
919                s->local_rect.x=s->fbuf.w-s->local_pic.w;
920                s->local_rect.y=s->fbuf.h-s->local_pic.h;
921        }
922        s->fbuf_selfview.w=(s->fbuf.w/1) & ~0x1;
923        s->fbuf_selfview.h=(s->fbuf.h/1) & ~0x1;
924}
925
926static void set_vsize(VideoOut *s, MSVideoSize *sz){
927        s->fbuf.w=sz->width & ~0x1;
928        s->fbuf.h=sz->height & ~0x1;
929        set_corner(s,s->corner);
930        ms_message("Video size set to %ix%i",s->fbuf.w,s->fbuf.h);
931}
932
933static void video_out_init(MSFilter  *f){
934        VideoOut *obj=(VideoOut*)ms_new0(VideoOut,1);
935        MSVideoSize def_size;
936        obj->ratio.num=11;
937        obj->ratio.den=9;
938        def_size.width=MS_VIDEO_SIZE_CIF_W;
939        def_size.height=MS_VIDEO_SIZE_CIF_H;
940        obj->prevsize.width=0;
941        obj->prevsize.height=0;
942        obj->local_msg=NULL;
943        obj->corner=0;
944        obj->scale_factor=SCALE_FACTOR;
945        obj->sv_posx=obj->sv_posy=SELVIEW_POS_INACTIVE;
946        obj->background_color[0]=obj->background_color[1]=obj->background_color[2]=0;
947        obj->sws1=NULL;
948        obj->sws2=NULL;
949        obj->display=NULL;
950        obj->own_display=FALSE;
951        obj->ready=FALSE;
952        obj->autofit=FALSE;
953        obj->mirror=FALSE;
954        set_vsize(obj,&def_size);
955        f->data=obj;
956}
957
958
959static void video_out_uninit(MSFilter *f){
960        VideoOut *obj=(VideoOut*)f->data;
961        if (obj->display!=NULL && obj->own_display)
962                ms_display_destroy(obj->display);
963        if (obj->sws1!=NULL){
964                sws_freeContext(obj->sws1);
965                obj->sws1=NULL;
966        }
967        if (obj->sws2!=NULL){
968                sws_freeContext(obj->sws2);
969                obj->sws2=NULL;
970        }
971        if (obj->local_msg!=NULL) {
972                freemsg(obj->local_msg);
973                obj->local_msg=NULL;
974        }
975        ms_free(obj);
976}
977
978static void video_out_prepare(MSFilter *f){
979        VideoOut *obj=(VideoOut*)f->data;
980        if (obj->display==NULL){
981                if (default_display_desc==NULL){
982                        ms_error("No default display built in !");
983                        return;
984                }
985                obj->display=ms_display_new(default_display_desc);
986                obj->own_display=TRUE;
987        }
988        if (!ms_display_init(obj->display,f,&obj->fbuf,&obj->fbuf_selfview)){
989                if (obj->own_display) ms_display_destroy(obj->display);
990                obj->display=NULL;
991        }
992        if (obj->sws1!=NULL){
993                sws_freeContext(obj->sws1);
994                obj->sws1=NULL;
995        }
996        if (obj->sws2!=NULL){
997                sws_freeContext(obj->sws2);
998                obj->sws2=NULL;
999        }
1000        if (obj->local_msg!=NULL) {
1001                freemsg(obj->local_msg);
1002                obj->local_msg=NULL;
1003        }
1004        set_corner(obj,obj->corner);
1005        obj->ready=TRUE;
1006}
1007
1008static int video_out_handle_resizing(MSFilter *f, void *data){
1009        VideoOut *s=(VideoOut*)f->data;
1010        MSDisplay *disp=s->display;
1011        if (disp!=NULL){
1012                MSDisplayEvent ev;
1013                if (ms_display_poll_event(disp,&ev)){
1014                        if (ev.evtype==MS_DISPLAY_RESIZE_EVENT){
1015                                MSVideoSize sz;
1016                                sz.width=ev.w;
1017                                sz.height=ev.h;
1018                                ms_filter_lock(f);
1019                                if (s->ready){
1020                                        set_vsize(s,&sz);
1021                                        s->ready=FALSE;
1022                                }
1023                                ms_filter_unlock(f);
1024                        }
1025                }
1026        }
1027        return 0;
1028}
1029
1030static void video_out_preprocess(MSFilter *f){
1031        video_out_prepare(f);
1032}
1033
1034
1035static void video_out_process(MSFilter *f){
1036        VideoOut *obj=(VideoOut*)f->data;
1037        mblk_t *inm;
1038        int update=0;
1039        int update_selfview=0;
1040
1041        ms_filter_lock(f);
1042        if (!obj->ready) video_out_prepare(f);
1043        if (obj->display==NULL){
1044                ms_filter_unlock(f);
1045                if (f->inputs[0]!=NULL)
1046                        ms_queue_flush(f->inputs[0]);
1047                if (f->inputs[1]!=NULL)
1048                        ms_queue_flush(f->inputs[1]);
1049                return;
1050        }
1051        /*get most recent message and draw it*/
1052        if (f->inputs[1]!=NULL && (inm=ms_queue_peek_last(f->inputs[1]))!=0) {
1053                if (obj->corner==-1){
1054                        if (obj->local_msg!=NULL) {
1055                                freemsg(obj->local_msg);
1056                                obj->local_msg=NULL;
1057                        }
1058                }else if (obj->fbuf_selfview.planes[0]!=NULL) {
1059                        MSPicture src;
1060                        if (yuv_buf_init_from_mblk(&src,inm)==0){
1061                               
1062                                if (obj->sws2==NULL){
1063                                        obj->sws2=sws_getContext(src.w,src.h,PIX_FMT_YUV420P,
1064                                                                                         obj->fbuf_selfview.w,obj->fbuf_selfview.h,PIX_FMT_YUV420P,
1065                                                                                         SWS_FAST_BILINEAR, NULL, NULL, NULL);
1066                                }
1067                                ms_display_lock(obj->display);
1068                                if (sws_scale(obj->sws2,src.planes,src.strides, 0,
1069                                                          src.h, obj->fbuf_selfview.planes, obj->fbuf_selfview.strides)<0){
1070                                        ms_error("Error in sws_scale().");
1071                                }
1072                                if (!mblk_get_precious_flag(inm)) yuv_buf_mirror(&obj->fbuf_selfview);
1073                                ms_display_unlock(obj->display);
1074                                update_selfview=1;
1075                        }
1076                }else{
1077                        MSPicture src;
1078                        if (yuv_buf_init_from_mblk(&src,inm)==0){
1079                               
1080                                if (obj->sws2==NULL){
1081                                        obj->sws2=sws_getContext(src.w,src.h,PIX_FMT_YUV420P,
1082                                                                obj->local_pic.w,obj->local_pic.h,PIX_FMT_YUV420P,
1083                                                                SWS_FAST_BILINEAR, NULL, NULL, NULL);
1084                                }
1085                                if (obj->local_msg==NULL){
1086                                        obj->local_msg=yuv_buf_alloc(&obj->local_pic,
1087                                                obj->local_pic.w,obj->local_pic.h);
1088                                }
1089                                if (obj->local_pic.planes[0]!=NULL)
1090                                {
1091                                        if (sws_scale(obj->sws2,src.planes,src.strides, 0,
1092                                                src.h, obj->local_pic.planes, obj->local_pic.strides)<0){
1093                                                ms_error("Error in sws_scale().");
1094                                        }
1095                                        if (!mblk_get_precious_flag(inm)) yuv_buf_mirror(&obj->local_pic);
1096                                        update=1;
1097                                }
1098                        }
1099                }
1100                ms_queue_flush(f->inputs[1]);
1101        }
1102       
1103        if (f->inputs[0]!=NULL && (inm=ms_queue_peek_last(f->inputs[0]))!=0) {
1104                MSPicture src;
1105                if (yuv_buf_init_from_mblk(&src,inm)==0){
1106                        MSVideoSize cur,newsize;
1107                        cur.width=obj->fbuf.w;
1108                        cur.height=obj->fbuf.h;
1109                        newsize.width=src.w;
1110                        newsize.height=src.h;
1111                        if (obj->autofit && !ms_video_size_equal(newsize,obj->prevsize) ) {
1112                                MSVideoSize qvga_size;
1113                                qvga_size.width=MS_VIDEO_SIZE_QVGA_W;
1114                                qvga_size.height=MS_VIDEO_SIZE_QVGA_H;
1115                                obj->prevsize=newsize;
1116                                ms_message("received size is %ix%i",newsize.width,newsize.height);
1117                                /*don't resize less than QVGA, it is too small*/
1118                                if (ms_video_size_greater_than(qvga_size,newsize)){
1119                                        newsize.width=MS_VIDEO_SIZE_QVGA_W;
1120                                        newsize.height=MS_VIDEO_SIZE_QVGA_H;
1121                                }
1122                                if (!ms_video_size_equal(newsize,cur)){
1123                                        set_vsize(obj,&newsize);
1124                                        ms_message("autofit: new size is %ix%i",newsize.width,newsize.height);
1125                                        video_out_prepare(f);
1126                                }
1127                        }
1128                        if (obj->sws1==NULL){
1129                                obj->sws1=sws_getContext(src.w,src.h,PIX_FMT_YUV420P,
1130                                obj->fbuf.w,obj->fbuf.h,PIX_FMT_YUV420P,
1131                                SWS_FAST_BILINEAR, NULL, NULL, NULL);
1132                        }
1133                        ms_display_lock(obj->display);
1134                        if (sws_scale(obj->sws1,src.planes,src.strides, 0,
1135                                src.h, obj->fbuf.planes, obj->fbuf.strides)<0){
1136                                ms_error("Error in sws_scale().");
1137                        }
1138                        if (obj->mirror && !mblk_get_precious_flag(inm)) yuv_buf_mirror(&obj->fbuf);
1139                        ms_display_unlock(obj->display);
1140                }
1141                update=1;
1142                ms_queue_flush(f->inputs[0]);
1143        }
1144
1145        /*copy resized local view into main buffer, at bottom left corner:*/
1146        if (obj->local_msg!=NULL){
1147                MSPicture corner=obj->fbuf;
1148                MSVideoSize roi;
1149                roi.width=obj->local_pic.w;
1150                roi.height=obj->local_pic.h;
1151                corner.w=obj->local_pic.w;
1152                corner.h=obj->local_pic.h;
1153                corner.planes[0]+=obj->local_rect.x+(obj->local_rect.y*corner.strides[0]);
1154                corner.planes[1]+=(obj->local_rect.x/2)+((obj->local_rect.y/2)*corner.strides[1]);
1155                corner.planes[2]+=(obj->local_rect.x/2)+((obj->local_rect.y/2)*corner.strides[2]);
1156                corner.planes[3]=0;
1157                ms_display_lock(obj->display);
1158                yuv_buf_copy(obj->local_pic.planes,obj->local_pic.strides,
1159                                corner.planes,corner.strides,roi);
1160                ms_display_unlock(obj->display);
1161        }
1162
1163        ms_display_update(obj->display, update, update_selfview);
1164        ms_filter_unlock(f);
1165}
1166
1167static int video_out_set_vsize(MSFilter *f,void *arg){
1168        VideoOut *s=(VideoOut*)f->data;
1169        ms_filter_lock(f);
1170        set_vsize(s,(MSVideoSize*)arg);
1171        ms_filter_unlock(f);
1172        return 0;
1173}
1174
1175static int video_out_set_display(MSFilter *f,void *arg){
1176        VideoOut *s=(VideoOut*)f->data;
1177        s->display=(MSDisplay*)arg;
1178        return 0;
1179}
1180
1181static int video_out_auto_fit(MSFilter *f, void *arg){
1182        VideoOut *s=(VideoOut*)f->data;
1183        s->autofit=*(int*)arg;
1184        return 0;
1185}
1186
1187static int video_out_set_corner(MSFilter *f,void *arg){
1188        VideoOut *s=(VideoOut*)f->data;
1189        s->sv_posx=s->sv_posy=SELVIEW_POS_INACTIVE;
1190        ms_filter_lock(f);
1191        set_corner(s, *(int*)arg);
1192        if (s->display){
1193                ms_display_lock(s->display);
1194                {
1195                int w=s->fbuf.w;
1196                int h=s->fbuf.h;
1197                int ysize=w*h;
1198                int usize=ysize/4;
1199               
1200                memset(s->fbuf.planes[0], 0, ysize);
1201                memset(s->fbuf.planes[1], 0, usize);
1202                memset(s->fbuf.planes[2], 0, usize);
1203                s->fbuf.planes[3]=NULL;
1204                }
1205                ms_display_unlock(s->display);
1206        }
1207        ms_filter_unlock(f);
1208        return 0;
1209}
1210
1211static int video_out_get_corner(MSFilter *f,void *arg){
1212        VideoOut *s=(VideoOut*)f->data;
1213        *((int*)arg)=s->corner;
1214        return 0;
1215}
1216
1217static int video_out_set_scalefactor(MSFilter *f,void *arg){
1218        VideoOut *s=(VideoOut*)f->data;
1219        s->scale_factor = *(float*)arg;
1220        if (s->scale_factor<0.5f)
1221                s->scale_factor = 0.5f;
1222        ms_filter_lock(f);
1223        set_corner(s, s->corner);
1224        if (s->display){
1225                ms_display_lock(s->display);
1226                {
1227                int w=s->fbuf.w;
1228                int h=s->fbuf.h;
1229                int ysize=w*h;
1230                int usize=ysize/4;
1231               
1232                memset(s->fbuf.planes[0], 0, ysize);
1233                memset(s->fbuf.planes[1], 0, usize);
1234                memset(s->fbuf.planes[2], 0, usize);
1235                s->fbuf.planes[3]=NULL;
1236                }
1237                ms_display_unlock(s->display);
1238        }
1239        ms_filter_unlock(f);
1240        return 0;
1241}
1242
1243static int video_out_get_scalefactor(MSFilter *f,void *arg){
1244        VideoOut *s=(VideoOut*)f->data;
1245        *((float*)arg)=(float)s->scale_factor;
1246        return 0;
1247}
1248
1249
1250static int video_out_enable_mirroring(MSFilter *f,void *arg){
1251        VideoOut *s=(VideoOut*)f->data;
1252        s->mirror=*(int*)arg;
1253        return 0;
1254}
1255
1256static int video_out_get_native_window_id(MSFilter *f, void*arg){
1257        VideoOut *s=(VideoOut*)f->data;
1258        unsigned long *id=(unsigned long*)arg;
1259        *id=0;
1260        if (s->display){
1261                *id=s->display->window_id;
1262                return 0;
1263        }
1264        return -1;
1265}
1266
1267static int video_out_set_selfview_pos(MSFilter *f,void *arg){
1268        VideoOut *s=(VideoOut*)f->data;
1269        s->sv_posx=((float*)arg)[0];
1270        s->sv_posy=((float*)arg)[1];
1271        s->scale_factor=(float)100.0/((float*)arg)[2];
1272        return 0;
1273}
1274
1275static int video_out_get_selfview_pos(MSFilter *f,void *arg){
1276        VideoOut *s=(VideoOut*)f->data;
1277        ((float*)arg)[0]=s->sv_posx;
1278        ((float*)arg)[1]=s->sv_posy;
1279        ((float*)arg)[2]=(float)100.0/s->scale_factor;
1280        return 0;
1281}
1282
1283static int video_out_set_background_color(MSFilter *f,void *arg){
1284        VideoOut *s=(VideoOut*)f->data;
1285        s->background_color[0]=((int*)arg)[0];
1286        s->background_color[1]=((int*)arg)[1];
1287        s->background_color[2]=((int*)arg)[2];
1288        return 0;
1289}
1290
1291static int video_out_get_background_color(MSFilter *f,void *arg){
1292        VideoOut *s=(VideoOut*)f->data;
1293        ((int*)arg)[0]=s->background_color[0];
1294        ((int*)arg)[1]=s->background_color[1];
1295        ((int*)arg)[2]=s->background_color[2];
1296        return 0;
1297}
1298
1299static MSFilterMethod methods[]={
1300        {       MS_FILTER_SET_VIDEO_SIZE        ,       video_out_set_vsize },
1301        {       MS_VIDEO_OUT_SET_DISPLAY        ,       video_out_set_display},
1302        {       MS_VIDEO_OUT_SET_CORNER         ,       video_out_set_corner},
1303        {       MS_VIDEO_OUT_AUTO_FIT           ,       video_out_auto_fit},
1304        {       MS_VIDEO_OUT_HANDLE_RESIZING    ,       video_out_handle_resizing},
1305        {       MS_VIDEO_OUT_ENABLE_MIRRORING   ,       video_out_enable_mirroring},
1306        {       MS_VIDEO_OUT_GET_NATIVE_WINDOW_ID,      video_out_get_native_window_id},
1307        {       MS_VIDEO_OUT_GET_CORNER         ,       video_out_get_corner},
1308        {       MS_VIDEO_OUT_SET_SCALE_FACTOR   ,       video_out_set_scalefactor},
1309        {       MS_VIDEO_OUT_GET_SCALE_FACTOR   ,       video_out_get_scalefactor},
1310        {       MS_VIDEO_OUT_SET_SELFVIEW_POS    ,      video_out_set_selfview_pos},
1311        {       MS_VIDEO_OUT_GET_SELFVIEW_POS    ,  video_out_get_selfview_pos},
1312        {       MS_VIDEO_OUT_SET_BACKGROUND_COLOR    ,  video_out_set_background_color},
1313        {       MS_VIDEO_OUT_GET_BACKGROUND_COLOR    ,  video_out_get_background_color},
1314       
1315        {       0       ,NULL}
1316};
1317
1318#ifdef _MSC_VER
1319
1320MSFilterDesc ms_video_out_desc={
1321        MS_VIDEO_OUT_ID,
1322        "MSVideoOut",
1323        N_("A generic video display"),
1324        MS_FILTER_OTHER,
1325        NULL,
1326        2,
1327        0,
1328        video_out_init,
1329        video_out_preprocess,
1330        video_out_process,
1331        NULL,
1332        video_out_uninit,
1333        methods
1334};
1335
1336#else
1337
1338MSFilterDesc ms_video_out_desc={
1339        .id=MS_VIDEO_OUT_ID,
1340        .name="MSVideoOut",
1341        .text=N_("A generic video display"),
1342        .category=MS_FILTER_OTHER,
1343        .ninputs=2,
1344        .noutputs=0,
1345        .init=video_out_init,
1346        .preprocess=video_out_preprocess,
1347        .process=video_out_process,
1348        .uninit=video_out_uninit,
1349        .methods=methods
1350};
1351
1352#endif
1353
1354MS_FILTER_DESC_EXPORT(ms_video_out_desc)
Note: See TracBrowser for help on using the repository browser.