aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m')
-rw-r--r--distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m330
1 files changed, 330 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m b/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m
new file mode 100644
index 0000000..acb3d94
--- /dev/null
+++ b/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzYUV.m
@@ -0,0 +1,330 @@
+/*
+ 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
+*/
+#include "SDL_config.h"
+
+#include "SDL_QuartzVideo.h"
+#include "SDL_QuartzWindow.h"
+#include "../SDL_yuvfuncs.h"
+
+
+#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) {
+
+ ;
+}
+
+static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) {
+
+ OSErr err;
+ CodecFlags flags;
+
+ if (dst->x != 0 || dst->y != 0) {
+
+ SDL_SetError ("Need a dst at (0,0)");
+ return -1;
+ }
+
+ if (dst->w != yuv_width || dst->h != yuv_height) {
+
+ Fixed scale_x, scale_y;
+
+ scale_x = FixDiv ( Long2Fix (dst->w), Long2Fix (overlay->w) );
+ scale_y = FixDiv ( Long2Fix (dst->h), Long2Fix (overlay->h) );
+
+ SetIdentityMatrix (yuv_matrix);
+ ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
+
+ SetDSequenceMatrix (yuv_seq, yuv_matrix);
+
+ yuv_width = dst->w;
+ yuv_height = dst->h;
+ }
+
+ if( ( err = DecompressSequenceFrameS(
+ yuv_seq,
+ (void*)yuv_pixmap,
+ sizeof (PlanarPixmapInfoYUV420),
+ codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
+ {
+ SDL_SetError ("DecompressSequenceFrameS failed");
+ }
+
+ return err != noErr;
+}
+
+static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
+
+ CDSequenceEnd (yuv_seq);
+ ExitMovies();
+
+ SDL_free (overlay->hwfuncs);
+ SDL_free (overlay->pitches);
+ SDL_free (overlay->pixels);
+
+ if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
+ [ qz_window close ];
+ qz_window = nil;
+ }
+
+ SDL_free (yuv_matrix);
+ 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;
+ }
+
+ yuv_matrix = (MatrixRecordPtr) SDL_malloc (sizeof(MatrixRecord));
+ 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;
+ }
+
+ overlay = (SDL_Overlay*) SDL_malloc (sizeof(*overlay));
+ 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;
+ }
+
+ pixels = (Uint8**) SDL_malloc (sizeof(*pixels) * 3);
+ pitches = (Uint16*) SDL_malloc (sizeof(*pitches) * 3);
+ if (pixels == NULL || pitches == NULL) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ /* Fix: jc.bertin@free.fr
+ PlanarPixmapInfoYUV420 is a big-endian struct */
+ yuv_pixmap = (PlanarPixmapInfoYUV420*)
+ SDL_malloc (sizeof(PlanarPixmapInfoYUV420) +
+ (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;
+ yuv_pixmap->componentInfoY.offset = EndianS32_NtoB(offset);
+ yuv_pixmap->componentInfoY.rowBytes = EndianU32_NtoB(width);
+
+ offset += width * height;
+ pixels[plane2] = (Uint8*)yuv_pixmap + offset;
+ pitches[plane2] = width / 2;
+ yuv_pixmap->componentInfoCb.offset = EndianS32_NtoB(offset);
+ yuv_pixmap->componentInfoCb.rowBytes = EndianU32_NtoB(width / 2);
+
+ offset += (width * height / 4);
+ pixels[plane3] = (Uint8*)yuv_pixmap + offset;
+ pitches[plane3] = width / 2;
+ yuv_pixmap->componentInfoCr.offset = EndianS32_NtoB(offset);
+ yuv_pixmap->componentInfoCr.rowBytes = EndianU32_NtoB(width / 2);
+
+ overlay->pixels = pixels;
+ overlay->pitches = pitches;
+ }
+
+ overlay->hwfuncs = SDL_malloc (sizeof(*overlay->hwfuncs));
+ 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;
+}