voutqt.m
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:25k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * vout.m: MacOS X video output module
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2003 VideoLAN
  5.  * $Id: vout.m 8351 2004-08-02 13:06:38Z hartman $
  6.  *
  7.  * Authors: Colin Delacroix <colin@zoy.org>
  8.  *          Florian G. Pflug <fgp@phlo.org>
  9.  *          Jon Lech Johansen <jon-vl@nanocrew.net>
  10.  *          Derk-Jan Hartman <hartman at videolan dot org>
  11.  *          Eric Petit <titer@m0k.org>
  12.  *
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2 of the License, or
  16.  * (at your option) any later version.
  17.  * 
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; if not, write to the Free Software
  25.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  26.  *****************************************************************************/
  27. /*****************************************************************************
  28.  * Preamble
  29.  *****************************************************************************/
  30. #include <errno.h>                                                 /* ENOMEM */
  31. #include <stdlib.h>                                                /* free() */
  32. #include <string.h>                                            /* strerror() */
  33. #include <QuickTime/QuickTime.h>
  34. #include <vlc_keys.h>
  35. #include "intf.h"
  36. #include "vout.h"
  37. #define QT_MAX_DIRECTBUFFERS 10
  38. #define VL_MAX_DISPLAYS 16
  39. /*****************************************************************************
  40.  * VLCView interface
  41.  *****************************************************************************/
  42. @interface VLCQTView : NSQuickDrawView
  43. {
  44.     vout_thread_t * p_vout;
  45. }
  46. - (id) initWithVout:(vout_thread_t *)p_vout;
  47. @end
  48. struct vout_sys_t
  49. {
  50.     NSAutoreleasePool *o_pool;
  51.     VLCWindow * o_window;
  52.     VLCQTView * o_qtview;
  53.     vlc_bool_t  b_saved_frame;
  54.     vlc_bool_t  b_altivec;
  55.     NSRect      s_frame;
  56.     CodecType i_codec;
  57.     CGrafPtr p_qdport;
  58.     ImageSequence i_seq;
  59.     MatrixRecordPtr p_matrix;
  60.     DecompressorComponent img_dc;
  61.     ImageDescriptionHandle h_img_descr;
  62. };
  63. struct picture_sys_t
  64. {
  65.     void *p_data;
  66.     unsigned int i_size;
  67.     
  68.     /* When using I420 output */
  69.     PlanarPixmapInfoYUV420 pixmap_i420;
  70. };
  71. /*****************************************************************************
  72.  * Local prototypes
  73.  *****************************************************************************/
  74. static int  InitVideo           ( vout_thread_t * );
  75. static void EndVideo            ( vout_thread_t * );
  76. static int  ManageVideo         ( vout_thread_t * );
  77. static void DisplayVideo        ( vout_thread_t *, picture_t * );
  78. static int  ControlVideo        ( vout_thread_t *, int, va_list );
  79. static int CoToggleFullscreen( vout_thread_t *p_vout );
  80. static void QTScaleMatrix       ( vout_thread_t * );
  81. static int  QTCreateSequence    ( vout_thread_t * );
  82. static void QTDestroySequence   ( vout_thread_t * );
  83. static int  QTNewPicture        ( vout_thread_t *, picture_t * );
  84. static void QTFreePicture       ( vout_thread_t *, picture_t * );
  85. /*****************************************************************************
  86.  * OpenVideo: allocates MacOS X video thread output method
  87.  *****************************************************************************
  88.  * This function allocates and initializes a MacOS X vout method.
  89.  *****************************************************************************/
  90. int E_(OpenVideoQT) ( vlc_object_t *p_this )
  91. {   
  92.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  93.     vlc_value_t val;
  94.     OSErr err;
  95.     int i_timeout;
  96.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  97.     if( p_vout->p_sys == NULL )
  98.     {
  99.         msg_Err( p_vout, "out of memory" );
  100.         return( 1 );
  101.     }
  102.     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
  103.     /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
  104.     for( i_timeout = 20 ; i_timeout-- ; )
  105.     {
  106.         if( NSApp == NULL )
  107.         {
  108.             msleep( INTF_IDLE_SLEEP );
  109.         }
  110.     }
  111.     if( NSApp == NULL )
  112.     {
  113.         /* no MacOS X intf, unable to communicate with MT */
  114.         msg_Err( p_vout, "no MacOS X interface present" );
  115.         free( p_vout->p_sys );
  116.         return( 1 );
  117.     }
  118.     p_vout->pf_init = InitVideo;
  119.     p_vout->pf_end = EndVideo;
  120.     p_vout->pf_manage = ManageVideo;
  121.     p_vout->pf_render = NULL;
  122.     p_vout->pf_display = DisplayVideo;
  123.     p_vout->pf_control = ControlVideo;
  124.     p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
  125.     var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  126.     var_Create( p_vout, "macosx-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  127.     var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  128.     var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  129.     
  130.     p_vout->p_sys->b_altivec = p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC;
  131.     msg_Dbg( p_vout, "We do%s have Altivec", p_vout->p_sys->b_altivec ? "" : "n't" );
  132.     
  133.     /* Initialize QuickTime */
  134.     p_vout->p_sys->h_img_descr = 
  135.         (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
  136.     p_vout->p_sys->p_matrix =
  137.         (MatrixRecordPtr)malloc( sizeof(MatrixRecord) );
  138.     if( ( err = EnterMovies() ) != noErr )
  139.     {
  140.         msg_Err( p_vout, "EnterMovies failed: %d", err );
  141.         free( p_vout->p_sys->p_matrix );
  142.         DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
  143.         free( p_vout->p_sys );
  144.         return VLC_EGENERIC;
  145.     }
  146.     /* Damn QT isn't thread safe. so keep a lock in the p_vlc object */
  147.     vlc_mutex_lock( &p_vout->p_vlc->quicktime_lock );
  148.     /* Can we find the right chroma ? */
  149.     if( p_vout->p_sys->b_altivec )
  150.     {
  151.         err = FindCodec( kYUVSPixelFormat, bestSpeedCodec,
  152.                         nil, &p_vout->p_sys->img_dc );
  153.     }
  154.     else
  155.     {
  156.         err = FindCodec( kYUV420CodecType, bestSpeedCodec,
  157.                         nil, &p_vout->p_sys->img_dc );
  158.     }
  159.     vlc_mutex_unlock( &p_vout->p_vlc->quicktime_lock );
  160.     
  161.     if( err == noErr && p_vout->p_sys->img_dc != 0 )
  162.     {
  163.         if( p_vout->p_sys->b_altivec )
  164.         {
  165.             p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
  166.             p_vout->p_sys->i_codec = kYUVSPixelFormat;
  167.         }
  168.         else
  169.         {
  170.             p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
  171.             p_vout->p_sys->i_codec = kYUV420CodecType;
  172.         }
  173.     }
  174.     else
  175.     {
  176.         msg_Err( p_vout, "failed to find an appropriate codec" );
  177.     }
  178.     if( p_vout->p_sys->img_dc == 0 )
  179.     {
  180.         free( p_vout->p_sys->p_matrix );
  181.         DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
  182.         free( p_vout->p_sys );
  183.         return VLC_EGENERIC;        
  184.     }
  185.     /* Setup the menuitem for the multiple displays. Read the vlc preference (macosx-vdev) for the primary display */
  186.     NSArray * o_screens = [NSScreen screens];
  187.     if( [o_screens count] > 0 && var_Type( p_vout, "video-device" ) == 0 )
  188.     {
  189.         int i = 1;
  190.         vlc_value_t val2, text;
  191.         NSScreen * o_screen;
  192.         var_Get( p_vout, "macosx-vdev", &val );
  193.         var_Create( p_vout, "video-device", VLC_VAR_INTEGER |
  194.                                             VLC_VAR_HASCHOICE ); 
  195.         text.psz_string = _("Video device");
  196.         var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
  197.         
  198.         NSEnumerator * o_enumerator = [o_screens objectEnumerator];
  199.         while( (o_screen = [o_enumerator nextObject]) != NULL )
  200.         {
  201.             char psz_temp[255];
  202.             NSRect s_rect = [o_screen frame];
  203.             snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1, 
  204.                       "%s %d (%dx%d)", _("Screen"), i,
  205.                       (int)s_rect.size.width, (int)s_rect.size.height ); 
  206.             text.psz_string = psz_temp;
  207.             val2.i_int = i;
  208.             var_Change( p_vout, "video-device",
  209.                         VLC_VAR_ADDCHOICE, &val2, &text );
  210.             if( ( i - 1 ) == val.i_int )
  211.             {
  212.                 var_Set( p_vout, "video-device", val2 );
  213.             }
  214.             i++;
  215.         }
  216.         var_AddCallback( p_vout, "video-device", vout_VarCallback,
  217.                          NULL );
  218.         val2.b_bool = VLC_TRUE;
  219.         var_Set( p_vout, "intf-change", val2 );
  220.     }
  221.     /* Spawn window */
  222.     p_vout->p_sys->o_window =
  223.         [[VLCWindow alloc] initWithVout: p_vout frame: nil];
  224. #define o_qtview p_vout->p_sys->o_qtview
  225.     o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
  226.     [p_vout->p_sys->o_window setContentView: o_qtview];
  227.     [o_qtview autorelease];
  228.     /* Retrieve the QuickDraw port */
  229.     [o_qtview lockFocus];
  230.     p_vout->p_sys->p_qdport = [o_qtview qdPort];
  231.     [o_qtview unlockFocus];
  232. #undef o_qtview
  233.     return VLC_SUCCESS;
  234. }
  235. /*****************************************************************************
  236.  * CloseVideo: destroy video thread output method
  237.  *****************************************************************************/
  238. void E_(CloseVideoQT) ( vlc_object_t *p_this )
  239. {
  240.     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; 
  241.     vout_thread_t * p_vout = (vout_thread_t *)p_this;
  242.     [p_vout->p_sys->o_window close];
  243.     /* Clean Up Quicktime environment */
  244.     ExitMovies();
  245.     free( p_vout->p_sys->p_matrix );
  246.     DisposeHandle( (Handle)p_vout->p_sys->h_img_descr );
  247.     [o_pool release];
  248.     free( p_vout->p_sys );
  249. }
  250. /*****************************************************************************
  251.  * InitVideo: initialize video thread output method
  252.  *****************************************************************************/
  253. static int InitVideo    ( vout_thread_t *p_vout )
  254. {
  255.     picture_t *p_pic;
  256.     int i_index;
  257.     I_OUTPUTPICTURES = 0;
  258.     /* Initialize the output structure; we already found a codec,
  259.      * and the corresponding chroma we will be using. Since we can
  260.      * arbitrary scale, stick to the coordinates and aspect. */
  261.     p_vout->output.i_width  = p_vout->render.i_width;
  262.     p_vout->output.i_height = p_vout->render.i_height;
  263.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  264.     SetPort( p_vout->p_sys->p_qdport );
  265.     QTScaleMatrix( p_vout );
  266.     if( QTCreateSequence( p_vout ) )
  267.     {
  268.         msg_Err( p_vout, "unable to create sequence" );
  269.         return( 1 );
  270.     }
  271.     /* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */
  272.     while( I_OUTPUTPICTURES < QT_MAX_DIRECTBUFFERS )
  273.     {
  274.         p_pic = NULL;
  275.         /* Find an empty picture slot */
  276.         for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
  277.         {
  278.             if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
  279.             {
  280.                 p_pic = p_vout->p_picture + i_index;
  281.                 break;
  282.             }
  283.         }
  284.         /* Allocate the picture */
  285.         if( p_pic == NULL || QTNewPicture( p_vout, p_pic ) )
  286.         {
  287.             break;
  288.         }
  289.         p_pic->i_status = DESTROYED_PICTURE;
  290.         p_pic->i_type   = DIRECT_PICTURE;
  291.         PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
  292.         I_OUTPUTPICTURES++;
  293.     }
  294.     return 0;
  295. }
  296. /*****************************************************************************
  297.  * EndVideo: terminate video thread output method
  298.  *****************************************************************************/
  299. static void EndVideo( vout_thread_t *p_vout )
  300. {
  301.     int i_index;
  302.     QTDestroySequence( p_vout );
  303.     /* Free the direct buffers we allocated */
  304.     for( i_index = I_OUTPUTPICTURES; i_index; )
  305.     {
  306.         i_index--;
  307.         QTFreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
  308.     }
  309. }
  310. /*****************************************************************************
  311.  * ManageVideo: handle events
  312.  *****************************************************************************
  313.  * This function should be called regularly by video output thread. It manages
  314.  * console events. It returns a non null value on error.
  315.  *****************************************************************************/
  316. static int ManageVideo( vout_thread_t *p_vout )
  317. {
  318.     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
  319.     {
  320.         if( CoToggleFullscreen( p_vout ) )  
  321.         {
  322.             return( 1 );
  323.         }
  324.         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
  325.     }
  326.     if( p_vout->i_changes & VOUT_SIZE_CHANGE ) 
  327.     {
  328.         QTScaleMatrix( p_vout );
  329.         SetDSequenceMatrix( p_vout->p_sys->i_seq, 
  330.                             p_vout->p_sys->p_matrix );
  331.  
  332.         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
  333.     }
  334.     [p_vout->p_sys->o_window manage];
  335.     
  336.     return( 0 );
  337. }
  338. /*****************************************************************************
  339.  * vout_Display: displays previously rendered output
  340.  *****************************************************************************
  341.  * This function sends the currently rendered image to the display.
  342.  *****************************************************************************/
  343. static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
  344. {
  345.     OSErr err;
  346.     CodecFlags flags;
  347.     if( ( err = DecompressSequenceFrameWhen( 
  348.                     p_vout->p_sys->i_seq,
  349.                     p_pic->p_sys->p_data,
  350.                     p_pic->p_sys->i_size,                    
  351.                     codecFlagUseImageBuffer, &flags, NULL, NULL ) != noErr ) )
  352.     {
  353.         msg_Warn( p_vout, "DecompressSequenceFrameWhen failed: %d", err );
  354.     }
  355.     else
  356.     {
  357.         QDFlushPortBuffer( p_vout->p_sys->p_qdport, nil );
  358.     }
  359. }
  360. /*****************************************************************************
  361.  * ControlVideo: control facility for the vout
  362.  *****************************************************************************/
  363. static int ControlVideo( vout_thread_t *p_vout, int i_query, va_list args )
  364. {
  365.     vlc_bool_t b_arg;
  366.     switch( i_query )
  367.     {
  368.         case VOUT_SET_STAY_ON_TOP:
  369.             b_arg = va_arg( args, vlc_bool_t );
  370.             [p_vout->p_sys->o_window setOnTop: b_arg];
  371.             return VLC_SUCCESS;
  372.         case VOUT_CLOSE:
  373.         case VOUT_REPARENT:
  374.         default:
  375.             return vout_vaControlDefault( p_vout, i_query, args );
  376.     }
  377. }
  378. /*****************************************************************************
  379.  * CoToggleFullscreen: toggle fullscreen 
  380.  *****************************************************************************
  381.  * Returns 0 on success, 1 otherwise
  382.  *****************************************************************************/
  383. static int CoToggleFullscreen( vout_thread_t *p_vout )
  384. {
  385.     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
  386.     QTDestroySequence( p_vout );
  387.     if( !p_vout->b_fullscreen )
  388.     {
  389.         /* Save window size and position */
  390.         p_vout->p_sys->s_frame.size =
  391.             [[p_vout->p_sys->o_window contentView] frame].size;
  392.         p_vout->p_sys->s_frame.origin =
  393.             [p_vout->p_sys->o_window frame].origin;
  394.         p_vout->p_sys->b_saved_frame = VLC_TRUE;
  395.     }
  396.     [p_vout->p_sys->o_window close];
  397.     p_vout->b_fullscreen = !p_vout->b_fullscreen;
  398.     if( p_vout->p_sys->b_saved_frame )
  399.     {
  400.         p_vout->p_sys->o_window = [[VLCWindow alloc]
  401.             initWithVout: p_vout frame: &p_vout->p_sys->s_frame];
  402.     }
  403.     else
  404.     {
  405.         p_vout->p_sys->o_window = [[VLCWindow alloc]
  406.             initWithVout: p_vout frame: nil];
  407.     }
  408. #define o_qtview p_vout->p_sys->o_qtview
  409.     o_qtview = [[VLCQTView alloc] initWithVout: p_vout];
  410.     [p_vout->p_sys->o_window setContentView: o_qtview];
  411.     [o_qtview autorelease];
  412.     /* Retrieve the QuickDraw port */
  413.     [o_qtview lockFocus];
  414.     p_vout->p_sys->p_qdport = [o_qtview qdPort];
  415.     [o_qtview unlockFocus];
  416. #undef o_qtview
  417.     SetPort( p_vout->p_sys->p_qdport );
  418.     QTScaleMatrix( p_vout );
  419.     if( QTCreateSequence( p_vout ) )
  420.     {
  421.         msg_Err( p_vout, "unable to create sequence" );
  422.         return( 1 ); 
  423.     } 
  424.     [o_pool release];
  425.     return 0;
  426. }
  427. /*****************************************************************************
  428.  * QTScaleMatrix: scale matrix 
  429.  *****************************************************************************/
  430. static void QTScaleMatrix( vout_thread_t *p_vout )
  431. {
  432.     Rect s_rect;
  433.     vlc_value_t val;
  434.     unsigned int i_width, i_height;
  435.     Fixed factor_x, factor_y;
  436.     unsigned int i_offset_x = 0;
  437.     unsigned int i_offset_y = 0;
  438.     GetPortBounds( p_vout->p_sys->p_qdport, &s_rect );
  439.     i_width = s_rect.right - s_rect.left;
  440.     i_height = s_rect.bottom - s_rect.top;
  441.     var_Get( p_vout, "macosx-stretch", &val );
  442.     if( val.b_bool )
  443.     {
  444.         factor_x = FixDiv( Long2Fix( i_width ),
  445.                            Long2Fix( p_vout->output.i_width ) );
  446.         factor_y = FixDiv( Long2Fix( i_height ),
  447.                            Long2Fix( p_vout->output.i_height ) );
  448.                            
  449.     }
  450.     else if( i_height * p_vout->output.i_aspect < i_width * VOUT_ASPECT_FACTOR )
  451.     {
  452.         int i_adj_width = i_height * p_vout->output.i_aspect /
  453.                           VOUT_ASPECT_FACTOR;
  454.         factor_x = FixDiv( Long2Fix( i_adj_width ),
  455.                            Long2Fix( p_vout->output.i_width ) );
  456.         factor_y = FixDiv( Long2Fix( i_height ),
  457.                            Long2Fix( p_vout->output.i_height ) );
  458.         i_offset_x = (i_width - i_adj_width) / 2;
  459.     }
  460.     else
  461.     {
  462.         int i_adj_height = i_width * VOUT_ASPECT_FACTOR /
  463.                            p_vout->output.i_aspect;
  464.         factor_x = FixDiv( Long2Fix( i_width ),
  465.                            Long2Fix( p_vout->output.i_width ) );
  466.         factor_y = FixDiv( Long2Fix( i_adj_height ),
  467.                            Long2Fix( p_vout->output.i_height ) );
  468.         i_offset_y = (i_height - i_adj_height) / 2;
  469.     }
  470.     
  471.     SetIdentityMatrix( p_vout->p_sys->p_matrix );
  472.     ScaleMatrix( p_vout->p_sys->p_matrix,
  473.                  factor_x, factor_y,
  474.                  Long2Fix(0), Long2Fix(0) );
  475.                  
  476.     TranslateMatrix( p_vout->p_sys->p_matrix,
  477.                  Long2Fix(i_offset_x), Long2Fix(i_offset_y) );
  478. }
  479. /*****************************************************************************
  480.  * QTCreateSequence: create a new sequence 
  481.  *****************************************************************************
  482.  * Returns 0 on success, 1 otherwise
  483.  *****************************************************************************/
  484. static int QTCreateSequence( vout_thread_t *p_vout )
  485. {
  486.     OSErr err;
  487.     ImageDescriptionPtr p_descr;
  488.     HLock( (Handle)p_vout->p_sys->h_img_descr );
  489.     p_descr = *p_vout->p_sys->h_img_descr;
  490.     p_descr->idSize = sizeof(ImageDescription);
  491.     p_descr->cType = p_vout->p_sys->i_codec;
  492.     p_descr->version = 2;
  493.     p_descr->revisionLevel = 0;
  494.     p_descr->vendor = 'mpla';
  495.     p_descr->width = p_vout->output.i_width;
  496.     p_descr->height = p_vout->output.i_height;
  497.     p_descr->hRes = Long2Fix(72);
  498.     p_descr->vRes = Long2Fix(72);
  499.     p_descr->spatialQuality = codecLosslessQuality;
  500.     p_descr->frameCount = 1;
  501.     p_descr->clutID = -1;
  502.     p_descr->dataSize = 0;
  503.     p_descr->depth = 24;
  504.     HUnlock( (Handle)p_vout->p_sys->h_img_descr );
  505.     if( ( err = DecompressSequenceBeginS( 
  506.                               &p_vout->p_sys->i_seq,
  507.                               p_vout->p_sys->h_img_descr,
  508.                               NULL,
  509.                               (p_descr->width * p_descr->height * 16) / 8,
  510.                               p_vout->p_sys->p_qdport,
  511.                               NULL, NULL,
  512.                               p_vout->p_sys->p_matrix,
  513.                               srcCopy, NULL,
  514.                               codecFlagUseImageBuffer,
  515.                               codecLosslessQuality,
  516.                               bestSpeedCodec ) ) )
  517.     {
  518.         msg_Err( p_vout, "DecompressSequenceBeginS failed: %d", err );
  519.         return( 1 );
  520.     }
  521.     return( 0 );
  522. }
  523. /*****************************************************************************
  524.  * QTDestroySequence: destroy sequence 
  525.  *****************************************************************************/
  526. static void QTDestroySequence( vout_thread_t *p_vout )
  527. {
  528.     CDSequenceEnd( p_vout->p_sys->i_seq );
  529. }
  530. /*****************************************************************************
  531.  * QTNewPicture: allocate a picture
  532.  *****************************************************************************
  533.  * Returns 0 on success, 1 otherwise
  534.  *****************************************************************************/
  535. static int QTNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
  536. {
  537.     /* We know the chroma, allocate a buffer which will be used
  538.      * directly by the decoder */
  539.     p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
  540.     if( p_pic->p_sys == NULL )
  541.     {
  542.         return( -1 );
  543.     }
  544.     vout_InitPicture( VLC_OBJECT( p_vout), p_pic, p_vout->output.i_chroma,
  545.                       p_vout->output.i_width, p_vout->output.i_height,
  546.                       p_vout->output.i_aspect );
  547.     switch( p_vout->output.i_chroma )
  548.     {
  549.         case VLC_FOURCC('Y','U','Y','2'):
  550.             p_pic->p_sys->i_size = p_vout->output.i_width * p_vout->output.i_height * 2;
  551.             /* Allocate the memory buffer */
  552.             p_pic->p_data = vlc_memalign( &p_pic->p_data_orig,
  553.                                           16, p_pic->p_sys->i_size );
  554.             p_pic->p[0].p_pixels = p_pic->p_data;
  555.             p_pic->p[0].i_lines = p_vout->output.i_height;
  556.             p_pic->p[0].i_visible_lines = p_vout->output.i_height;
  557.             p_pic->p[0].i_pitch = p_vout->output.i_width * 2;
  558.             p_pic->p[0].i_pixel_pitch = 1;
  559.             p_pic->p[0].i_visible_pitch = p_vout->output.i_width * 2;
  560.             p_pic->i_planes = 1;
  561.             p_pic->p_sys->p_data = (void *)p_pic->p[0].p_pixels;
  562.             break;
  563.             
  564.         case VLC_FOURCC('I','4','2','0'):
  565.             p_pic->p_sys->p_data = (void *)&p_pic->p_sys->pixmap_i420;
  566.             p_pic->p_sys->i_size = sizeof(PlanarPixmapInfoYUV420);
  567.             
  568.             /* Allocate the memory buffer */
  569.             p_pic->p_data = vlc_memalign( &p_pic->p_data_orig,
  570.                                           16, p_vout->output.i_width * p_vout->output.i_height * 3 / 2 );
  571.             /* Y buffer */
  572.             p_pic->Y_PIXELS = p_pic->p_data; 
  573.             p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
  574.             p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
  575.             p_pic->p[Y_PLANE].i_pitch = p_vout->output.i_width;
  576.             p_pic->p[Y_PLANE].i_pixel_pitch = 1;
  577.             p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width;
  578.             /* U buffer */
  579.             p_pic->U_PIXELS = p_pic->Y_PIXELS + p_vout->output.i_height * p_vout->output.i_width;
  580.             p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
  581.             p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
  582.             p_pic->p[U_PLANE].i_pitch = p_vout->output.i_width / 2;
  583.             p_pic->p[U_PLANE].i_pixel_pitch = 1;
  584.             p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2;
  585.             /* V buffer */
  586.             p_pic->V_PIXELS = p_pic->U_PIXELS + p_vout->output.i_height * p_vout->output.i_width / 4;
  587.             p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
  588.             p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
  589.             p_pic->p[V_PLANE].i_pitch = p_vout->output.i_width / 2;
  590.             p_pic->p[V_PLANE].i_pixel_pitch = 1;
  591.             p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2;
  592.             /* We allocated 3 planes */
  593.             p_pic->i_planes = 3;
  594. #define P p_pic->p_sys->pixmap_i420
  595.             P.componentInfoY.offset = (void *)p_pic->Y_PIXELS
  596.                                        - p_pic->p_sys->p_data;
  597.             P.componentInfoCb.offset = (void *)p_pic->U_PIXELS
  598.                                         - p_pic->p_sys->p_data;
  599.             P.componentInfoCr.offset = (void *)p_pic->V_PIXELS
  600.                                         - p_pic->p_sys->p_data;
  601.             P.componentInfoY.rowBytes = p_vout->output.i_width;
  602.             P.componentInfoCb.rowBytes = p_vout->output.i_width / 2;
  603.             P.componentInfoCr.rowBytes = p_vout->output.i_width / 2;
  604. #undef P
  605.             break;
  606.         
  607.         default:
  608.             /* Unknown chroma, tell the guy to get lost */
  609.             free( p_pic->p_sys );
  610.             msg_Err( p_vout, "never heard of chroma 0x%.8x (%4.4s)",
  611.                      p_vout->output.i_chroma, (char*)&p_vout->output.i_chroma );
  612.             p_pic->i_planes = 0;
  613.             return( -1 );
  614.     }
  615.     return( 0 );
  616. }
  617. /*****************************************************************************
  618.  * QTFreePicture: destroy a picture allocated with QTNewPicture
  619.  *****************************************************************************/
  620. static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
  621. {
  622.     switch( p_vout->output.i_chroma )
  623.     {
  624.         case VLC_FOURCC('I','4','2','0'):
  625.             free( p_pic->p_data_orig );
  626.             break;
  627.     }
  628.     free( p_pic->p_sys );
  629. }
  630. /*****************************************************************************
  631.  * VLCQTView implementation
  632.  *****************************************************************************/
  633. @implementation VLCQTView
  634. - (id) initWithVout:(vout_thread_t *)_p_vout
  635. {
  636.     p_vout = _p_vout;
  637.     return [super init];
  638. }
  639. - (void)drawRect:(NSRect)rect
  640. {
  641.     [[NSColor blackColor] set];
  642.     NSRectFill( rect );
  643.     [super drawRect: rect];
  644.     p_vout->i_changes |= VOUT_SIZE_CHANGE;
  645. }
  646. @end