vout.m
来自「VLC媒体播放程序」· M 代码 · 共 1,859 行 · 第 1/4 页
M
1,859 行
/***************************************************************************** * vout.m: MacOS X video output module ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN * $Id: vout.m,v 1.85 2004/02/28 13:53:35 titer Exp $ * * Authors: Colin Delacroix <colin@zoy.org> * Florian G. Pflug <fgp@phlo.org> * Jon Lech Johansen <jon-vl@nanocrew.net> * Derk-Jan Hartman <thedj@users.sourceforge.net> * Eric Petit <titer@m0k.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <errno.h> /* ENOMEM */#include <stdlib.h> /* free() */#include <string.h> /* strerror() */#include <QuickTime/QuickTime.h>#include <OpenGL/OpenGL.h>#include <OpenGL/gl.h>#include <OpenGL/glext.h>#include <vlc_keys.h>#include "intf.h"#include "vout.h"#define QT_MAX_DIRECTBUFFERS 10#define VL_MAX_DISPLAYS 16#define OPENGL_EFFECT_NONE 1#define OPENGL_EFFECT_CUBE 2#define OPENGL_EFFECT_TRANSPARENT_CUBE 4struct picture_sys_t{ void *p_info; unsigned int i_size; /* When using I420 output */ PlanarPixmapInfoYUV420 pixmap_i420;};/***************************************************************************** * Local prototypes *****************************************************************************/static int vout_Init ( vout_thread_t * );static void vout_End ( vout_thread_t * );static int vout_Manage ( vout_thread_t * );static void vout_Display ( vout_thread_t *, picture_t * );static int CoSendRequest ( vout_thread_t *, SEL );static int CoCreateWindow ( vout_thread_t * );static int CoDestroyWindow ( vout_thread_t * );static int CoToggleFullscreen ( vout_thread_t * );static void VLCHideMouse ( vout_thread_t *, BOOL );static void QTScaleMatrix ( vout_thread_t * );static int QTCreateSequence ( vout_thread_t * );static void QTDestroySequence ( vout_thread_t * );static int QTNewPicture ( vout_thread_t *, picture_t * );static void QTFreePicture ( vout_thread_t *, picture_t * );/***************************************************************************** * OpenVideo: allocates MacOS X video thread output method ***************************************************************************** * This function allocates and initializes a MacOS X vout method. *****************************************************************************/int E_(OpenVideo) ( vlc_object_t *p_this ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; OSErr err; int i_timeout; p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); if( p_vout->p_sys == NULL ) { msg_Err( p_vout, "out of memory" ); return( 1 ); } memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) ); /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */ for( i_timeout = 20 ; i_timeout-- ; ) { if( NSApp == NULL ) { msleep( INTF_IDLE_SLEEP ); } } if( NSApp == NULL ) { /* no MacOS X intf, unable to communicate with MT */ msg_Err( p_vout, "no MacOS X interface present" ); free( p_vout->p_sys ); return( 1 ); } if( [NSApp respondsToSelector: @selector(getIntf)] ) { intf_thread_t * p_intf; for( i_timeout = 10 ; i_timeout-- ; ) { if( ( p_intf = [NSApp getIntf] ) == NULL ) { msleep( INTF_IDLE_SLEEP ); } } if( p_intf == NULL ) { msg_Err( p_vout, "MacOS X intf has getIntf, but is NULL" ); free( p_vout->p_sys ); return( 1 ); } } p_vout->p_sys->b_mouse_moved = VLC_TRUE; p_vout->p_sys->i_time_mouse_last_moved = mdate(); /* set window size */ p_vout->p_sys->s_rect.size.width = p_vout->i_window_width; p_vout->p_sys->s_rect.size.height = p_vout->i_window_height; /* Check if we should use QuickTime or OpenGL */ p_vout->p_sys->i_opengl = config_GetInt( p_vout, "macosx-opengl" ); if( !p_vout->p_sys->i_opengl ) { /* Initialize QuickTime */ p_vout->p_sys->h_img_descr = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) ); p_vout->p_sys->p_matrix = (MatrixRecordPtr)malloc( sizeof(MatrixRecord) ); p_vout->p_sys->p_fullscreen_state = NULL; if( ( err = EnterMovies() ) != noErr ) { msg_Err( p_vout, "EnterMovies failed: %d", err ); free( p_vout->p_sys->p_matrix ); DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ); free( p_vout->p_sys ); return( 1 ); } /* Damn QT isn't thread safe. so keep a lock in the p_vlc object */ vlc_mutex_lock( &p_vout->p_vlc->quicktime_lock ); err = FindCodec( kYUV420CodecType, bestSpeedCodec, nil, &p_vout->p_sys->img_dc ); vlc_mutex_unlock( &p_vout->p_vlc->quicktime_lock ); if( err == noErr && p_vout->p_sys->img_dc != 0 ) { p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0'); p_vout->p_sys->i_codec = kYUV420CodecType; } else { msg_Err( p_vout, "failed to find an appropriate codec" ); } if( p_vout->p_sys->img_dc == 0 ) { free( p_vout->p_sys->p_matrix ); DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ); free( p_vout->p_sys ); return VLC_EGENERIC; } } NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; NSArray * o_screens = [NSScreen screens]; if( [o_screens count] > 0 && var_Type( p_vout, "video-device" ) == 0 ) { int i = 1; vlc_value_t val, text; NSScreen * o_screen; int i_option = config_GetInt( p_vout, "macosx-vdev" ); var_Create( p_vout, "video-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = _("Video device"); var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL ); NSEnumerator * o_enumerator = [o_screens objectEnumerator]; while( (o_screen = [o_enumerator nextObject]) != NULL ) { char psz_temp[255]; NSRect s_rect = [o_screen frame]; snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1, "%s %d (%dx%d)", _("Screen"), i, (int)s_rect.size.width, (int)s_rect.size.height ); text.psz_string = psz_temp; val.i_int = i; var_Change( p_vout, "video-device", VLC_VAR_ADDCHOICE, &val, &text ); if( ( i - 1 ) == i_option ) { var_Set( p_vout, "video-device", val ); } i++; } var_AddCallback( p_vout, "video-device", vout_VarCallback, NULL ); val.b_bool = VLC_TRUE; var_Set( p_vout, "intf-change", val ); } [o_pool release]; if( CoCreateWindow( p_vout ) ) { msg_Err( p_vout, "unable to create window" ); if( !p_vout->p_sys->i_opengl ) { free( p_vout->p_sys->p_matrix ); DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ); } free( p_vout->p_sys ); return( 1 ); } p_vout->pf_init = vout_Init; p_vout->pf_end = vout_End; p_vout->pf_manage = vout_Manage; p_vout->pf_render = NULL; p_vout->pf_display = vout_Display; return( 0 );}/***************************************************************************** * vout_Init: initialize video thread output method *****************************************************************************/static int vout_Init( vout_thread_t *p_vout ){ int i_index; picture_t *p_pic; I_OUTPUTPICTURES = 0; /* Initialize the output structure; we already found a codec, * and the corresponding chroma we will be using. Since we can * arbitrary scale, stick to the coordinates and aspect. */ p_vout->output.i_width = p_vout->render.i_width; p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; if( !p_vout->p_sys->i_opengl ) { SetPort( p_vout->p_sys->p_qdport ); QTScaleMatrix( p_vout ); if( QTCreateSequence( p_vout ) ) { msg_Err( p_vout, "unable to create sequence" ); return( 1 ); } } else { p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2'); p_vout->output.i_rmask = 0xFF0000; p_vout->output.i_gmask = 0x00FF00; p_vout->output.i_bmask = 0x0000FF; } /* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */ while( I_OUTPUTPICTURES < p_vout->p_sys->i_opengl ? 1 : QT_MAX_DIRECTBUFFERS ) { p_pic = NULL; /* Find an empty picture slot */ for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ ) { if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) { p_pic = p_vout->p_picture + i_index; break; } } /* Allocate the picture */ if( p_pic == NULL ) { break; } if( !p_vout->p_sys->i_opengl ) { if( QTNewPicture( p_vout, p_pic ) ) { break; } } else { /* Nothing special to do, we just need a basic allocated picture_t */ vout_AllocatePicture( VLC_OBJECT( p_vout ), p_pic, p_vout->output.i_chroma, p_vout->output.i_width, p_vout->output.i_height, p_vout->output.i_aspect ); } p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; I_OUTPUTPICTURES++; } if( p_vout->p_sys->i_opengl ) { [p_vout->p_sys->o_glview lockFocus]; [p_vout->p_sys->o_glview initTextures]; [p_vout->p_sys->o_glview reshape]; [p_vout->p_sys->o_glview unlockFocus]; } return( 0 );}/***************************************************************************** * vout_End: terminate video thread output method *****************************************************************************/static void vout_End( vout_thread_t *p_vout ){ int i_index; if( !p_vout->p_sys->i_opengl ) { QTDestroySequence( p_vout ); } else { [p_vout->p_sys->o_glview cleanUp]; } /* Free the direct buffers we allocated */ for( i_index = I_OUTPUTPICTURES; i_index; ) { i_index--; if( !p_vout->p_sys->i_opengl ) { QTFreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] ); } else { free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); } }}/***************************************************************************** * CloseVideo: destroy video thread output method *****************************************************************************/void E_(CloseVideo) ( vlc_object_t *p_this ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; if( CoDestroyWindow( p_vout ) ) { msg_Err( p_vout, "unable to destroy window" ); } if( !p_vout->p_sys->i_opengl ) { if ( p_vout->p_sys->p_fullscreen_state != NULL ) EndFullScreen ( p_vout->p_sys->p_fullscreen_state, NULL ); ExitMovies(); free( p_vout->p_sys->p_matrix ); DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ); } free( p_vout->p_sys );}/***************************************************************************** * vout_Manage: handle events ***************************************************************************** * This function should be called regularly by video output thread. It manages * console events. It returns a non null value on error. *****************************************************************************/static int vout_Manage( vout_thread_t *p_vout ){ if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) { if( CoToggleFullscreen( p_vout ) ) { return( 1 ); } p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; } if( p_vout->i_changes & VOUT_SIZE_CHANGE ) { if( !p_vout->p_sys->i_opengl ) { QTScaleMatrix( p_vout ); SetDSequenceMatrix( p_vout->p_sys->i_seq, p_vout->p_sys->p_matrix ); } p_vout->i_changes &= ~VOUT_SIZE_CHANGE; } /* hide/show mouse cursor * this code looks unnecessarily complicated, but is necessary like this. * it has to deal with multiple monitors and therefore checks a lot */ if( !p_vout->p_sys->b_mouse_moved && p_vout->b_fullscreen ) { if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 3000000 ) { VLCHideMouse( p_vout, YES ); } } else if ( p_vout->p_sys->b_mouse_moved && p_vout->b_fullscreen ) { VLCHideMouse( p_vout, NO ); } /* disable screen saver */ UpdateSystemActivity( UsrActivity ); return( 0 );}/***************************************************************************** * vout_Display: displays previously rendered output *****************************************************************************
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?