Skip to content

Latest commit

 

History

History
330 lines (261 loc) · 9.82 KB

SDL_QuartzYUV.m

File metadata and controls

330 lines (261 loc) · 9.82 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2003 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
23
24
25
#include "SDL_QuartzVideo.h"
#include "SDL_QuartzWindow.h"
Feb 16, 2006
Feb 16, 2006
26
#include "../SDL_yuvfuncs.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#define yuv_idh (this->hidden->yuv_idh)
#define yuv_matrix (this->hidden->yuv_matrix)
#define yuv_codec (this->hidden->yuv_codec)
#define yuv_seq (this->hidden->yuv_seq)
#define yuv_pixmap (this->hidden->yuv_pixmap)
#define yuv_data (this->hidden->yuv_data)
#define yuv_width (this->hidden->yuv_width)
#define yuv_height (this->hidden->yuv_height)
#define yuv_port (this->hidden->yuv_port)
static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) {
return 0;
}
static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) {
;
}
Apr 22, 2006
Apr 22, 2006
50
static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) {
51
52
53
54
OSErr err;
CodecFlags flags;
Apr 22, 2006
Apr 22, 2006
55
if (dst->x != 0 || dst->y != 0) {
56
Apr 22, 2006
Apr 22, 2006
57
SDL_SetError ("Need a dst at (0,0)");
58
59
60
return -1;
}
Apr 22, 2006
Apr 22, 2006
61
if (dst->w != yuv_width || dst->h != yuv_height) {
62
63
64
Fixed scale_x, scale_y;
Apr 22, 2006
Apr 22, 2006
65
66
scale_x = FixDiv ( Long2Fix (dst->w), Long2Fix (overlay->w) );
scale_y = FixDiv ( Long2Fix (dst->h), Long2Fix (overlay->h) );
67
68
69
70
71
72
SetIdentityMatrix (yuv_matrix);
ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
SetDSequenceMatrix (yuv_seq, yuv_matrix);
Apr 22, 2006
Apr 22, 2006
73
74
yuv_width = dst->w;
yuv_height = dst->h;
75
76
77
78
79
80
81
82
83
84
85
}
if( ( err = DecompressSequenceFrameS(
yuv_seq,
(void*)yuv_pixmap,
sizeof (PlanarPixmapInfoYUV420),
codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
{
SDL_SetError ("DecompressSequenceFrameS failed");
}
Mar 15, 2006
Mar 15, 2006
86
return err != noErr;
87
88
89
90
91
92
93
}
static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
CDSequenceEnd (yuv_seq);
ExitMovies();
May 1, 2006
May 1, 2006
94
95
96
SDL_free (overlay->hwfuncs);
SDL_free (overlay->pitches);
SDL_free (overlay->pixels);
97
98
99
100
101
102
if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
[ qz_window close ];
qz_window = nil;
}
May 1, 2006
May 1, 2006
103
SDL_free (yuv_matrix);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
DisposeHandle ((Handle)yuv_idh);
}
/* check for 16 byte alignment, bail otherwise */
#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
/* align a byte offset, return how much to add to make it a multiple of 16 */
#define ALIGN(x) ((16 - (x & 15)) & 15)
SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
Uint32 format, SDL_Surface *display) {
Uint32 codec;
OSStatus err;
CGrafPtr port;
SDL_Overlay *overlay;
if (format == SDL_YV12_OVERLAY ||
format == SDL_IYUV_OVERLAY) {
codec = kYUV420CodecType;
}
else {
SDL_SetError ("Hardware: unsupported video format");
return NULL;
}
yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription));
if (yuv_idh == NULL) {
SDL_OutOfMemory();
return NULL;
}
May 1, 2006
May 1, 2006
137
yuv_matrix = (MatrixRecordPtr) SDL_malloc (sizeof(MatrixRecord));
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
if (yuv_matrix == NULL) {
SDL_OutOfMemory();
return NULL;
}
if ( EnterMovies() != noErr ) {
SDL_SetError ("Could not init QuickTime for YUV playback");
return NULL;
}
err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec);
if (err != noErr) {
SDL_SetError ("Could not find QuickTime codec for format");
return NULL;
}
if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
/*
Acceleration requires a window to be present.
A CGrafPtr that points to the screen isn't good enough
*/
NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
qz_window = [ [ SDL_QuartzWindow alloc ]
initWithContentRect:content
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered defer:NO ];
if (qz_window == nil) {
SDL_SetError ("Could not create the Cocoa window");
return NULL;
}
[ qz_window setContentView:[ [ NSQuickDrawView alloc ] init ] ];
[ qz_window setReleasedWhenClosed:YES ];
[ qz_window center ];
[ qz_window setAcceptsMouseMovedEvents:YES ];
[ qz_window setLevel:CGShieldingWindowLevel() ];
[ qz_window makeKeyAndOrderFront:nil ];
port = [ [ qz_window contentView ] qdPort ];
SetPort (port);
/*
BUG: would like to remove white flash when window kicks in
{
Rect r;
SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
PaintRect (&r);
QDFlushPortBuffer (port, nil);
}
*/
}
else {
port = [ window_view qdPort ];
SetPort (port);
}
SetIdentityMatrix (yuv_matrix);
HLock ((Handle)yuv_idh);
(**yuv_idh).idSize = sizeof(ImageDescription);
(**yuv_idh).cType = codec;
(**yuv_idh).version = 1;
(**yuv_idh).revisionLevel = 0;
(**yuv_idh).width = width;
(**yuv_idh).height = height;
(**yuv_idh).hRes = Long2Fix(72);
(**yuv_idh).vRes = Long2Fix(72);
(**yuv_idh).spatialQuality = codecLosslessQuality;
(**yuv_idh).frameCount = 1;
(**yuv_idh).clutID = -1;
(**yuv_idh).dataSize = 0;
(**yuv_idh).depth = 24;
HUnlock ((Handle)yuv_idh);
err = DecompressSequenceBeginS (
&yuv_seq,
yuv_idh,
NULL,
0,
port,
NULL,
NULL,
yuv_matrix,
0,
NULL,
codecFlagUseImageBuffer,
codecLosslessQuality,
yuv_codec);
if (err != noErr) {
SDL_SetError ("Error trying to start YUV codec.");
return NULL;
}
May 1, 2006
May 1, 2006
237
overlay = (SDL_Overlay*) SDL_malloc (sizeof(*overlay));
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
if (overlay == NULL) {
SDL_OutOfMemory();
return NULL;
}
overlay->format = format;
overlay->w = width;
overlay->h = height;
overlay->planes = 3;
overlay->hw_overlay = 1;
{
int offset;
Uint8 **pixels;
Uint16 *pitches;
int plane2, plane3;
if (format == SDL_IYUV_OVERLAY) {
plane2 = 1; /* Native codec format */
plane3 = 2;
}
else if (format == SDL_YV12_OVERLAY) {
/* switch the U and V planes */
plane2 = 2; /* U plane maps to plane 3 */
plane3 = 1; /* V plane maps to plane 2 */
}
else {
SDL_SetError("Unsupported YUV format");
return NULL;
}
May 1, 2006
May 1, 2006
270
271
pixels = (Uint8**) SDL_malloc (sizeof(*pixels) * 3);
pitches = (Uint16*) SDL_malloc (sizeof(*pitches) * 3);
272
273
274
275
276
if (pixels == NULL || pitches == NULL) {
SDL_OutOfMemory();
return NULL;
}
Sep 24, 2006
Sep 24, 2006
277
278
/* Fix: jc.bertin@free.fr
PlanarPixmapInfoYUV420 is a big-endian struct */
279
yuv_pixmap = (PlanarPixmapInfoYUV420*)
May 1, 2006
May 1, 2006
280
SDL_malloc (sizeof(PlanarPixmapInfoYUV420) +
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
(width * height * 2));
if (yuv_pixmap == NULL) {
SDL_OutOfMemory ();
return NULL;
}
/* CHECK_ALIGN(yuv_pixmap); */
offset = sizeof(PlanarPixmapInfoYUV420);
/* offset += ALIGN(offset); */
/* CHECK_ALIGN(offset); */
pixels[0] = (Uint8*)yuv_pixmap + offset;
/* CHECK_ALIGN(pixels[0]); */
pitches[0] = width;
Sep 24, 2006
Sep 24, 2006
296
297
yuv_pixmap->componentInfoY.offset = EndianS32_NtoB(offset);
yuv_pixmap->componentInfoY.rowBytes = EndianU32_NtoB(width);
298
299
300
301
offset += width * height;
pixels[plane2] = (Uint8*)yuv_pixmap + offset;
pitches[plane2] = width / 2;
Sep 24, 2006
Sep 24, 2006
302
303
yuv_pixmap->componentInfoCb.offset = EndianS32_NtoB(offset);
yuv_pixmap->componentInfoCb.rowBytes = EndianU32_NtoB(width / 2);
304
305
306
307
offset += (width * height / 4);
pixels[plane3] = (Uint8*)yuv_pixmap + offset;
pitches[plane3] = width / 2;
Sep 24, 2006
Sep 24, 2006
308
309
yuv_pixmap->componentInfoCr.offset = EndianS32_NtoB(offset);
yuv_pixmap->componentInfoCr.rowBytes = EndianU32_NtoB(width / 2);
310
311
312
313
314
overlay->pixels = pixels;
overlay->pitches = pitches;
}
May 1, 2006
May 1, 2006
315
overlay->hwfuncs = SDL_malloc (sizeof(*overlay->hwfuncs));
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
if (overlay->hwfuncs == NULL) {
SDL_OutOfMemory();
return NULL;
}
overlay->hwfuncs->Lock = QZ_LockYUV;
overlay->hwfuncs->Unlock = QZ_UnlockYUV;
overlay->hwfuncs->Display = QZ_DisplayYUV;
overlay->hwfuncs->FreeHW = QZ_FreeHWYUV;
yuv_width = overlay->w;
yuv_height = overlay->h;
return overlay;
}