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 + -
显示快捷键?