vout.m

来自「VLC媒体播放程序」· M 代码 · 共 1,859 行 · 第 1/4 页

M
1,859
字号
 * This function sends the currently rendered image to the display. *****************************************************************************/static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ){    if( !p_vout->p_sys->i_opengl )    {        OSErr err;        CodecFlags flags;        if( ( err = DecompressSequenceFrameS(                         p_vout->p_sys->i_seq,                        p_pic->p_sys->p_info,                        p_pic->p_sys->i_size,                                            codecFlagUseImageBuffer, &flags, nil ) != noErr ) )        {            msg_Warn( p_vout, "DecompressSequenceFrameS failed: %d", err );        }        else        {            QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );        }    }    else    {        if( [p_vout->p_sys->o_glview lockFocusIfCanDraw] )        {            /* Texture gotta be reload before the buffer is filled               (thanks to gcc from arstechnica forums) */            [p_vout->p_sys->o_glview drawRect:                [p_vout->p_sys->o_glview bounds]];            [p_vout->p_sys->o_glview reloadTexture];            [p_vout->p_sys->o_glview unlockFocus];        }    }}/***************************************************************************** * CoSendRequest: send request to interface thread ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int CoSendRequest( vout_thread_t *p_vout, SEL sel ){    int i_ret = 0;    vlc_value_t val;    intf_thread_t * p_intf;    VLCVout * o_vlv = [[VLCVout alloc] init];    if( ( i_ret = ExecuteOnMainThread( o_vlv, sel, (void *)p_vout ) ) )    {        msg_Err( p_vout, "SendRequest: no way to communicate with mt" );    }    [o_vlv release];    /*This makes this function dependant of the presence of a macosx     interface. We do not check if this interface exists, since it has     already been done before.*/    p_intf = [NSApp getIntf];    val.b_bool = VLC_TRUE;    var_Create(p_intf,"intf-change",VLC_VAR_BOOL);    var_Set(p_intf, "intf-change",val);    return( i_ret );}/***************************************************************************** * CoCreateWindow: create new window  ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int CoCreateWindow( vout_thread_t *p_vout ){    if( CoSendRequest( p_vout, @selector(createWindow:) ) )    {        msg_Err( p_vout, "CoSendRequest (createWindow) failed" );        return( 1 );    }        return( 0 );}/***************************************************************************** * CoDestroyWindow: destroy window  ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int CoDestroyWindow( vout_thread_t *p_vout ){    VLCHideMouse( p_vout, NO );    if( CoSendRequest( p_vout, @selector(destroyWindow:) ) )    {        msg_Err( p_vout, "CoSendRequest (destroyWindow) failed" );        return( 1 );    }    return( 0 );}/***************************************************************************** * CoToggleFullscreen: toggle fullscreen  ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int CoToggleFullscreen( vout_thread_t *p_vout ){    if( p_vout->p_sys->i_opengl )    {        p_vout->b_fullscreen = !p_vout->b_fullscreen;        if( p_vout->b_fullscreen )        {            [p_vout->p_sys->o_glview goFullScreen];        }        else        {            [p_vout->p_sys->o_glview exitFullScreen];        }        return 0;    }        QTDestroySequence( p_vout );    if( CoDestroyWindow( p_vout ) )    {        msg_Err( p_vout, "unable to destroy window" );        return( 1 );    }        p_vout->b_fullscreen = !p_vout->b_fullscreen;    if( CoCreateWindow( p_vout ) )    {        msg_Err( p_vout, "unable to create window" );        return( 1 );    }    SetPort( p_vout->p_sys->p_qdport );    QTScaleMatrix( p_vout );    if( QTCreateSequence( p_vout ) )    {        msg_Err( p_vout, "unable to create sequence" );        return( 1 );     }     return( 0 );}/***************************************************************************** * VLCHideMouse: if b_hide then hide the cursor *****************************************************************************/static void VLCHideMouse ( vout_thread_t *p_vout, BOOL b_hide ){    BOOL b_inside;    NSRect s_rect;    NSPoint ml;    NSWindow *o_window = p_vout->p_sys->o_window;    NSView *o_contents = [o_window contentView];        s_rect = [o_contents bounds];    ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];    ml = [o_contents convertPoint:ml fromView:nil];    b_inside = [o_contents mouse: ml inRect: s_rect];        if ( b_hide && b_inside )    {        /* only hide if mouse over VLCQTView */        [NSCursor setHiddenUntilMouseMoves: YES];    }    else if ( !b_hide )    {        [NSCursor setHiddenUntilMouseMoves: NO];    }    p_vout->p_sys->b_mouse_moved = NO;    p_vout->p_sys->i_time_mouse_last_moved = mdate();    return;}/***************************************************************************** * QTScaleMatrix: scale matrix  *****************************************************************************/static void QTScaleMatrix( vout_thread_t *p_vout ){    Rect s_rect;    unsigned int i_width, i_height;    Fixed factor_x, factor_y;    unsigned int i_offset_x = 0;    unsigned int i_offset_y = 0;    GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );    i_width = s_rect.right - s_rect.left;    i_height = s_rect.bottom - s_rect.top;    if( config_GetInt( p_vout, "macosx-stretch" ) )    {        factor_x = FixDiv( Long2Fix( i_width ),                           Long2Fix( p_vout->output.i_width ) );        factor_y = FixDiv( Long2Fix( i_height ),                           Long2Fix( p_vout->output.i_height ) );                               }    else if( i_height * p_vout->output.i_aspect < i_width * VOUT_ASPECT_FACTOR )    {        int i_adj_width = i_height * p_vout->output.i_aspect /                          VOUT_ASPECT_FACTOR;        factor_x = FixDiv( Long2Fix( i_adj_width ),                           Long2Fix( p_vout->output.i_width ) );        factor_y = FixDiv( Long2Fix( i_height ),                           Long2Fix( p_vout->output.i_height ) );        i_offset_x = (i_width - i_adj_width) / 2;    }    else    {        int i_adj_height = i_width * VOUT_ASPECT_FACTOR /                           p_vout->output.i_aspect;        factor_x = FixDiv( Long2Fix( i_width ),                           Long2Fix( p_vout->output.i_width ) );        factor_y = FixDiv( Long2Fix( i_adj_height ),                           Long2Fix( p_vout->output.i_height ) );        i_offset_y = (i_height - i_adj_height) / 2;    }        SetIdentityMatrix( p_vout->p_sys->p_matrix );    ScaleMatrix( p_vout->p_sys->p_matrix,                 factor_x, factor_y,                 Long2Fix(0), Long2Fix(0) );                     TranslateMatrix( p_vout->p_sys->p_matrix,                 Long2Fix(i_offset_x), Long2Fix(i_offset_y) );}/***************************************************************************** * QTCreateSequence: create a new sequence  ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int QTCreateSequence( vout_thread_t *p_vout ){    OSErr err;    ImageDescriptionPtr p_descr;    HLock( (Handle)p_vout->p_sys->h_img_descr );    p_descr = *p_vout->p_sys->h_img_descr;    p_descr->idSize = sizeof(ImageDescription);    p_descr->cType = p_vout->p_sys->i_codec;    p_descr->version = 1;    p_descr->revisionLevel = 0;    p_descr->vendor = 'appl';    p_descr->width = p_vout->output.i_width;    p_descr->height = p_vout->output.i_height;    p_descr->hRes = Long2Fix(72);    p_descr->vRes = Long2Fix(72);    p_descr->spatialQuality = codecLosslessQuality;    p_descr->frameCount = 1;    p_descr->clutID = -1;    p_descr->dataSize = 0;    p_descr->depth = 24;    HUnlock( (Handle)p_vout->p_sys->h_img_descr );    if( ( err = DecompressSequenceBeginS(                               &p_vout->p_sys->i_seq,                              p_vout->p_sys->h_img_descr,                              NULL, 0,                              p_vout->p_sys->p_qdport,                              NULL, NULL,                              p_vout->p_sys->p_matrix,                              0, NULL,                              codecFlagUseImageBuffer,                              codecLosslessQuality,                              p_vout->p_sys->img_dc ) ) )    {        msg_Err( p_vout, "DecompressSequenceBeginS failed: %d", err );        return( 1 );    }    return( 0 );}/***************************************************************************** * QTDestroySequence: destroy sequence  *****************************************************************************/static void QTDestroySequence( vout_thread_t *p_vout ){    CDSequenceEnd( p_vout->p_sys->i_seq );}/***************************************************************************** * QTNewPicture: allocate a picture ***************************************************************************** * Returns 0 on success, 1 otherwise *****************************************************************************/static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic ){    int i_width  = p_vout->output.i_width;    int i_height = p_vout->output.i_height;    /* We know the chroma, allocate a buffer which will be used     * directly by the decoder */    p_pic->p_sys = malloc( sizeof( picture_sys_t ) );    if( p_pic->p_sys == NULL )    {        return( -1 );    }    switch( p_vout->output.i_chroma )    {        case VLC_FOURCC('I','4','2','0'):            p_pic->p_sys->p_info = (void *)&p_pic->p_sys->pixmap_i420;            p_pic->p_sys->i_size = sizeof(PlanarPixmapInfoYUV420);            /* Allocate the memory buffer */            p_pic->p_data = vlc_memalign( &p_pic->p_data_orig,                                          16, i_width * i_height * 3 / 2 );            /* Y buffer */            p_pic->Y_PIXELS = p_pic->p_data;             p_pic->p[Y_PLANE].i_lines = i_height;            p_pic->p[Y_PLANE].i_pitch = i_width;            p_pic->p[Y_PLANE].i_pixel_pitch = 1;            p_pic->p[Y_PLANE].i_visible_pitch = i_width;            /* U buffer */            p_pic->U_PIXELS = p_pic->Y_PIXELS + i_height * i_width;            p_pic->p[U_PLANE].i_lines = i_height / 2;            p_pic->p[U_PLANE].i_pitch = i_width / 2;            p_pic->p[U_PLANE].i_pixel_pitch = 1;            p_pic->p[U_PLANE].i_visible_pitch = i_width / 2;            /* V buffer */            p_pic->V_PIXELS = p_pic->U_PIXELS + i_height * i_width / 4;            p_pic->p[V_PLANE].i_lines = i_height / 2;            p_pic->p[V_PLANE].i_pitch = i_width / 2;            p_pic->p[V_PLANE].i_pixel_pitch = 1;            p_pic->p[V_PLANE].i_visible_pitch = i_width / 2;            /* We allocated 3 planes */            p_pic->i_planes = 3;#define P p_pic->p_sys->pixmap_i420            P.componentInfoY.offset = (void *)p_pic->Y_PIXELS                                       - p_pic->p_sys->p_info;            P.componentInfoCb.offset = (void *)p_pic->U_PIXELS                                        - p_pic->p_sys->p_info;            P.componentInfoCr.offset = (void *)p_pic->V_PIXELS                                        - p_pic->p_sys->p_info;            P.componentInfoY.rowBytes = i_width;            P.componentInfoCb.rowBytes = i_width / 2;            P.componentInfoCr.rowBytes = i_width / 2;#undef P            break;    default:        /* Unknown chroma, tell the guy to get lost */        free( p_pic->p_sys );        msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",                 p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );        p_pic->i_planes = 0;        return( -1 );    }    return( 0 );}/***************************************************************************** * QTFreePicture: destroy a picture allocated with QTNewPicture *****************************************************************************/static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ){    switch( p_vout->output.i_chroma )    {        case VLC_FOURCC('I','4','2','0'):            free( p_pic->p_data_orig );            break;    }    free( p_pic->p_sys );}/***************************************************************************** * VLCWindow implementation *****************************************************************************/@implementation VLCWindow- (void)setVout:(vout_thread_t *)_p_vout{    p_vout = _p_vout;}- (vout_thread_t *)getVout{    return( p_vout );}- (void)scaleWindowWithFactor: (float)factor{    NSSize newsize;    int i_corrected_height, i_corrected_width;    NSPoint topleftbase;    NSPoint topleftscreen;        if ( !p_vout->b_fullscreen )    {        topleftbase.x = 0;        topleftbase.y = [self frame].size.height;        topleftscreen = [self convertBaseToScreen: topleftbase];                if( p_vout->output.i_height * p_vout->output.i_aspect >                         p_vout->output.i_width * VOUT_ASPECT_FACTOR )        {            i_corrected_width = p_vout->output.i_height * p_vout->output.i_aspect /                                            VOUT_ASPECT_FACTOR;            newsize.width = (int) ( i_corrected_width * factor );            newsize.height = (int) ( p_vout->render.i_height * factor );        }        else        {            i_corrected_height = p_vout->output.i_width * VOUT_ASPECT_FACTOR /                                            p_vout->output.i_aspect;            newsize.width = (int) ( p_vout->render.i_width * factor );            newsize.height = (int) ( i_corrected_height * factor );        }            [self setContentSize: newsize];                [self setFrameTopLeftPoint: topleftscreen];        p_vout->i_changes |= VOUT_SIZE_CHANGE;    }}- (void)toggleFloatOnTop{    if( config_GetInt( p_vout, "video-on-top" ) )    {        config_PutInt( p_vout, "video-on-top", 0 );        [p_vout->p_sys->o_window setLevel: NSNormalWindowLevel];    }    else    {        config_PutInt( p_vout, "video-on-top", 1 );        [p_vout->p_sys->o_window setLevel: NSStatusWindowLevel];    }}- (void)toggleFullscreen{    config_PutInt(p_vout, "fullscreen", !p_vout->b_fullscreen);    p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?