1 /*****************************************************************************
2 * vout_macosx.c: MacOS X video output plugin
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
6 * Authors: Colin Delacroix <colin@zoy.org>
7 * Florian G. Pflug <fgp@phlo.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <errno.h> /* ENOMEM */
28 #include <stdlib.h> /* free() */
29 #include <string.h> /* strerror() */
31 #include <videolan/vlc.h>
33 #include "interface.h"
36 #include "video_output.h"
40 #include <QuickTime/QuickTime.h>
42 /*****************************************************************************
43 * vout_sys_t: MacOS X video output method descriptor
44 *****************************************************************************
45 * This structure is part of the video output thread descriptor.
46 * It describes the MacOS X specific properties of an output thread.
47 *****************************************************************************/
48 typedef unsigned int yuv2_data_t ;
49 typedef struct vout_sys_s
51 osx_com_t osx_communication ;
53 ImageDescriptionHandle h_img_descr ;
55 unsigned int c_codec ;
56 MatrixRecordPtr p_matrix ;
59 unsigned i_yuv2_size ;
60 PlanarPixmapInfoYUV420 s_ppiy420 ;
64 /*****************************************************************************
66 *****************************************************************************/
67 static int vout_Probe ( probedata_t *p_data );
68 static int vout_Create ( struct vout_thread_s * );
69 static int vout_Init ( struct vout_thread_s * );
70 static void vout_End ( struct vout_thread_s * );
71 static void vout_Destroy ( struct vout_thread_s * );
72 static int vout_Manage ( struct vout_thread_s * );
73 static void vout_Display ( struct vout_thread_s * );
76 static void fillout_PPIYUV420( picture_t *p_y420, PlanarPixmapInfoYUV420 *p_ppiy420 ) ;
77 static void fillout_ImageDescription(ImageDescriptionHandle h_descr, unsigned int i_with, unsigned int i_height, unsigned int c_codec) ;
78 static void fillout_ScalingMatrix( vout_thread_t *p_vout ) ;
79 static OSErr new_QTSequence(ImageSequence *i_seq, CGrafPtr p_port, ImageDescriptionHandle h_descr, MatrixRecordPtr p_matrix) ;
80 static int create_QTSequenceBestCodec( vout_thread_t *p_vout ) ;
81 static void dispose_QTSequence( vout_thread_t *p_vout ) ;
82 static void convert_Y420_to_YUV2( picture_t *p_y420, yuv2_data_t *p_yuv2 ) ;
84 /*****************************************************************************
85 * Functions exported as capabilities. They are declared as static so that
86 * we don't pollute the namespace too much.
87 *****************************************************************************/
88 void _M( vout_getfunctions )( function_list_t * p_function_list )
90 p_function_list->pf_probe = vout_Probe;
91 p_function_list->functions.vout.pf_create = vout_Create;
92 p_function_list->functions.vout.pf_init = vout_Init;
93 p_function_list->functions.vout.pf_end = vout_End;
94 p_function_list->functions.vout.pf_destroy = vout_Destroy;
95 p_function_list->functions.vout.pf_manage = vout_Manage;
96 p_function_list->functions.vout.pf_display = vout_Display;
97 p_function_list->functions.vout.pf_setpalette = NULL;
100 /*****************************************************************************
101 * intf_Probe: return a score
102 *****************************************************************************/
103 static int vout_Probe( probedata_t *p_data )
105 if( TestMethod( VOUT_METHOD_VAR, "macosx" ) )
113 /*****************************************************************************
114 * vout_Create: allocates MacOS X video thread output method
115 *****************************************************************************
116 * This function allocates and initializes a MacOS X vout method.
117 *****************************************************************************/
118 static int vout_Create( vout_thread_t *p_vout )
120 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
121 if( p_vout->p_sys == NULL )
123 intf_ErrMsg( "error: %s", strerror( ENOMEM ) );
126 p_vout->p_sys->h_img_descr = (ImageDescriptionHandle)NewHandleClear( sizeof( ImageDescription ) ) ;
127 p_vout->p_sys->p_matrix = (MatrixRecordPtr)malloc( sizeof( MatrixRecord ) ) ;
128 p_vout->p_sys->c_codec = 'NONE' ;
135 /*****************************************************************************
136 * vout_Init: initialize video thread output method
137 *****************************************************************************/
138 static int vout_Init( vout_thread_t *p_vout )
140 p_vout->b_need_render = 0 ;
141 p_vout->i_bytes_per_line = p_vout->i_width ;
142 p_vout->p_sys->c_codec = 'NONE' ;
143 p_vout->p_sys->osx_communication.i_changes |= OSX_VOUT_INTF_REQUEST_QDPORT ;
148 /*****************************************************************************
149 * vout_End: terminate video thread output method
150 *****************************************************************************/
151 static void vout_End( vout_thread_t *p_vout )
153 dispose_QTSequence( p_vout ) ;
154 p_vout->p_sys->osx_communication.i_changes |= OSX_VOUT_INTF_RELEASE_QDPORT ;
157 /*****************************************************************************
158 * vout_Destroy: destroy video thread output method
159 *****************************************************************************/
160 static void vout_Destroy( vout_thread_t *p_vout )
162 free( p_vout->p_sys->p_matrix ) ;
163 DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ) ;
164 free( p_vout->p_sys );
167 /*****************************************************************************
168 * vout_Manage: handle events
169 *****************************************************************************
170 * This function should be called regularly by video output thread. It manages
171 * console events. It returns a non null value on error.
172 *****************************************************************************/
173 static int vout_Manage( vout_thread_t *p_vout )
175 if ( p_vout->p_sys->osx_communication.i_changes & OSX_INTF_VOUT_QDPORT_CHANGE ) {
176 dispose_QTSequence( p_vout ) ;
177 create_QTSequenceBestCodec( p_vout ) ;
179 else if ( p_vout->p_sys->osx_communication.i_changes & OSX_INTF_VOUT_SIZE_CHANGE ) {
180 if ( p_vout->p_sys->c_codec != 'NONE' ) {
181 fillout_ScalingMatrix( p_vout ) ;
182 SetDSequenceMatrix( p_vout->p_sys->i_seq, p_vout->p_sys->p_matrix ) ;
186 p_vout->p_sys->osx_communication.i_changes &= ~(
187 OSX_INTF_VOUT_QDPORT_CHANGE |
188 OSX_INTF_VOUT_SIZE_CHANGE
195 /*****************************************************************************
196 * vout_OSX_Display: displays previously rendered output
197 *****************************************************************************
198 * This function send the currently rendered image to image, waits until
199 * it is displayed and switch the two rendering buffers, preparing next frame.
200 *****************************************************************************/
201 void vout_Display( vout_thread_t *p_vout )
203 CodecFlags out_flags ;
205 switch (p_vout->p_sys->c_codec)
208 convert_Y420_to_YUV2(p_vout->p_rendered_pic, p_vout->p_sys->p_yuv2) ;
209 DecompressSequenceFrameS(
210 p_vout->p_sys->i_seq,
211 (void *)p_vout->p_sys->p_yuv2,
212 p_vout->p_sys->i_yuv2_size,
213 codecFlagUseScreenBuffer,
219 fillout_PPIYUV420(p_vout->p_rendered_pic, &p_vout->p_sys->s_ppiy420) ;
220 DecompressSequenceFrameS(
221 p_vout->p_sys->i_seq,
222 (void *)&p_vout->p_sys->s_ppiy420,
223 sizeof(PlanarPixmapInfoYUV420),
224 codecFlagUseScreenBuffer,
230 intf_WarnMsg( 1, "vout_macosx: vout_Display called, but no codec available" ) ;
234 static void fillout_PPIYUV420( picture_t *p_y420, PlanarPixmapInfoYUV420 *p_ppiy420 )
236 p_ppiy420->componentInfoY.offset = (void *)p_y420->p_y - (void *)p_ppiy420 ;
237 p_ppiy420->componentInfoY.rowBytes = p_y420->i_width ;
238 p_ppiy420->componentInfoCb.offset = (void *)p_y420->p_u - (void *)p_ppiy420 ;
239 p_ppiy420->componentInfoCb.rowBytes = p_y420->i_width / 2;
240 p_ppiy420->componentInfoCr.offset = (void *)p_y420->p_v - (void *)p_ppiy420 ;
241 p_ppiy420->componentInfoCr.rowBytes = p_y420->i_width / 2;
245 static void fillout_ImageDescription(ImageDescriptionHandle h_descr, unsigned int i_width, unsigned int i_height, unsigned int c_codec)
247 ImageDescriptionPtr p_descr ;
249 HLock((Handle)h_descr) ;
251 p_descr->idSize = sizeof(ImageDescription) ;
252 p_descr->cType = c_codec ;
253 p_descr->resvd1 = 0 ; //Reserved
254 p_descr->resvd2 = 0 ; //Reserved
255 p_descr->dataRefIndex = 0 ; //Reserved
256 p_descr->version = 1 ; //
257 p_descr->revisionLevel = 0 ;
258 p_descr->vendor = 'appl' ; //How do we get a vendor id??
259 p_descr->width = i_width ;
260 p_descr->height = i_height ;
261 p_descr->hRes = Long2Fix(72) ;
262 p_descr->vRes = Long2Fix(72) ;
263 p_descr->spatialQuality = codecLosslessQuality ;
264 p_descr->frameCount = 1 ;
265 p_descr->clutID = -1 ; //We don't need a color table
270 p_descr->dataSize=i_width * i_height * 2 ;
271 p_descr->depth = 24 ;
274 p_descr->dataSize=i_width * i_height * 1.5 ;
275 p_descr->depth = 12 ;
279 HUnlock((Handle)h_descr) ;
282 static void fillout_ScalingMatrix( vout_thread_t *p_vout)
288 GetPortBounds( p_vout->p_sys->osx_communication.p_qdport, &s_rect ) ;
289 // if (((s_rect.right - s_rect.left) / ((float) p_vout->i_width)) < ((s_rect.bottom - s_rect.top) / ((float) p_vout->i_height)))
290 factor_x = FixDiv(Long2Fix(s_rect.right - s_rect.left), Long2Fix(p_vout->i_width)) ;
292 factor_y = FixDiv(Long2Fix(s_rect.bottom - s_rect.top), Long2Fix(p_vout->i_height)) ;
294 SetIdentityMatrix(p_vout->p_sys->p_matrix) ;
295 ScaleMatrix( p_vout->p_sys->p_matrix, factor_x, factor_y, Long2Fix(0), Long2Fix(0) ) ;
298 static OSErr new_QTSequence( ImageSequence *i_seq, CGrafPtr p_qdport, ImageDescriptionHandle h_descr, MatrixRecordPtr p_matrix )
300 return DecompressSequenceBeginS(
306 NULL, //device to display (is set implicit via the qdPort)
309 0, //just do plain copying
310 NULL, //no mask region
311 codecFlagUseScreenBuffer,
312 codecLosslessQuality,
313 (DecompressorComponent) bestSpeedCodec
317 static int create_QTSequenceBestCodec( vout_thread_t *p_vout )
319 if ( p_vout->p_sys->osx_communication.p_qdport == nil)
321 p_vout->p_sys->c_codec = 'NONE' ;
325 SetPort( p_vout->p_sys->osx_communication.p_qdport ) ;
326 fillout_ScalingMatrix( p_vout ) ;
327 fillout_ImageDescription(
328 p_vout->p_sys->h_img_descr,
333 if ( !new_QTSequence(
334 &p_vout->p_sys->i_seq,
335 p_vout->p_sys->osx_communication.p_qdport,
336 p_vout->p_sys->h_img_descr,
337 p_vout->p_sys->p_matrix
340 p_vout->p_sys->c_codec = 'y420' ;
344 p_vout->p_sys->c_codec = 'NONE' ;
348 static void dispose_QTSequence( vout_thread_t *p_vout )
350 if (p_vout->p_sys->c_codec == 'NONE')
353 CDSequenceEnd( p_vout->p_sys->i_seq ) ;
354 switch (p_vout->p_sys->c_codec)
357 free( (void *)p_vout->p_sys->p_yuv2 ) ;
358 p_vout->p_sys->i_yuv2_size = 0 ;
363 p_vout->p_sys->c_codec = 'NONE' ;
366 static void convert_Y420_to_YUV2( picture_t *p_y420, yuv2_data_t *p_yuv2 )
368 unsigned int width = p_y420->i_width, height = p_y420->i_height ;
371 for( x=0; x < height; x++ )
373 for( y=0; y < (width/2); y++ )
375 p_yuv2[(width/2)*x + y] =
376 (p_y420->p_y[width*x + 2*y]) << 24 |
377 ((p_y420->p_u[(width/2)*(x/2) + y] ^ 0x80) << 16) |
378 (p_y420->p_y[width*x + 2*y + 1] << 8) |
379 (p_y420->p_v[(width/2)*(x/2) + y] ^ 0x80) ;