146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2003  Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Library General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Library General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Library General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_QuartzVideo.h"
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_QuartzWindow.h"
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_yuvfuncs.h"
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_idh (this->hidden->yuv_idh)
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_matrix (this->hidden->yuv_matrix)
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_codec (this->hidden->yuv_codec)
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_seq (this->hidden->yuv_seq)
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_pixmap (this->hidden->yuv_pixmap)
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_data (this->hidden->yuv_data)
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_width (this->hidden->yuv_width)
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_height (this->hidden->yuv_height)
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define yuv_port (this->hidden->yuv_port)
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int QZ_LockYUV (_THIS, SDL_Overlay *overlay) {
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return 0;
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) {
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ;
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) {
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    OSErr err;
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CodecFlags flags;
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (dst->x != 0 || dst->y != 0) {
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("Need a dst at (0,0)");
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return -1;
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (dst->w != yuv_width || dst->h != yuv_height) {
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Fixed scale_x, scale_y;
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        scale_x = FixDiv ( Long2Fix (dst->w), Long2Fix (overlay->w) );
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        scale_y = FixDiv ( Long2Fix (dst->h), Long2Fix (overlay->h) );
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SetIdentityMatrix (yuv_matrix);
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SetDSequenceMatrix (yuv_seq, yuv_matrix);
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_width = dst->w;
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_height = dst->h;
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if( ( err = DecompressSequenceFrameS(
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         yuv_seq,
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         (void*)yuv_pixmap,
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         sizeof (PlanarPixmapInfoYUV420),
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("DecompressSequenceFrameS failed");
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return err != noErr;
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CDSequenceEnd (yuv_seq);
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    ExitMovies();
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free (overlay->hwfuncs);
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free (overlay->pitches);
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free (overlay->pixels);
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window close ];
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        qz_window = nil;
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free (yuv_matrix);
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    DisposeHandle ((Handle)yuv_idh);
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* check for 16 byte alignment, bail otherwise */
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* align a byte offset, return how much to add to make it a multiple of 16 */
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ALIGN(x) ((16 - (x & 15)) & 15)
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11346be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                         Uint32 format, SDL_Surface *display) {
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Uint32 codec;
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    OSStatus err;
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    CGrafPtr port;
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_Overlay *overlay;
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (format == SDL_YV12_OVERLAY ||
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        format == SDL_IYUV_OVERLAY) {
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        codec = kYUV420CodecType;
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("Hardware: unsupported video format");
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription));
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (yuv_idh == NULL) {
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_OutOfMemory();
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    yuv_matrix = (MatrixRecordPtr) SDL_malloc (sizeof(MatrixRecord));
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (yuv_matrix == NULL) {
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_OutOfMemory();
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( EnterMovies() != noErr ) {
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("Could not init QuickTime for YUV playback");
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec);
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (err != noErr) {
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("Could not find QuickTime codec for format");
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /*
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          Acceleration requires a window to be present.
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner          A CGrafPtr that points to the screen isn't good enough
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        */
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        qz_window = [ [ SDL_QuartzWindow alloc ]
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                            initWithContentRect:content
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                            styleMask:NSBorderlessWindowMask
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                            backing:NSBackingStoreBuffered defer:NO ];
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (qz_window == nil) {
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_SetError ("Could not create the Cocoa window");
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            return NULL;
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window setContentView:[ [ NSQuickDrawView alloc ] init ] ];
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window setReleasedWhenClosed:YES ];
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window center ];
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window setAcceptsMouseMovedEvents:YES ];
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window setLevel:CGShieldingWindowLevel() ];
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        [ qz_window makeKeyAndOrderFront:nil ];
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        port = [ [ qz_window contentView ] qdPort ];
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SetPort (port);
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /*
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            BUG: would like to remove white flash when window kicks in
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            {
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                Rect r;
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                PaintRect (&r);
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                QDFlushPortBuffer (port, nil);
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            }
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        */
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    else {
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        port = [ window_view qdPort ];
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SetPort (port);
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SetIdentityMatrix (yuv_matrix);
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    HLock ((Handle)yuv_idh);
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).idSize = sizeof(ImageDescription);
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).cType  = codec;
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).version = 1;
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).revisionLevel = 0;
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).width = width;
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).height = height;
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).hRes = Long2Fix(72);
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).vRes = Long2Fix(72);
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).spatialQuality = codecLosslessQuality;
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).frameCount = 1;
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).clutID = -1;
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).dataSize = 0;
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    (**yuv_idh).depth = 24;
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    HUnlock ((Handle)yuv_idh);
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    err = DecompressSequenceBeginS (
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    &yuv_seq,
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    yuv_idh,
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    NULL,
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    0,
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    port,
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    NULL,
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    NULL,
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    yuv_matrix,
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    0,
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    NULL,
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    codecFlagUseImageBuffer,
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    codecLosslessQuality,
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                                    yuv_codec);
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (err != noErr) {
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_SetError ("Error trying to start YUV codec.");
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay = (SDL_Overlay*) SDL_malloc (sizeof(*overlay));
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (overlay == NULL) {
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_OutOfMemory();
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->format      = format;
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->w           = width;
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->h           = height;
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->planes      = 3;
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hw_overlay  = 1;
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    {
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int      offset;
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint8  **pixels;
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        Uint16  *pitches;
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        int      plane2, plane3;
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (format == SDL_IYUV_OVERLAY) {
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            plane2 = 1; /* Native codec format */
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            plane3 = 2;
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else if (format == SDL_YV12_OVERLAY) {
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            /* switch the U and V planes */
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            plane2 = 2; /* U plane maps to plane 3 */
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            plane3 = 1; /* V plane maps to plane 2 */
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        else {
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_SetError("Unsupported YUV format");
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            return NULL;
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pixels = (Uint8**) SDL_malloc (sizeof(*pixels) * 3);
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pitches = (Uint16*) SDL_malloc (sizeof(*pitches) * 3);
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (pixels == NULL || pitches == NULL) {
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_OutOfMemory();
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            return NULL;
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* Fix: jc.bertin@free.fr
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner           PlanarPixmapInfoYUV420 is a big-endian struct */
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap = (PlanarPixmapInfoYUV420*)
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_malloc (sizeof(PlanarPixmapInfoYUV420) +
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                    (width * height * 2));
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if (yuv_pixmap == NULL) {
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_OutOfMemory ();
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            return NULL;
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* CHECK_ALIGN(yuv_pixmap); */
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        offset  = sizeof(PlanarPixmapInfoYUV420);
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* offset += ALIGN(offset); */
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* CHECK_ALIGN(offset); */
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pixels[0] = (Uint8*)yuv_pixmap + offset;
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        /* CHECK_ALIGN(pixels[0]); */
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pitches[0] = width;
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoY.offset = EndianS32_NtoB(offset);
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoY.rowBytes = EndianU32_NtoB(width);
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        offset += width * height;
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pixels[plane2] = (Uint8*)yuv_pixmap + offset;
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pitches[plane2] = width / 2;
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoCb.offset = EndianS32_NtoB(offset);
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoCb.rowBytes = EndianU32_NtoB(width / 2);
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        offset += (width * height / 4);
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pixels[plane3] = (Uint8*)yuv_pixmap + offset;
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        pitches[plane3] = width / 2;
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoCr.offset = EndianS32_NtoB(offset);
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        yuv_pixmap->componentInfoCr.rowBytes = EndianU32_NtoB(width / 2);
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        overlay->pixels = pixels;
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        overlay->pitches = pitches;
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hwfuncs = SDL_malloc (sizeof(*overlay->hwfuncs));
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (overlay->hwfuncs == NULL) {
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_OutOfMemory();
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return NULL;
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hwfuncs->Lock    = QZ_LockYUV;
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hwfuncs->Unlock  = QZ_UnlockYUV;
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hwfuncs->Display = QZ_DisplayYUV;
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    overlay->hwfuncs->FreeHW  = QZ_FreeHWYUV;
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    yuv_width = overlay->w;
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    yuv_height = overlay->h;
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return overlay;
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
331