📄 voutqt.m
字号:
/***************************************************************************** * vout.m: MacOS X video output module ***************************************************************************** * Copyright (C) 2001-2004 VideoLAN * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $ * * Authors: Colin Delacroix <colin@zoy.org> * Florian G. Pflug <fgp@phlo.org> * Jon Lech Johansen <jon-vl@nanocrew.net> * Derk-Jan Hartman <hartman at videolan dot org> * 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 <vlc_keys.h>#include "intf.h"#include "vout.h"#define QT_MAX_DIRECTBUFFERS 10#define VL_MAX_DISPLAYS 16/***************************************************************************** * VLCView interface *****************************************************************************/@interface VLCQTView : NSQuickDrawView{ vout_thread_t * p_vout;}- (id) initWithVout:(vout_thread_t *)p_vout;@endstruct vout_sys_t{ NSAutoreleasePool *o_pool; VLCWindow * o_window; VLCQTView * o_qtview; vlc_bool_t b_saved_frame; vlc_bool_t b_altivec; NSRect s_frame; CodecType i_codec; CGrafPtr p_qdport; ImageSequence i_seq; MatrixRecordPtr p_matrix; DecompressorComponent img_dc; ImageDescriptionHandle h_img_descr; /* Mozilla plugin-related variables */ vlc_bool_t b_embedded; Rect clipping_rect; int portx, porty;};struct picture_sys_t{ void *p_data; unsigned int i_size; /* When using I420 output */ PlanarPixmapInfoYUV420 pixmap_i420;};/***************************************************************************** * Local prototypes *****************************************************************************/static int InitVideo ( vout_thread_t * );static void EndVideo ( vout_thread_t * );static int ManageVideo ( vout_thread_t * );static void DisplayVideo ( vout_thread_t *, picture_t * );static int ControlVideo ( vout_thread_t *, int, va_list );static int CoToggleFullscreen( vout_thread_t *p_vout );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_(OpenVideoQT) ( vlc_object_t *p_this ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; OSErr err; vlc_value_t value_drawable; 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 ) ); p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init]; p_vout->pf_init = InitVideo; p_vout->pf_end = EndVideo; p_vout->pf_manage = ManageVideo; p_vout->pf_render = NULL; p_vout->pf_display = DisplayVideo; p_vout->pf_control = ControlVideo; /* Are we embedded? If so, the drawable value will be a pointer to a * CGrafPtr that we're expected to use */ var_Get( p_vout->p_vlc, "drawable", &value_drawable ); if( value_drawable.i_int != 0 ) p_vout->p_sys->b_embedded = VLC_TRUE; else p_vout->p_sys->b_embedded = VLC_FALSE; p_vout->p_sys->b_altivec = p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC; msg_Dbg( p_vout, "We do%s have Altivec", p_vout->p_sys->b_altivec ? "" : "n't" ); /* Initialize QuickTime */ p_vout->p_sys->h_img_descr = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) ); p_vout->p_sys->p_matrix = (MatrixRecordPtr)malloc( sizeof(MatrixRecord) ); 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 VLC_EGENERIC; } /* Damn QT isn't thread safe. so keep a lock in the p_vlc object */ vlc_mutex_lock( &p_vout->p_vlc->quicktime_lock ); /* Can we find the right chroma ? */ if( p_vout->p_sys->b_altivec ) { err = FindCodec( kYUVSPixelFormat, bestSpeedCodec, nil, &p_vout->p_sys->img_dc ); } else { 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 ) { if( p_vout->p_sys->b_altivec ) { p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2'); p_vout->p_sys->i_codec = kYUVSPixelFormat; } else { 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; }#define o_qtview p_vout->p_sys->o_qtview o_qtview = [[VLCQTView alloc] initWithVout: p_vout]; [o_qtview autorelease]; if( p_vout->p_sys->b_embedded ) { /* Zero the clipping rectangle */ p_vout->p_sys->clipping_rect.left = 0; p_vout->p_sys->clipping_rect.right = 0; p_vout->p_sys->clipping_rect.top = 0; p_vout->p_sys->clipping_rect.bottom = 0; } else { /* Spawn window */ p_vout->p_sys->o_window = [[VLCWindow alloc] initWithVout: p_vout view: o_qtview frame: nil]; if( !p_vout->p_sys->o_window ) { return VLC_EGENERIC; } } /* Retrieve the QuickDraw port */ if( p_vout->p_sys->b_embedded ) { /* Don't need (nor want) to lock the focus, since otherwise we crash * (presumably because we don't own the window, but I'm not sure * if this is the exact reason) -andrep */ p_vout->p_sys->p_qdport = [o_qtview qdPort]; } else { [o_qtview lockFocus]; p_vout->p_sys->p_qdport = [o_qtview qdPort]; [o_qtview unlockFocus]; }#undef o_qtview return VLC_SUCCESS;}/***************************************************************************** * CloseVideo: destroy video thread output method *****************************************************************************/void E_(CloseVideoQT) ( vlc_object_t *p_this ){ NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; vout_thread_t * p_vout = (vout_thread_t *)p_this; if( !p_vout->p_sys->b_embedded ) [p_vout->p_sys->o_window close]; /* Clean Up Quicktime environment */ ExitMovies(); free( p_vout->p_sys->p_matrix ); DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ); [o_pool release]; free( p_vout->p_sys );}/***************************************************************************** * InitVideo: initialize video thread output method *****************************************************************************/static int InitVideo ( vout_thread_t *p_vout ){ picture_t *p_pic; int i_index; 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 we are embedded (e.g. running as a Mozilla plugin), use the pointer * stored in the "drawable" value as the CGrafPtr for the QuickDraw * graphics port */ if( p_vout->p_sys->b_embedded ) { vlc_value_t val; var_Get( p_vout->p_vlc, "drawable", &val ); p_vout->p_sys->p_qdport = (CGrafPtr) val.i_int; } SetPort( p_vout->p_sys->p_qdport ); QTScaleMatrix( p_vout ); if( QTCreateSequence( p_vout ) ) { msg_Err( p_vout, "unable to create sequence" ); return( 1 ); } /* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */ while( I_OUTPUTPICTURES < 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 || QTNewPicture( p_vout, p_pic ) ) { break; } p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; I_OUTPUTPICTURES++; } return 0;}/***************************************************************************** * EndVideo: terminate video thread output method *****************************************************************************/static void EndVideo( vout_thread_t *p_vout ){ int i_index; QTDestroySequence( p_vout ); /* Free the direct buffers we allocated */ for( i_index = I_OUTPUTPICTURES; i_index; ) { i_index--; QTFreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] ); }}/***************************************************************************** * ManageVideo: 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 ManageVideo( vout_thread_t *p_vout ){ vlc_value_t val; var_Get( p_vout->p_vlc, "drawableredraw", &val ); if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) { if( CoToggleFullscreen( p_vout ) ) { return( 1 ); } p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; } if( p_vout->p_sys->b_embedded && val.i_int == 1 ) { /* If we're embedded, the application is expected to indicate a * window change (move/resize/etc) via the "drawableredraw" value. * If that's the case, set the VOUT_SIZE_CHANGE flag so we do * actually handle the window change. */ val.i_int = 0; var_Set( p_vout->p_vlc, "drawableredraw", val ); p_vout->i_changes |= VOUT_SIZE_CHANGE; } if( p_vout->i_changes & VOUT_SIZE_CHANGE ) { QTScaleMatrix( p_vout ); SetDSequenceMatrix( p_vout->p_sys->i_seq, p_vout->p_sys->p_matrix ); p_vout->i_changes &= ~VOUT_SIZE_CHANGE; } [p_vout->p_sys->o_window manage]; return( 0 );}/***************************************************************************** * vout_Display: displays previously rendered output ***************************************************************************** * This function sends the currently rendered image to the display. *****************************************************************************/static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ){ OSErr err; CodecFlags flags; Rect saved_rect; RgnHandle saved_clip; saved_clip = NewRgn(); if( p_vout->p_sys->b_embedded ) { /* In the Mozilla plugin, the browser also draws things in the windows. * So, we have to update the origin and clipping rectangle for each * picture. FIXME: The vout should probably lock something ... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -