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
#define MODULE_NAME macosx
25
#include "modules_inner.h"
27
/*****************************************************************************
29
*****************************************************************************/
32
#include <errno.h> /* ENOMEM */
33
#include <stdlib.h> /* free() */
34
#include <string.h> /* strerror() */
42
#include "interface.h"
45
#include "video_output.h"
51
#include <QuickTime/QuickTime.h>
53
/*****************************************************************************
54
* vout_sys_t: MacOS X video output method descriptor
55
*****************************************************************************
56
* This structure is part of the video output thread descriptor.
57
* It describes the MacOS X specific properties of an output thread.
58
*****************************************************************************/
59
typedef unsigned int yuv2_data_t ;
60
typedef struct vout_sys_s
62
osx_com_t osx_communication ;
64
ImageDescriptionHandle h_img_descr ;
66
unsigned int c_codec ;
67
MatrixRecordPtr p_matrix ;
70
unsigned i_yuv2_size ;
71
PlanarPixmapInfoYUV420 s_ppiy420 ;
75
/*****************************************************************************
77
*****************************************************************************/
78
static int vout_Probe ( probedata_t *p_data );
79
static int vout_Create ( struct vout_thread_s * );
80
static int vout_Init ( struct vout_thread_s * );
81
static void vout_End ( struct vout_thread_s * );
82
static void vout_Destroy ( struct vout_thread_s * );
83
static int vout_Manage ( struct vout_thread_s * );
84
static void vout_Display ( struct vout_thread_s * );
87
static void fillout_PPIYUV420( picture_t *p_y420, PlanarPixmapInfoYUV420 *p_ppiy420 ) ;
88
static void fillout_ImageDescription(ImageDescriptionHandle h_descr, unsigned int i_with, unsigned int i_height, unsigned int c_codec) ;
89
static void fillout_ScalingMatrix( vout_thread_t *p_vout ) ;
90
static OSErr new_QTSequence(ImageSequence *i_seq, CGrafPtr p_port, ImageDescriptionHandle h_descr, MatrixRecordPtr p_matrix) ;
91
static int create_QTSequenceBestCodec( vout_thread_t *p_vout ) ;
92
static void dispose_QTSequence( vout_thread_t *p_vout ) ;
93
static void convert_Y420_to_YUV2( picture_t *p_y420, yuv2_data_t *p_yuv2 ) ;
95
/*****************************************************************************
96
* Functions exported as capabilities. They are declared as static so that
97
* we don't pollute the namespace too much.
98
*****************************************************************************/
99
void _M( vout_getfunctions )( function_list_t * p_function_list )
101
p_function_list->pf_probe = vout_Probe;
102
p_function_list->functions.vout.pf_create = vout_Create;
103
p_function_list->functions.vout.pf_init = vout_Init;
104
p_function_list->functions.vout.pf_end = vout_End;
105
p_function_list->functions.vout.pf_destroy = vout_Destroy;
106
p_function_list->functions.vout.pf_manage = vout_Manage;
107
p_function_list->functions.vout.pf_display = vout_Display;
108
p_function_list->functions.vout.pf_setpalette = NULL;
111
/*****************************************************************************
112
* intf_Probe: return a score
113
*****************************************************************************/
114
static int vout_Probe( probedata_t *p_data )
116
if( TestMethod( VOUT_METHOD_VAR, "macosx" ) )
124
/*****************************************************************************
125
* vout_Create: allocates MacOS X video thread output method
126
*****************************************************************************
127
* This function allocates and initializes a MacOS X vout method.
128
*****************************************************************************/
129
static int vout_Create( vout_thread_t *p_vout )
131
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
132
if( p_vout->p_sys == NULL )
134
intf_ErrMsg( "error: %s", strerror( ENOMEM ) );
137
p_vout->p_sys->h_img_descr = (ImageDescriptionHandle)NewHandleClear( sizeof( ImageDescription ) ) ;
138
p_vout->p_sys->p_matrix = (MatrixRecordPtr)malloc( sizeof( MatrixRecord ) ) ;
139
p_vout->p_sys->c_codec = 'NONE' ;
146
/*****************************************************************************
147
* vout_Init: initialize video thread output method
148
*****************************************************************************/
149
static int vout_Init( vout_thread_t *p_vout )
151
p_vout->b_need_render = 0 ;
152
p_vout->i_bytes_per_line = p_vout->i_width ;
153
p_vout->p_sys->c_codec = 'NONE' ;
154
p_vout->p_sys->osx_communication.i_changes |= OSX_VOUT_INTF_REQUEST_QDPORT ;
159
/*****************************************************************************
160
* vout_End: terminate video thread output method
161
*****************************************************************************/
162
static void vout_End( vout_thread_t *p_vout )
164
dispose_QTSequence( p_vout ) ;
165
p_vout->p_sys->osx_communication.i_changes |= OSX_VOUT_INTF_RELEASE_QDPORT ;
168
/*****************************************************************************
169
* vout_Destroy: destroy video thread output method
170
*****************************************************************************/
171
static void vout_Destroy( vout_thread_t *p_vout )
173
free( p_vout->p_sys->p_matrix ) ;
174
DisposeHandle( (Handle)p_vout->p_sys->h_img_descr ) ;
175
free( p_vout->p_sys );
178
/*****************************************************************************
179
* vout_Manage: handle events
180
*****************************************************************************
181
* This function should be called regularly by video output thread. It manages
182
* console events. It returns a non null value on error.
183
*****************************************************************************/
184
static int vout_Manage( vout_thread_t *p_vout )
186
if ( p_vout->p_sys->osx_communication.i_changes & OSX_INTF_VOUT_QDPORT_CHANGE ) {
187
dispose_QTSequence( p_vout ) ;
188
create_QTSequenceBestCodec( p_vout ) ;
190
else if ( p_vout->p_sys->osx_communication.i_changes & OSX_INTF_VOUT_SIZE_CHANGE ) {
191
if ( p_vout->p_sys->c_codec != 'NONE' ) {
192
fillout_ScalingMatrix( p_vout ) ;
193
SetDSequenceMatrix( p_vout->p_sys->i_seq, p_vout->p_sys->p_matrix ) ;
197
p_vout->p_sys->osx_communication.i_changes &= ~(
198
OSX_INTF_VOUT_QDPORT_CHANGE |
199
OSX_INTF_VOUT_SIZE_CHANGE
206
/*****************************************************************************
207
* vout_OSX_Display: displays previously rendered output
208
*****************************************************************************
209
* This function send the currently rendered image to image, waits until
210
* it is displayed and switch the two rendering buffers, preparing next frame.
211
*****************************************************************************/
212
void vout_Display( vout_thread_t *p_vout )
214
CodecFlags out_flags ;
216
switch (p_vout->p_sys->c_codec)
219
convert_Y420_to_YUV2(p_vout->p_rendered_pic, p_vout->p_sys->p_yuv2) ;
220
DecompressSequenceFrameS(
221
p_vout->p_sys->i_seq,
222
(void *)p_vout->p_sys->p_yuv2,
223
p_vout->p_sys->i_yuv2_size,
224
codecFlagUseScreenBuffer,
230
fillout_PPIYUV420(p_vout->p_rendered_pic, &p_vout->p_sys->s_ppiy420) ;
231
DecompressSequenceFrameS(
232
p_vout->p_sys->i_seq,
233
(void *)&p_vout->p_sys->s_ppiy420,
234
sizeof(PlanarPixmapInfoYUV420),
235
codecFlagUseScreenBuffer,
241
intf_WarnMsg( 1, "vout_macosx: vout_Display called, but no codec available" ) ;
245
static void fillout_PPIYUV420( picture_t *p_y420, PlanarPixmapInfoYUV420 *p_ppiy420 )
247
p_ppiy420->componentInfoY.offset = (void *)p_y420->p_y - (void *)p_ppiy420 ;
248
p_ppiy420->componentInfoY.rowBytes = p_y420->i_width ;
249
p_ppiy420->componentInfoCb.offset = (void *)p_y420->p_u - (void *)p_ppiy420 ;
250
p_ppiy420->componentInfoCb.rowBytes = p_y420->i_width / 2;
251
p_ppiy420->componentInfoCr.offset = (void *)p_y420->p_v - (void *)p_ppiy420 ;
252
p_ppiy420->componentInfoCr.rowBytes = p_y420->i_width / 2;
256
static void fillout_ImageDescription(ImageDescriptionHandle h_descr, unsigned int i_width, unsigned int i_height, unsigned int c_codec)
258
ImageDescriptionPtr p_descr ;
260
HLock((Handle)h_descr) ;
262
p_descr->idSize = sizeof(ImageDescription) ;
263
p_descr->cType = c_codec ;
264
p_descr->resvd1 = 0 ; //Reserved
265
p_descr->resvd2 = 0 ; //Reserved
266
p_descr->dataRefIndex = 0 ; //Reserved
267
p_descr->version = 1 ; //
268
p_descr->revisionLevel = 0 ;
269
p_descr->vendor = 'appl' ; //How do we get a vendor id??
270
p_descr->width = i_width ;
271
p_descr->height = i_height ;
272
p_descr->hRes = Long2Fix(72) ;
273
p_descr->vRes = Long2Fix(72) ;
274
p_descr->spatialQuality = codecLosslessQuality ;
275
p_descr->frameCount = 1 ;
276
p_descr->clutID = -1 ; //We don't need a color table
281
p_descr->dataSize=i_width * i_height * 2 ;
282
p_descr->depth = 24 ;
285
p_descr->dataSize=i_width * i_height * 1.5 ;
286
p_descr->depth = 12 ;
290
HUnlock((Handle)h_descr) ;
293
static void fillout_ScalingMatrix( vout_thread_t *p_vout)
299
GetPortBounds( p_vout->p_sys->osx_communication.p_qdport, &s_rect ) ;
300
// if (((s_rect.right - s_rect.left) / ((float) p_vout->i_width)) < ((s_rect.bottom - s_rect.top) / ((float) p_vout->i_height)))
301
factor_x = FixDiv(Long2Fix(s_rect.right - s_rect.left), Long2Fix(p_vout->i_width)) ;
303
factor_y = FixDiv(Long2Fix(s_rect.bottom - s_rect.top), Long2Fix(p_vout->i_height)) ;
305
SetIdentityMatrix(p_vout->p_sys->p_matrix) ;
306
ScaleMatrix( p_vout->p_sys->p_matrix, factor_x, factor_y, Long2Fix(0), Long2Fix(0) ) ;
309
static OSErr new_QTSequence( ImageSequence *i_seq, CGrafPtr p_qdport, ImageDescriptionHandle h_descr, MatrixRecordPtr p_matrix )
311
return DecompressSequenceBeginS(
317
NULL, //device to display (is set implicit via the qdPort)
320
0, //just do plain copying
321
NULL, //no mask region
322
codecFlagUseScreenBuffer,
323
codecLosslessQuality,
324
(DecompressorComponent) bestSpeedCodec
328
static int create_QTSequenceBestCodec( vout_thread_t *p_vout )
330
if ( p_vout->p_sys->osx_communication.p_qdport == nil)
332
p_vout->p_sys->c_codec = 'NONE' ;
336
SetPort( p_vout->p_sys->osx_communication.p_qdport ) ;
337
fillout_ScalingMatrix( p_vout ) ;
338
fillout_ImageDescription(
339
p_vout->p_sys->h_img_descr,
344
if ( !new_QTSequence(
345
&p_vout->p_sys->i_seq,
346
p_vout->p_sys->osx_communication.p_qdport,
347
p_vout->p_sys->h_img_descr,
348
p_vout->p_sys->p_matrix
351
p_vout->p_sys->c_codec = 'y420' ;
355
p_vout->p_sys->c_codec = 'NONE' ;
359
static void dispose_QTSequence( vout_thread_t *p_vout )
361
if (p_vout->p_sys->c_codec == 'NONE')
364
CDSequenceEnd( p_vout->p_sys->i_seq ) ;
365
switch (p_vout->p_sys->c_codec)
368
free( (void *)p_vout->p_sys->p_yuv2 ) ;
369
p_vout->p_sys->i_yuv2_size = 0 ;
374
p_vout->p_sys->c_codec = 'NONE' ;
377
static void convert_Y420_to_YUV2( picture_t *p_y420, yuv2_data_t *p_yuv2 )
379
unsigned int width = p_y420->i_width, height = p_y420->i_height ;
382
for( x=0; x < height; x++ )
384
for( y=0; y < (width/2); y++ )
386
p_yuv2[(width/2)*x + y] =
387
(p_y420->p_y[width*x + 2*y]) << 24 |
388
((p_y420->p_u[(width/2)*(x/2) + y] ^ 0x80) << 16) |
389
(p_y420->p_y[width*x + 2*y + 1] << 8) |
390
(p_y420->p_v[(width/2)*(x/2) + y] ^ 0x80) ;