win32.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * win32.c: Screen capture module.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004-2008 the VideoLAN team
  5.  * $Id: e0cfd7abfb53add3df95916eb02c6d91a0e9aacb $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include "screen.h"
  31. #ifndef CAPTUREBLT
  32. #   define CAPTUREBLT (DWORD)0x40000000 /* Include layered windows */
  33. #endif
  34. struct screen_data_t
  35. {
  36.     HDC hdc_src;
  37.     HDC hdc_dst;
  38.     BITMAPINFO bmi;
  39.     HGDIOBJ hgdi_backup;
  40.     int i_fragment_size;
  41.     int i_fragment;
  42.     block_t *p_block;
  43. };
  44. int screen_InitCapture( demux_t *p_demux )
  45. {
  46.     demux_sys_t *p_sys = p_demux->p_sys;
  47.     screen_data_t *p_data;
  48.     int i_chroma, i_bits_per_pixel;
  49.     p_sys->p_data = p_data = calloc( 1, sizeof( screen_data_t ) );
  50.     if( !p_data )
  51.         return VLC_ENOMEM;
  52.     /* Get the device context for the whole screen */
  53.     p_data->hdc_src = CreateDC( "DISPLAY", NULL, NULL, NULL );
  54.     if( !p_data->hdc_src )
  55.     {
  56.         msg_Err( p_demux, "cannot get device context" );
  57.         free( p_data );
  58.         return VLC_EGENERIC;
  59.     }
  60.     p_data->hdc_dst = CreateCompatibleDC( p_data->hdc_src );
  61.     if( !p_data->hdc_dst )
  62.     {
  63.         msg_Err( p_demux, "cannot get compat device context" );
  64.         free( p_data );
  65.         ReleaseDC( 0, p_data->hdc_src );
  66.         return VLC_EGENERIC;
  67.     }
  68.     i_bits_per_pixel = GetDeviceCaps( p_data->hdc_src, BITSPIXEL );
  69.     switch( i_bits_per_pixel )
  70.     {
  71.     case 8: /* FIXME: set the palette */
  72.         i_chroma = VLC_FOURCC('R','G','B','2'); break;
  73.     case 15:
  74.     case 16:    /* Yes it is really 15 bits (when using BI_RGB) */
  75.         i_chroma = VLC_FOURCC('R','V','1','5'); break;
  76.     case 24:
  77.         i_chroma = VLC_FOURCC('R','V','2','4'); break;
  78.     case 32:
  79.         i_chroma = VLC_FOURCC('R','V','3','2'); break;
  80.     default:
  81.         msg_Err( p_demux, "unknown screen depth %i",
  82.                  p_sys->fmt.video.i_bits_per_pixel );
  83.         DeleteDC( p_data->hdc_dst );
  84.         ReleaseDC( 0, p_data->hdc_src );
  85.         free( p_data );
  86.         return VLC_EGENERIC;
  87.     }
  88.     es_format_Init( &p_sys->fmt, VIDEO_ES, i_chroma );
  89.     p_sys->fmt.video.i_visible_width =
  90.     p_sys->fmt.video.i_width  = GetDeviceCaps( p_data->hdc_src, HORZRES );
  91.     p_sys->fmt.video.i_visible_height =
  92.     p_sys->fmt.video.i_height = GetDeviceCaps( p_data->hdc_src, VERTRES );
  93.     p_sys->fmt.video.i_bits_per_pixel = i_bits_per_pixel;
  94.     p_sys->fmt.video.i_chroma = i_chroma;
  95.     switch( i_chroma )
  96.     {
  97.     case VLC_FOURCC('R','V','1','5'):
  98.         p_sys->fmt.video.i_rmask = 0x7c00;
  99.         p_sys->fmt.video.i_gmask = 0x03e0;
  100.         p_sys->fmt.video.i_bmask = 0x001f;
  101.         break;
  102.     case VLC_FOURCC('R','V','2','4'):
  103.         p_sys->fmt.video.i_rmask = 0x00ff0000;
  104.         p_sys->fmt.video.i_gmask = 0x0000ff00;
  105.         p_sys->fmt.video.i_bmask = 0x000000ff;
  106.         break;
  107.     case VLC_FOURCC('R','V','3','2'):
  108.         p_sys->fmt.video.i_rmask = 0x00ff0000;
  109.         p_sys->fmt.video.i_gmask = 0x0000ff00;
  110.         p_sys->fmt.video.i_bmask = 0x000000ff;
  111.         break;
  112.     default:
  113.         msg_Warn( p_demux, "Unknown RGB masks" );
  114.         break;
  115.     }
  116.     return VLC_SUCCESS;
  117. }
  118. int screen_CloseCapture( demux_t *p_demux )
  119. {
  120.     demux_sys_t *p_sys = p_demux->p_sys;
  121.     screen_data_t *p_data = p_sys->p_data;
  122.     if( p_data->p_block ) block_Release( p_data->p_block );
  123.     if( p_data->hgdi_backup)
  124.         SelectObject( p_data->hdc_dst, p_data->hgdi_backup );
  125.     DeleteDC( p_data->hdc_dst );
  126.     ReleaseDC( 0, p_data->hdc_src );
  127.     free( p_data );
  128.     return VLC_SUCCESS;
  129. }
  130. struct block_sys_t
  131. {
  132.     block_t self;
  133.     HBITMAP hbmp;
  134. };
  135. static void CaptureBlockRelease( block_t *p_block )
  136. {
  137.     DeleteObject( ((block_sys_t *)p_block)->hbmp );
  138.     free( p_block );
  139. }
  140. static block_t *CaptureBlockNew( demux_t *p_demux )
  141. {
  142.     demux_sys_t *p_sys = p_demux->p_sys;
  143.     screen_data_t *p_data = p_sys->p_data;
  144.     block_sys_t *p_block;
  145.     void *p_buffer;
  146.     int i_buffer;
  147.     HBITMAP hbmp;
  148.     if( p_data->bmi.bmiHeader.biSize == 0 )
  149.     {
  150.         int i_val;
  151.         /* Create the bitmap info header */
  152.         p_data->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  153.         p_data->bmi.bmiHeader.biWidth = p_sys->fmt.video.i_width;
  154.         p_data->bmi.bmiHeader.biHeight = - p_sys->fmt.video.i_height;
  155.         p_data->bmi.bmiHeader.biPlanes = 1;
  156.         p_data->bmi.bmiHeader.biBitCount = p_sys->fmt.video.i_bits_per_pixel;
  157.         p_data->bmi.bmiHeader.biCompression = BI_RGB;
  158.         p_data->bmi.bmiHeader.biSizeImage = 0;
  159.         p_data->bmi.bmiHeader.biXPelsPerMeter =
  160.             p_data->bmi.bmiHeader.biYPelsPerMeter = 0;
  161.         p_data->bmi.bmiHeader.biClrUsed = 0;
  162.         p_data->bmi.bmiHeader.biClrImportant = 0;
  163.         i_val = var_CreateGetInteger( p_demux, "screen-fragment-size" );
  164.         p_data->i_fragment_size = i_val > 0 ? i_val : p_sys->fmt.video.i_height;
  165.         p_data->i_fragment_size = i_val > p_sys->fmt.video.i_height ?
  166.                                             p_sys->fmt.video.i_height :
  167.                                             p_data->i_fragment_size;
  168.         p_sys->f_fps *= (p_sys->fmt.video.i_height/p_data->i_fragment_size);
  169.         p_sys->i_incr = 1000000 / p_sys->f_fps;
  170.         p_data->i_fragment = 0;
  171.         p_data->p_block = 0;
  172.     }
  173.     /* Create the bitmap storage space */
  174.     hbmp = CreateDIBSection( p_data->hdc_dst, &p_data->bmi, DIB_RGB_COLORS,
  175.                              &p_buffer, NULL, 0 );
  176.     if( !hbmp || !p_buffer )
  177.     {
  178.         msg_Err( p_demux, "cannot create bitmap" );
  179.         if( hbmp ) DeleteObject( hbmp );
  180.         return NULL;
  181.     }
  182.     /* Select the bitmap into the compatible DC */
  183.     if( !p_data->hgdi_backup )
  184.         p_data->hgdi_backup = SelectObject( p_data->hdc_dst, hbmp );
  185.     else
  186.         SelectObject( p_data->hdc_dst, hbmp );
  187.     if( !p_data->hgdi_backup )
  188.     {
  189.         msg_Err( p_demux, "cannot select bitmap" );
  190.         DeleteObject( hbmp );
  191.         return NULL;
  192.     }
  193.     /* Build block */
  194.     if( !(p_block = malloc( sizeof( block_t ) + sizeof( block_sys_t ) )) )
  195.     {
  196.         DeleteObject( hbmp );
  197.         return NULL;
  198.     }
  199.     /* Fill all fields */
  200.     i_buffer = (p_sys->fmt.video.i_bits_per_pixel + 7) / 8 *
  201.         p_sys->fmt.video.i_width * p_sys->fmt.video.i_height;
  202.     block_Init( &p_block->self, p_buffer, i_buffer );
  203.     p_block->self.pf_release = CaptureBlockRelease;
  204.     p_block->hbmp            = hbmp;
  205.     return &p_block->self;
  206. }
  207. block_t *screen_Capture( demux_t *p_demux )
  208. {
  209.     demux_sys_t *p_sys = p_demux->p_sys;
  210.     screen_data_t *p_data = p_sys->p_data;
  211.     if( !p_data->i_fragment )
  212.     {
  213.         if( !( p_data->p_block = CaptureBlockNew( p_demux ) ) )
  214.         {
  215.             msg_Warn( p_demux, "cannot get block" );
  216.             return NULL;
  217.         }
  218.     }
  219.     if( p_sys->b_follow_mouse )
  220.     {
  221.         POINT pos;
  222.         GetCursorPos( &pos );
  223.         FollowMouse( p_sys, pos.x, pos.y );
  224.     }
  225.     if( !BitBlt( p_data->hdc_dst, 0,
  226.                  p_data->i_fragment * p_data->i_fragment_size,
  227.                  p_sys->fmt.video.i_width, p_data->i_fragment_size,
  228.                  p_data->hdc_src, p_sys->i_left, p_sys->i_top +
  229.                  p_data->i_fragment * p_data->i_fragment_size,
  230.                  SRCCOPY | CAPTUREBLT ) )
  231.     {
  232.         msg_Err( p_demux, "error during BitBlt()" );
  233.         return NULL;
  234.     }
  235.     p_data->i_fragment++;
  236.     if( !( p_data->i_fragment %
  237.            (p_sys->fmt.video.i_height/p_data->i_fragment_size) ) )
  238.     {
  239.         block_t *p_block = p_data->p_block;
  240.         p_data->i_fragment = 0;
  241.         p_data->p_block = 0;
  242.         if( p_sys->p_mouse )
  243.         {
  244.             POINT pos;
  245.             GetCursorPos( &pos );
  246.             RenderCursor( p_demux, pos.x, pos.y,
  247.                           p_block->p_buffer );
  248.         }
  249.         return p_block;
  250.     }
  251.     return NULL;
  252. }