Mercurial > mplayer.hg
comparison libvo/vo_sdl.c @ 784:dee122f9cdb9
Added full aspect awareness, rewrote fullscreen handling.
author | atmosfear |
---|---|
date | Sun, 13 May 2001 16:38:33 +0000 |
parents | e70a52f17f92 |
children | e09c92ca4c45 |
comparison
equal
deleted
inserted
replaced
783:b03f5689175c | 784:dee122f9cdb9 |
---|---|
94 /* define to force software-surface (video surface stored in system memory)*/ | 94 /* define to force software-surface (video surface stored in system memory)*/ |
95 #undef SDL_NOHWSURFACE | 95 #undef SDL_NOHWSURFACE |
96 | 96 |
97 //#define BUGGY_SDL //defined by configure | 97 //#define BUGGY_SDL //defined by configure |
98 | 98 |
99 /* MONITOR_ASPECT MUST BE FLOAT */ | |
100 #define MONITOR_ASPECT 4.0/3.0 | |
101 | |
99 #include <stdio.h> | 102 #include <stdio.h> |
100 #include <stdlib.h> | 103 #include <stdlib.h> |
101 #include <string.h> | 104 #include <string.h> |
102 #include <inttypes.h> | 105 #include <inttypes.h> |
103 | 106 |
128 "" | 131 "" |
129 }; | 132 }; |
130 | 133 |
131 #include <SDL/SDL.h> | 134 #include <SDL/SDL.h> |
132 | 135 |
136 #define FS 0x01 | |
137 #define VM 0x02 | |
138 #define ZOOM 0x04 | |
139 #define FLIP 0x08 | |
140 | |
133 /** Private SDL Data structure **/ | 141 /** Private SDL Data structure **/ |
134 | 142 |
135 static struct sdl_priv_s { | 143 static struct sdl_priv_s { |
136 | 144 |
137 /* output driver used by sdl */ | 145 /* output driver used by sdl */ |
143 /* SDL RGB surface */ | 151 /* SDL RGB surface */ |
144 SDL_Surface *rgbsurface; | 152 SDL_Surface *rgbsurface; |
145 | 153 |
146 /* SDL YUV overlay */ | 154 /* SDL YUV overlay */ |
147 SDL_Overlay *overlay; | 155 SDL_Overlay *overlay; |
148 | |
149 /* x,y video position for centering */ | |
150 SDL_Rect vidpos; | |
151 | 156 |
152 /* available fullscreen modes */ | 157 /* available fullscreen modes */ |
153 SDL_Rect **fullmodes; | 158 SDL_Rect **fullmodes; |
154 | 159 |
155 /* surface attributes for fullscreen and windowed mode */ | 160 /* surface attributes for fullscreen and windowed mode */ |
169 | 174 |
170 /* current fullscreen mode, 0 = highest available fullscreen mode */ | 175 /* current fullscreen mode, 0 = highest available fullscreen mode */ |
171 int fullmode; | 176 int fullmode; |
172 | 177 |
173 /* YUV ints */ | 178 /* YUV ints */ |
174 int framePlaneY, framePlaneUV; | 179 int framePlaneY, framePlaneUV, framePlaneYUY; |
175 int stridePlaneY, stridePlaneUV; | 180 int stridePlaneY, stridePlaneUV, stridePlaneYUY; |
176 | 181 |
177 /* RGB ints */ | 182 /* RGB ints */ |
178 int framePlaneRGB; | 183 int framePlaneRGB; |
179 int stridePlaneRGB; | 184 int stridePlaneRGB; |
180 | 185 |
181 /* Flip image */ | 186 /* Flip image */ |
182 int flip; | 187 int flip; |
183 | 188 |
184 int width,height; | 189 /* fullscreen behaviour; see init */ |
190 int fulltype; | |
191 | |
192 #ifdef HAVE_X11 | |
193 /* X11 Resolution */ | |
194 int XWidth, XHeight; | |
195 #endif | |
196 | |
197 /* original image dimensions */ | |
198 int width, height; | |
199 | |
200 /* destination dimensions */ | |
201 int dstwidth, dstheight; | |
202 | |
203 /* source image format (YUV/RGB/...) */ | |
185 int format; | 204 int format; |
186 } sdl_priv; | 205 } sdl_priv; |
187 | 206 |
188 | 207 |
189 /** libvo Plugin functions **/ | 208 /** libvo Plugin functions **/ |
407 if(verbose > 2) printf("SDL: Closed Plugin\n"); | 426 if(verbose > 2) printf("SDL: Closed Plugin\n"); |
408 | 427 |
409 return 0; | 428 return 0; |
410 } | 429 } |
411 | 430 |
431 /** | |
432 * Do aspect ratio calculations | |
433 * | |
434 * params : srcw == sourcewidth | |
435 * srch == sourceheight | |
436 * dstw == destinationwidth | |
437 * dsth == destinationheight | |
438 * | |
439 * returns : SDL_Rect structure with new x and y, w and h | |
440 **/ | |
441 | |
442 static SDL_Rect aspect(int srcw, int srch, int dstw, int dsth) { | |
443 SDL_Rect newres; | |
444 if(verbose > 1) printf("SDL Aspect: src: %ix%i dst: %ix%i\n", srcw, srch, dstw, dsth); | |
445 newres.h = ((float)dstw / (float)srcw * (float)srch) * ((float)dsth/((float)dstw/(MONITOR_ASPECT))); | |
446 if(newres.h > dsth) { | |
447 newres.w = ((float)dsth / (float)newres.h) * dstw; | |
448 newres.h = dsth; | |
449 newres.x = (dstw - newres.w) / 2; | |
450 newres.y = 0; | |
451 } | |
452 else { | |
453 newres.w = dstw; | |
454 newres.x = 0; | |
455 newres.y = (dsth - newres.h) / 2; | |
456 } | |
457 | |
458 if(verbose) printf("SDL Aspect-Destinationres: %ix%i (x: %i, y: %i)\n", newres.w, newres.h, newres.x, newres.y); | |
459 | |
460 return newres; | |
461 } | |
412 | 462 |
413 /** | 463 /** |
414 * Sets the specified fullscreen mode. | 464 * Sets the specified fullscreen mode. |
415 * | 465 * |
416 * params : mode == index of the desired fullscreen mode | 466 * params : mode == index of the desired fullscreen mode |
417 * returns : doesn't return | 467 * returns : doesn't return |
418 **/ | 468 **/ |
419 | 469 |
470 #if 0 | |
420 static void set_fullmode (int mode) | 471 static void set_fullmode (int mode) |
421 { | 472 { |
422 struct sdl_priv_s *priv = &sdl_priv; | 473 struct sdl_priv_s *priv = &sdl_priv; |
423 SDL_Surface *newsurface = NULL; | 474 SDL_Surface *newsurface = NULL; |
424 int haspect, waspect = 0; | 475 int haspect, waspect = 0; |
444 if (newsurface) { | 495 if (newsurface) { |
445 priv->surface = newsurface; | 496 priv->surface = newsurface; |
446 SDL_ShowCursor(0); | 497 SDL_ShowCursor(0); |
447 } | 498 } |
448 //TODO: check if this produces memhole! (no surface freeing) | 499 //TODO: check if this produces memhole! (no surface freeing) |
449 priv->vidpos.x = (priv->surface->w - priv->width) / 2; | 500 } |
450 priv->vidpos.y = (priv->surface->h - priv->height) / 2; | 501 #endif |
451 } | 502 |
452 | 503 static void set_fullmode (int mode) { |
504 struct sdl_priv_s *priv = &sdl_priv; | |
505 SDL_Surface *newsurface = NULL; | |
506 SDL_Rect newsize; | |
507 | |
508 /* if we haven't set a fullmode yet, default to the lowest res fullmode first */ | |
509 if(mode < 0) | |
510 mode = priv->fullmode = findArrayEnd(priv->fullmodes) - 1; | |
511 | |
512 /* calculate new video size/aspect */ | |
513 if(priv->fulltype&FS) { | |
514 newsize = aspect(priv->width, priv->height, priv->XWidth ? priv->XWidth : priv->dstwidth, priv->XHeight ? priv->XHeight : priv->dstheight); | |
515 } else | |
516 if(priv->fulltype&VM) { | |
517 newsize = aspect(priv->dstwidth, priv->dstheight, priv->dstwidth, priv->dstwidth*((float)priv->XHeight / (float)priv->XWidth)); | |
518 } | |
519 else { | |
520 newsize = aspect(priv->dstwidth, priv->dstheight, priv->fullmodes[mode]->w, priv->fullmodes[mode]->h); | |
521 } | |
522 | |
523 /* try to change to given fullscreenmode */ | |
524 newsurface = SDL_SetVideoMode(newsize.w, newsize.h, priv->bpp, priv->sdlfullflags); | |
525 | |
526 /* if creation of new surface was successfull, save it and hide mouse cursor */ | |
527 if(newsurface) { | |
528 priv->surface = newsurface; | |
529 SDL_ShowCursor(0); | |
530 } | |
531 } | |
532 | |
453 | 533 |
454 /** | 534 /** |
455 * Initialize an SDL surface and an SDL YUV overlay. | 535 * Initialize an SDL surface and an SDL YUV overlay. |
456 * | 536 * |
457 * params : width == width of video we'll be displaying. | 537 * params : width == width of video we'll be displaying. |
465 init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) | 545 init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) |
466 //static int sdl_setup (int width, int height) | 546 //static int sdl_setup (int width, int height) |
467 { | 547 { |
468 struct sdl_priv_s *priv = &sdl_priv; | 548 struct sdl_priv_s *priv = &sdl_priv; |
469 unsigned int sdl_format; | 549 unsigned int sdl_format; |
550 SDL_Rect res; | |
470 #ifdef HAVE_X11 | 551 #ifdef HAVE_X11 |
471 static Display *XDisplay; | 552 static Display *XDisplay; |
553 static int XScreen; | |
472 #endif | 554 #endif |
473 | 555 |
474 //priv->flip = 1; // debugging only | |
475 | |
476 sdl_format = format; | 556 sdl_format = format; |
477 switch(format){ | 557 switch(format){ |
478 case IMGFMT_YV12: | 558 case IMGFMT_YV12: |
479 if(verbose) printf("SDL: Using 0x%X (YV12) image format\n", format); break; | 559 if(verbose) printf("SDL: Using 0x%X (YV12) image format\n", format); break; |
480 case IMGFMT_IYUV: | 560 case IMGFMT_IYUV: |
525 default: | 605 default: |
526 printf("SDL: Unsupported image format (0x%X)\n",format); | 606 printf("SDL: Unsupported image format (0x%X)\n",format); |
527 return -1; | 607 return -1; |
528 } | 608 } |
529 | 609 |
530 sdl_open (NULL, NULL); | |
531 #ifdef HAVE_X11 | 610 #ifdef HAVE_X11 |
532 if(getenv("DISPLAY")) { | 611 if(getenv("DISPLAY")) { |
533 if(verbose) printf("SDL: deactivating XScreensaver/DPMS\n"); | 612 if(verbose) printf("SDL: deactivating XScreensaver/DPMS\n"); |
534 XDisplay = XOpenDisplay(getenv("DISPLAY")); | 613 XDisplay = XOpenDisplay(getenv("DISPLAY")); |
614 XScreen = DefaultScreen(XDisplay); | |
615 priv->XWidth = DisplayWidth(XDisplay, XScreen); | |
616 priv->XHeight = DisplayHeight(XDisplay, XScreen); | |
617 if(verbose) printf("SDL: X11 Resolution %ix%i\n", priv->XWidth, priv->XHeight); | |
535 saver_off(XDisplay); | 618 saver_off(XDisplay); |
536 XCloseDisplay(XDisplay); | 619 XCloseDisplay(XDisplay); |
537 } | 620 } |
538 #endif | 621 #endif |
622 sdl_open (NULL, NULL); | |
539 | 623 |
540 /* Set output window title */ | 624 /* Set output window title */ |
541 SDL_WM_SetCaption (".: MPlayer : F = Fullscreen/Windowed : C = Cycle Fullscreen Resolutions :.", "SDL Video Out"); | 625 SDL_WM_SetCaption (".: MPlayer : F = Fullscreen/Windowed : C = Cycle Fullscreen Resolutions :.", "SDL Video Out"); |
542 //SDL_WM_SetCaption (title, title); | 626 //SDL_WM_SetCaption (title, title); |
543 | 627 |
544 /* Save the original Image size */ | 628 /* Save the original Image size */ |
545 | 629 |
546 //priv->width = d_width ? d_width : width; | |
547 //priv->height = d_height ? d_height : height; | |
548 priv->width = width; | 630 priv->width = width; |
549 priv->height = height; | 631 priv->height = height; |
632 priv->dstwidth = d_width ? d_width : width; | |
633 priv->dstheight = d_height ? d_height : height; | |
634 | |
635 /*priv->width = res.w; | |
636 priv->height = res.h;*/ | |
550 priv->format = format; | 637 priv->format = format; |
551 priv->windowsize.w = d_width ? d_width : width; | 638 #ifdef HAVE_X11 |
552 priv->windowsize.h = d_height ? d_height : height; | 639 res = aspect(priv->dstwidth, priv->dstheight, priv->dstwidth, priv->dstwidth*((float)priv->XHeight / (float)priv->XWidth)); |
640 priv->windowsize.w = res.w; | |
641 priv->windowsize.h = res.h; | |
642 #else | |
643 priv->windowsize.w = priv->dstwidth; | |
644 priv->windowsize.h = priv->dstheight; | |
645 #endif | |
553 | 646 |
554 /* bit 0 (0x01) means fullscreen (-fs) | 647 /* bit 0 (0x01) means fullscreen (-fs) |
555 * bit 1 (0x02) means mode switching (-vm) | 648 * bit 1 (0x02) means mode switching (-vm) |
556 * bit 2 (0x04) enables software scaling (-zoom) | 649 * bit 2 (0x04) enables software scaling (-zoom) |
557 * bit 3 (0x08) enables flipping (-flip) | 650 * bit 3 (0x08) enables flipping (-flip) |
558 */ | 651 */ |
559 #define FS 0x01 | |
560 #define VM 0x02 | |
561 #define ZOOM 0x04 | |
562 #define FLIP 0x08 | |
563 // printf("SDL: flags are set to: %i\n", flags); | 652 // printf("SDL: flags are set to: %i\n", flags); |
564 // printf("SDL: Width: %i Height: %i D_Width %i D_Height: %i\n", width, height, d_width, d_height); | 653 // printf("SDL: Width: %i Height: %i D_Width %i D_Height: %i\n", width, height, d_width, d_height); |
565 if(flags&FLIP) { // flipping flag set, use it | 654 if(flags&FLIP) { |
566 if(verbose) printf("SDL: using flipped video (only with RGB/BGR)\n"); | 655 if(verbose) printf("SDL: using flipped video (only with RGB/BGR/packed YUV)\n"); |
567 priv->flip = 1; | 656 priv->flip = 1; |
568 } | 657 } |
569 if(flags&FS) { | 658 if(flags&FS) { |
570 priv->width = width; | |
571 priv->height = height; | |
572 if(verbose) printf("SDL: setting zoomed fullscreen without modeswitching\n"); | 659 if(verbose) printf("SDL: setting zoomed fullscreen without modeswitching\n"); |
573 printf("SDL: Info - please use -vm (unscaled) or -zoom (scaled) for best fullscreen experience\n"); | 660 printf("SDL: Info - please use -vm (unscaled) or -zoom (scaled) for best fullscreen experience\n"); |
574 if((priv->surface = SDL_SetVideoMode (d_width, d_height, priv->bpp, priv->sdlfullflags))) | 661 priv->surface = NULL; |
575 SDL_ShowCursor(0); | 662 priv->fulltype = FS; |
663 set_fullmode(priv->fullmode); | |
664 /*if((priv->surface = SDL_SetVideoMode (d_width, d_height, priv->bpp, priv->sdlfullflags))) | |
665 SDL_ShowCursor(0);*/ | |
576 } else | 666 } else |
577 if(flags&VM) { | 667 if(flags&VM) { |
578 if(verbose) printf("SDL: setting nonzoomed fullscreen with modeswitching\n"); | 668 if(verbose) printf("SDL: setting nonzoomed fullscreen with modeswitching\n"); |
579 printf("SDL: Info - please use -zoom switch to scale video\n"); | 669 printf("SDL: Info - please use -zoom switch to scale video\n"); |
580 if((priv->surface = SDL_SetVideoMode (d_width ? d_width : width, d_height ? d_height : height, priv->bpp, priv->sdlfullflags))) | 670 |
581 SDL_ShowCursor(0); | 671 priv->surface = NULL; |
672 priv->fulltype = VM; | |
673 set_fullmode(priv->fullmode); | |
674 /*if((priv->surface = SDL_SetVideoMode (d_width ? d_width : width, d_height ? d_height : height, priv->bpp, priv->sdlfullflags))) | |
675 SDL_ShowCursor(0);*/ | |
582 } else | 676 } else |
583 if(flags&ZOOM) { | 677 if(flags&ZOOM) { |
584 if(verbose) printf("SDL: setting zoomed fullscreen with modeswitching\n"); | 678 if(verbose) printf("SDL: setting zoomed fullscreen with modeswitching\n"); |
585 printf("SDL: Info - please use -vm switch instead if you don't want scaled video\n"); | 679 printf("SDL: Info - please use -vm switch instead if you don't want scaled video\n"); |
586 priv->surface=NULL; | 680 |
587 set_fullmode(priv->fullmode); | 681 priv->surface = NULL; |
682 priv->fulltype = ZOOM; | |
683 set_fullmode(priv->fullmode); | |
588 } | 684 } |
589 else { | 685 else { |
590 if(verbose) printf("SDL: setting windowed mode\n"); | 686 if(strcmp(priv->driver, "x11") == 0) { |
591 if((priv->surface = SDL_SetVideoMode (d_width, d_height, priv->bpp, priv->sdlflags)) | 687 if(verbose) printf("SDL: setting windowed mode\n"); |
592 && (strcmp(priv->driver, "dga") == 0)) SDL_ShowCursor(0); //TODO: other sdl drivers that are fullscreen only? | 688 #ifdef HAVE_X11 |
689 priv->surface = SDL_SetVideoMode (res.w, res.h, priv->bpp, priv->sdlflags); | |
690 #else | |
691 priv->surface = SDL_SetVideoMode (priv->dstwidth, priv->dstheight, priv->bpp, priv->sdlflags); | |
692 #endif | |
693 } | |
694 else { | |
695 if(verbose) printf("SDL: setting nonzoomed fullscreen with modeswitching\n"); | |
696 printf("SDL: Info - please use -zoom switch to scale video\n"); | |
697 | |
698 priv->surface = NULL; | |
699 priv->fulltype = VM; | |
700 set_fullmode(priv->fullmode); | |
701 } | |
593 } | 702 } |
594 | 703 |
595 if(!priv->surface) { // cannot SetVideoMode | 704 if(!priv->surface) { // cannot SetVideoMode |
596 printf("SDL: failed to set video mode: %s\n", SDL_GetError()); | 705 printf("SDL: failed to set video mode: %s\n", SDL_GetError()); |
597 return -1; | 706 return -1; |
660 printf ("SDL: Couldn't create a YUV overlay: %s\n", SDL_GetError()); | 769 printf ("SDL: Couldn't create a YUV overlay: %s\n", SDL_GetError()); |
661 return -1; | 770 return -1; |
662 } | 771 } |
663 priv->framePlaneY = width * height; | 772 priv->framePlaneY = width * height; |
664 priv->framePlaneUV = (width * height) >> 2; | 773 priv->framePlaneUV = (width * height) >> 2; |
774 priv->framePlaneYUY = width * height * 2; | |
665 priv->stridePlaneY = width; | 775 priv->stridePlaneY = width; |
666 priv->stridePlaneUV = width/2; | 776 priv->stridePlaneUV = width/2; |
777 priv->stridePlaneYUY = width * 2; | |
667 } | 778 } |
668 | 779 |
669 if(priv->mode) { | 780 if(priv->mode) { |
670 priv->framePlaneRGB = width * height * priv->rgbsurface->format->BytesPerPixel; | 781 priv->framePlaneRGB = width * height * priv->rgbsurface->format->BytesPerPixel; |
671 priv->stridePlaneRGB = width * priv->rgbsurface->format->BytesPerPixel; | 782 priv->stridePlaneRGB = width * priv->rgbsurface->format->BytesPerPixel; |
712 /*if (SDL_LockYUVOverlay (priv->overlay)) { | 823 /*if (SDL_LockYUVOverlay (priv->overlay)) { |
713 if(verbose) printf("SDL: Couldn't lock YUV overlay\n"); | 824 if(verbose) printf("SDL: Couldn't lock YUV overlay\n"); |
714 return -1; | 825 return -1; |
715 }*/ | 826 }*/ |
716 dst = (uint8_t *) *(priv->overlay->pixels); | 827 dst = (uint8_t *) *(priv->overlay->pixels); |
717 memcpy (dst, src[0], priv->width*priv->height*2); | 828 if(priv->flip) { |
829 mysrc+=priv->framePlaneYUY; | |
830 for(i = 0; i < priv->height; i++) { | |
831 mysrc-=priv->stridePlaneYUY; | |
832 memcpy (dst, mysrc, priv->stridePlaneYUY); | |
833 dst+=priv->stridePlaneYUY; | |
834 } | |
835 } | |
836 else memcpy (dst, src[0], priv->framePlaneYUY); | |
718 /*SDL_UnlockYUVOverlay (priv->overlay);*/ | 837 /*SDL_UnlockYUVOverlay (priv->overlay);*/ |
719 break; | 838 break; |
720 | 839 |
721 case IMGFMT_RGB15: | 840 case IMGFMT_RGB15: |
722 case IMGFMT_BGR15: | 841 case IMGFMT_BGR15: |
967 case IMGFMT_RGB24: | 1086 case IMGFMT_RGB24: |
968 case IMGFMT_BGR24: | 1087 case IMGFMT_BGR24: |
969 case IMGFMT_RGB32: | 1088 case IMGFMT_RGB32: |
970 case IMGFMT_BGR32: | 1089 case IMGFMT_BGR32: |
971 /* blit to the RGB surface */ | 1090 /* blit to the RGB surface */ |
972 blitconv = SDL_DisplayFormat(priv->rgbsurface); | 1091 blitconv = SDL_DisplayFormat(priv->rgbsurface); |
973 if(SDL_BlitSurface (blitconv, NULL, priv->surface, &priv->vidpos)) | 1092 if(SDL_BlitSurface (blitconv, NULL, priv->surface, NULL)) |
974 printf("SDL: Blit failed: %s\n", SDL_GetError()); | 1093 printf("SDL: Blit failed: %s\n", SDL_GetError()); |
975 SDL_FreeSurface(blitconv); | 1094 SDL_FreeSurface(blitconv); |
976 | 1095 |
977 /*if(SDL_MUSTLOCK(priv->surface)) { | |
978 if (SDL_LockSurface (priv->surface)) { | |
979 if(verbose) printf("SDL: Couldn't lock RGB surface\n"); | |
980 return; | |
981 } | |
982 }*/ | |
983 /* update screen */ | 1096 /* update screen */ |
984 SDL_UpdateRect(priv->surface, priv->vidpos.x, priv->vidpos.y, priv->width, priv->height); | 1097 //SDL_UpdateRect(priv->surface, 0, 0, priv->surface->clip_rect.w, priv->surface->clip_rect.h); |
985 /*if(SDL_MUSTLOCK(priv->surface)) | 1098 SDL_UpdateRects(priv->surface, 1, &priv->surface->clip_rect); |
986 SDL_UnlockSurface (priv->surface);*/ | |
987 | 1099 |
988 /* check if we have a double buffered surface and flip() if we do. */ | 1100 /* check if we have a double buffered surface and flip() if we do. */ |
989 if ( priv->surface->flags & SDL_DOUBLEBUF ) | 1101 if ( priv->surface->flags & SDL_DOUBLEBUF ) |
990 SDL_Flip(priv->surface); | 1102 SDL_Flip(priv->surface); |
991 | 1103 |