wingdi.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:16k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: wingdi.c 8551 2004-08-28 17:36:02Z gbazin $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <string.h>
  28. #include <vlc/vlc.h>
  29. #include <vlc/vout.h>
  30. #define WIN32_LEAN_AND_MEAN
  31. #include <windows.h>
  32. #define MAX_DIRECTBUFFERS 10
  33. /*****************************************************************************
  34.  * Local prototypes
  35.  *****************************************************************************/
  36. static int  OpenVideo  ( vlc_object_t * );
  37. static void CloseVideo ( vlc_object_t * );
  38. static int  Init      ( vout_thread_t * );
  39. static void End       ( vout_thread_t * );
  40. static int  Manage    ( vout_thread_t * );
  41. static void Render    ( vout_thread_t *, picture_t * );
  42. static void Display   ( vout_thread_t *, picture_t * );
  43. static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
  44. static void EventThread        ( vlc_object_t * );
  45. static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM );
  46. static void InitBuffers        ( vout_thread_t * );
  47. /*****************************************************************************
  48.  * Private structure
  49.  *****************************************************************************/
  50. struct vout_sys_t
  51. {
  52.     /* The event thread */
  53.     vlc_object_t * p_event;
  54.     /* Our video output window */
  55.     HWND window;
  56.     int  i_depth;
  57.     /* Our offscreen bitmap and its framebuffer */
  58.     HDC        off_dc;
  59.     HBITMAP    off_bitmap;
  60.     uint8_t *  p_buffer;
  61.     BITMAPINFO bitmapinfo;
  62.     RGBQUAD    red;
  63.     RGBQUAD    green;
  64.     RGBQUAD    blue;
  65. };
  66. /*****************************************************************************
  67.  * Module descriptor
  68.  *****************************************************************************/
  69. vlc_module_begin();
  70.     set_description( _("Windows GDI video output") );
  71.     set_capability( "video output", 10 );
  72.     set_callbacks( OpenVideo, CloseVideo );
  73. vlc_module_end();
  74. /*****************************************************************************
  75.  * OpenVideo: activate GDI video thread output method
  76.  *****************************************************************************/
  77. static int OpenVideo ( vlc_object_t *p_this )
  78. {
  79.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  80.     vlc_value_t val;
  81.     p_vout->p_sys = malloc( sizeof(vout_sys_t) );
  82.     if( !p_vout->p_sys )
  83.     {
  84.         return VLC_ENOMEM;
  85.     }
  86.     p_vout->p_sys->p_event = vlc_object_create( p_vout, VLC_OBJECT_GENERIC );
  87.     if( !p_vout->p_sys->p_event )
  88.     {
  89.         free( p_vout->p_sys );
  90.         return VLC_ENOMEM;
  91.     }
  92.     var_Create( p_vout->p_sys->p_event, "p_vout", VLC_VAR_ADDRESS );
  93.     val.p_address = (void *)p_vout;
  94.     var_Set( p_vout->p_sys->p_event, "p_vout", val );
  95.     p_vout->pf_init = Init;
  96.     p_vout->pf_end = End;
  97.     p_vout->pf_manage = Manage;
  98.     p_vout->pf_render = Render;
  99.     p_vout->pf_display = Display;
  100.     return VLC_SUCCESS;
  101. }
  102. /*****************************************************************************
  103.  * CloseVideo: deactivate the GDI video output
  104.  *****************************************************************************/
  105. static void CloseVideo ( vlc_object_t *p_this )
  106. {
  107.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  108.     var_Destroy( p_vout->p_sys->p_event, "p_vout" );
  109.     vlc_object_destroy( p_vout->p_sys->p_event );
  110.     free( p_vout->p_sys );
  111. }
  112. /*****************************************************************************
  113.  * Init: initialize video thread output method
  114.  *****************************************************************************/
  115. static int Init( vout_thread_t *p_vout )
  116. {
  117.     int i_index;
  118.     picture_t *p_pic;
  119.     if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread",
  120.                            EventThread, 0, 1 ) )
  121.     {
  122.         msg_Err( p_vout, "cannot spawn EventThread" );
  123.         return VLC_ETHREAD;
  124.     }
  125.     I_OUTPUTPICTURES = 0;
  126.     /* Initialize the output structure */
  127.     switch( p_vout->p_sys->i_depth )
  128.     {
  129.         case 8:
  130.             p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
  131.             p_vout->output.pf_setpalette = SetPalette;
  132.             break;
  133.         case 24:
  134.             p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
  135.             p_vout->output.i_rmask  = 0x00ff0000;
  136.             p_vout->output.i_gmask  = 0x0000ff00;
  137.             p_vout->output.i_bmask  = 0x000000ff;
  138.             break;
  139.         case 32:
  140.             p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
  141.             p_vout->output.i_rmask  = 0x00ff0000;
  142.             p_vout->output.i_gmask  = 0x0000ff00;
  143.             p_vout->output.i_bmask  = 0x000000ff;
  144.             break;
  145.         default:
  146.         case 16:
  147.             p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
  148.             p_vout->output.i_rmask  = 0x7c00;
  149.             p_vout->output.i_gmask  = 0x03e0;
  150.             p_vout->output.i_bmask  = 0x001f;
  151.             break;
  152.     }
  153.     p_vout->output.i_width  = p_vout->render.i_width;
  154.     p_vout->output.i_height = p_vout->render.i_height;
  155.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  156.     /* Try to initialize MAX_DIRECTBUFFERS direct buffers */
  157.     while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
  158.     {
  159.         p_pic = NULL;
  160.         /* Find an empty picture slot */
  161.         for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
  162.         {
  163.             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
  164.             {
  165.                 p_pic = p_vout->p_picture + i_index;
  166.                 break;
  167.             }
  168.         }
  169.         /* Allocate the picture */
  170.         if( p_pic == NULL )
  171.         {
  172.             break;
  173.         }
  174.         vout_AllocatePicture( p_vout, p_pic, p_vout->output.i_chroma,
  175.                               p_vout->output.i_width, p_vout->output.i_height,
  176.                               p_vout->output.i_aspect );
  177.         if( p_pic->i_planes == 0 )
  178.         {
  179.             break;
  180.         }
  181.         p_pic->i_status = DESTROYED_PICTURE;
  182.         p_pic->i_type   = DIRECT_PICTURE;
  183.         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
  184.         I_OUTPUTPICTURES++;
  185.     }
  186.     return VLC_SUCCESS;
  187. }
  188. /*****************************************************************************
  189.  * End: terminate video thread output method
  190.  *****************************************************************************/
  191. static void End( vout_thread_t *p_vout )
  192. {
  193.     int i_index;
  194.     /* Free the fake output buffers we allocated */
  195.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  196.     {
  197.         i_index--;
  198.         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
  199.     }
  200.     p_vout->p_sys->p_event->b_die = VLC_TRUE;
  201.     PostMessage( p_vout->p_sys->window, WM_NULL, 0, 0 );
  202.     vlc_thread_join( p_vout->p_sys->p_event );
  203. }
  204. /*****************************************************************************
  205.  * Manage: handle events
  206.  *****************************************************************************
  207.  * This function should be called regularly by video output thread. It manages
  208.  * console events. It returns a non null value on error.
  209.  *****************************************************************************/
  210. static int Manage( vout_thread_t *p_vout )
  211. {
  212.     return VLC_SUCCESS;
  213. }
  214. /*****************************************************************************
  215.  * Render: render previously calculated output
  216.  *****************************************************************************/
  217. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  218. {
  219.     /* No need to do anything, the fake direct buffers stay as they are */
  220. }
  221. /*****************************************************************************
  222.  * Display: displays previously rendered output
  223.  *****************************************************************************/
  224. static void Display( vout_thread_t *p_vout, picture_t *p_pic )
  225. {
  226.     /* No need to do anything, the fake direct buffers stay as they are */
  227.     HDC hdc;
  228.     int i_src_bytes, i_dest_bytes;
  229.     hdc = GetDC( p_vout->p_sys->window );
  230.     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
  231.     /* Stupid GDI is upside-down */
  232.     i_src_bytes = p_pic->p->i_visible_lines * p_pic->p->i_pitch;
  233.     i_dest_bytes = 0;
  234.     while( i_src_bytes )
  235.     {
  236.         i_src_bytes -= p_pic->p->i_pitch;
  237.         p_vout->p_vlc->pf_memcpy( p_vout->p_sys->p_buffer + i_dest_bytes,
  238.                                   p_pic->p->p_pixels + i_src_bytes,
  239.                                   p_pic->p->i_visible_pitch );
  240.         i_dest_bytes += p_pic->p->i_pitch;
  241.     }
  242.     BitBlt( hdc, 0, 0, p_vout->output.i_width, p_vout->output.i_height,
  243.             p_vout->p_sys->off_dc, 0, 0, SRCCOPY );
  244.     ReleaseDC( p_vout->p_sys->window, hdc );
  245. }
  246. /*****************************************************************************
  247.  * SetPalette: sets an 8 bpp palette
  248.  *****************************************************************************/
  249. static void SetPalette( vout_thread_t *p_vout,
  250.                         uint16_t *red, uint16_t *green, uint16_t *blue )
  251. {
  252.     msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
  253. }
  254. /*****************************************************************************
  255.  * EventThread: Event handling thread
  256.  *****************************************************************************/
  257. static void EventThread ( vlc_object_t *p_event )
  258. {
  259.     vout_thread_t * p_vout;
  260.     vlc_value_t     val;
  261.     HINSTANCE  instance;
  262.     WNDCLASS   wc;
  263.     MSG        msg;
  264. #ifdef UNDER_CE
  265.     wchar_t *psz_class = L"VOUT";
  266.     wchar_t *psz_title = L"Video Output";
  267. #else
  268.     char *psz_class = "VOUT";
  269.     char *psz_title = "Video Output";
  270. #endif
  271.     var_Get( p_event, "p_vout", &val );
  272.     p_vout = (vout_thread_t *)val.p_address;
  273.     instance = GetModuleHandle( NULL );
  274.     /* Register window class */
  275.     memset( &wc, 0, sizeof(wc) );
  276.     wc.style          = CS_HREDRAW | CS_VREDRAW;
  277.     wc.lpfnWndProc    = (WNDPROC)WndProc;
  278.     wc.cbClsExtra     = 0;
  279.     wc.cbWndExtra     = 0;
  280.     wc.hInstance      = instance;
  281.     wc.hIcon          = 0;
  282.     wc.hCursor        = 0;
  283.     wc.hbrBackground  = (HBRUSH)GetStockObject( BLACK_BRUSH );
  284.     wc.lpszMenuName   = 0;
  285.     wc.lpszClassName  = psz_class;
  286.     RegisterClass( &wc );
  287.     /* Create output window */
  288.     p_vout->p_sys->window =
  289.              CreateWindow( psz_class, psz_title,
  290.                            WS_VISIBLE | WS_SIZEBOX | WS_CAPTION,
  291.                            CW_USEDEFAULT, CW_USEDEFAULT,
  292.                            p_vout->render.i_width,
  293.                            p_vout->render.i_height + 10,
  294.                            NULL, NULL, instance, (LPVOID)p_vout );
  295.     /* Initialize offscreen buffer */
  296.     InitBuffers( p_vout );
  297.     /* Tell the video output we're ready to receive data */
  298.     vlc_thread_ready( p_event );
  299.     /* Display our window */
  300.     ShowWindow( p_vout->p_sys->window, SW_SHOWNORMAL );
  301.     UpdateWindow( p_vout->p_sys->window );
  302.     while( !p_event->b_die
  303.              && GetMessage( &msg, p_vout->p_sys->window, 0, 0 ) )
  304.     {
  305.         if( p_event->b_die )
  306.         {
  307.             break;
  308.         }
  309.         switch( msg.message )
  310.         {
  311.         case WM_KEYDOWN:
  312.             switch( msg.wParam )
  313.             {
  314.             case VK_ESCAPE:
  315.                 p_event->p_vlc->b_die = VLC_TRUE;
  316.                 break;
  317.             }
  318.             TranslateMessage( &msg );
  319.             break;
  320.         case WM_CHAR:
  321.             switch( msg.wParam )
  322.             {
  323.             case 'q':
  324.             case 'Q':
  325.                 p_event->p_vlc->b_die = VLC_TRUE;
  326.                 break;
  327.             }
  328.             break;
  329.         default:
  330.             TranslateMessage( &msg );
  331.             DispatchMessage( &msg );
  332.             break;
  333.         }
  334.     }
  335.     DestroyWindow( p_vout->p_sys->window );
  336.     DeleteDC( p_vout->p_sys->off_dc );
  337.     DeleteObject( p_vout->p_sys->off_bitmap );
  338. }
  339. /*****************************************************************************
  340.  * Message handler for the main window
  341.  *****************************************************************************/
  342. static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
  343.                                  WPARAM wParam, LPARAM lParam )
  344. {
  345.     /* Caution: this only works */
  346.     vout_thread_t *p_vout;
  347.     if( message == WM_CREATE )
  348.     {
  349.         /* Store p_vout for future use */
  350.         p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
  351.         SetWindowLong( hWnd, GWL_USERDATA, (LONG)p_vout );
  352.     }
  353.     else
  354.     {
  355.         p_vout = (vout_thread_t *)GetWindowLong( hWnd, GWL_USERDATA );
  356.     }
  357.     switch( message )
  358.     {
  359.         case WM_LBUTTONDOWN:
  360.             break;
  361.         case WM_MOUSEMOVE:
  362.             break;
  363.         case WM_LBUTTONUP:
  364.             break;
  365.         case WM_CREATE:
  366.             break;
  367.         case WM_DESTROY:
  368.             PostQuitMessage( 0 );
  369.             break;
  370.         default:
  371.             return DefWindowProc( hWnd, message, wParam, lParam );
  372.    }
  373.    return 0;
  374. }
  375. /*****************************************************************************
  376.  * InitBuffers: initialize an offscreen bitmap for direct buffer operations.
  377.  *****************************************************************************/
  378. static void InitBuffers( vout_thread_t *p_vout )
  379. {
  380.     BITMAPINFOHEADER * p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
  381.     BITMAPINFO *       p_info = &p_vout->p_sys->bitmapinfo;
  382.     int   i_pixels = p_vout->render.i_height * p_vout->render.i_width;
  383.     HDC   window_dc;
  384.     window_dc = GetDC( p_vout->p_sys->window );
  385.     /* Get screen properties */
  386.     p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES )
  387.                               * GetDeviceCaps( window_dc, BITSPIXEL );
  388.     msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
  389.     /* Initialize offscreen bitmap */
  390.     memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) );
  391.     p_header->biSize = sizeof( BITMAPINFOHEADER );
  392.     p_header->biSizeImage = 0;
  393.     p_header->biPlanes = 1;
  394.     switch( p_vout->p_sys->i_depth )
  395.     {
  396.         case 8:
  397.             p_header->biBitCount = 8;
  398.             p_header->biCompression = BI_RGB;
  399.             /* FIXME: we need a palette here */
  400.             break;
  401.         case 24:
  402.             p_header->biBitCount = 24;
  403.             p_header->biCompression = BI_RGB;
  404.             ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
  405.             ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
  406.             ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
  407.             break;
  408.         case 32:
  409.             p_header->biBitCount = 32;
  410.             p_header->biCompression = BI_RGB;
  411.             ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
  412.             ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
  413.             ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
  414.             break;
  415.         case 16:
  416.         default:
  417.             p_header->biBitCount = 16;
  418.             p_header->biCompression = BI_RGB;
  419.             ((DWORD*)p_info->bmiColors)[0] = 0x00007c00;
  420.             ((DWORD*)p_info->bmiColors)[1] = 0x000003e0;
  421.             ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
  422.             break;
  423.     }
  424.     p_header->biWidth = p_vout->render.i_width;
  425.     p_header->biHeight = p_vout->render.i_height;
  426.     p_header->biClrImportant = 0;
  427.     p_header->biClrUsed = 0;
  428.     p_header->biXPelsPerMeter = 0;
  429.     p_header->biYPelsPerMeter = 0;
  430.     p_vout->p_sys->off_bitmap =
  431.           CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
  432.                             (void**)&p_vout->p_sys->p_buffer, NULL, 0 );
  433.     p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
  434.     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
  435.     ReleaseDC( 0, window_dc );
  436. }