~ubuntu-branches/ubuntu/trusty/psychtoolbox-3/trusty-proposed

« back to all changes in this revision

Viewing changes to PsychSourceGL/Source/Common/Screen/PsychMovieWritingSupportQuickTime.c

  • Committer: Package Import Robot
  • Author(s): Yaroslav Halchenko
  • Date: 2013-11-19 23:34:50 UTC
  • mfrom: (3.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20131119233450-f7nf92vb8qavjmk8
Tags: 3.0.11.20131017.dfsg1-3
Upload to unsable since fresh glew has arrived to sid!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
        Common/Screen/PsychMovieWritingSupportQuickTime.c
3
 
        
4
 
        PLATFORMS:      
5
 
        
6
 
                MacOS/X and MS-Windows, but only if GStreamer support is disabled.
7
 
                
8
 
                This is the movie editing and writing/creation engine based on the
9
 
                Apple QuickTime API. It works on Apple MacOS/X and MS-Windows.
10
 
 
11
 
        AUTHORS:
12
 
        
13
 
                Mario Kleiner           mk              mario.kleiner@tuebingen.mpg.de
14
 
 
15
 
        HISTORY:
16
 
        
17
 
        04/18/10                mk              Wrote it. 
18
 
        
19
 
        DESCRIPTION:
20
 
        
21
 
                Psychtoolbox functions for dealing with Quicktime movie editing. This implementation uses
22
 
                Quicktimes API's, therefore it works on Operating systems with Quicktime support,
23
 
                currently OS/X and Windows.
24
 
 
25
 
        NOTES:
26
 
 
27
 
*/
28
 
 
29
 
#include "Screen.h"
30
 
 
31
 
// No Quicktime support for GNU/Linux:
32
 
#if PSYCH_SYSTEM != PSYCH_LINUX
33
 
#ifndef PTB_USE_GSTREAMER
34
 
 
35
 
#if PSYCH_SYSTEM == PSYCH_OSX
36
 
#include <Quicktime/QuickTimeComponents.h>
37
 
#endif
38
 
 
39
 
#if PSYCH_SYSTEM == PSYCH_WINDOWS
40
 
#include <QTML.h>
41
 
#include <QuickTimeComponents.h>
42
 
#endif
43
 
 
44
 
// Forward declaration of internal helper function:
45
 
 
46
 
 
47
 
// Record which defines all state for a capture device:
48
 
typedef struct {
49
 
        Movie                                           Movie;
50
 
        Track                                           Track;
51
 
        Media                                           Media;
52
 
        FSSpec                                          File;
53
 
        short                                           ResRefNum;
54
 
        short                                           ResID;
55
 
        GWorldPtr                                       GWorld;
56
 
        PixMapHandle                            PixMap;
57
 
        CodecType                                       CodecType;
58
 
        CodecQ                                          CodecQuality;
59
 
        long                                            MaxComprSize;
60
 
        Handle                                          ComprDataHdl;
61
 
        Ptr                                                     ComprDataPtr;
62
 
        ImageDescriptionHandle          ImageDesc;
63
 
        CGrafPtr                                        SavedPort;
64
 
        GDHandle                                        SavedDevice;
65
 
        Rect                                            Rect;
66
 
        int                                                     height;
67
 
        int                                                     width;
68
 
        int                                                     padding;
69
 
} PsychMovieWriterRecordType;
70
 
 
71
 
static PsychMovieWriterRecordType moviewriterRecordBANK[PSYCH_MAX_MOVIEWRITERDEVICES];
72
 
static int moviewritercount = 0;
73
 
static psych_bool firsttime = TRUE;
74
 
 
75
 
void PsychMovieWritingInit(void)
76
 
{
77
 
        int i;
78
 
        
79
 
        for (i = 0; i < PSYCH_MAX_MOVIEWRITERDEVICES; i++) {
80
 
                memset(&(moviewriterRecordBANK[i]), 0, sizeof(PsychMovieWriterRecordType));
81
 
        }
82
 
        
83
 
        moviewritercount = 0;
84
 
        
85
 
        return;
86
 
}
87
 
 
88
 
void PsychDeleteAllMovieWriters(void)
89
 
{
90
 
        int i;
91
 
                
92
 
        for (i = 0; i < PSYCH_MAX_MOVIEWRITERDEVICES; i++) {
93
 
                if (moviewriterRecordBANK[i].Movie) PsychFinalizeNewMovieFile(i);
94
 
        }
95
 
}
96
 
 
97
 
void PsychExitMovieWriting(void)
98
 
{
99
 
        PsychDeleteAllMovieWriters();
100
 
    firsttime = TRUE;
101
 
        return;
102
 
}
103
 
 
104
 
PsychMovieWriterRecordType* PsychGetMovieWriter(int moviehandle, psych_bool unsafe)
105
 
{
106
 
        if (moviehandle < 0 || moviehandle >= PSYCH_MAX_MOVIEWRITERDEVICES) PsychErrorExitMsg(PsychError_user, "Invalid handle for moviewriter provided!");
107
 
        if (!unsafe && (NULL == moviewriterRecordBANK[moviehandle].Movie)) PsychErrorExitMsg(PsychError_user, "Invalid handle for moviewriter provided! No such writer open.");
108
 
        return(&(moviewriterRecordBANK[moviehandle]));
109
 
}
110
 
 
111
 
unsigned char*  PsychGetVideoFrameForMoviePtr(int moviehandle, unsigned int* twidth, unsigned int* theight)
112
 
{
113
 
        PsychMovieWriterRecordType* pwriterRec = PsychGetMovieWriter(moviehandle, FALSE);
114
 
        if (NULL == pwriterRec->PixMap) return(NULL);
115
 
 
116
 
        *twidth = pwriterRec->width;
117
 
        *theight = pwriterRec->height - pwriterRec->padding; // Hack hack pwriterRec->padding !
118
 
        return((unsigned char*) GetPixBaseAddr(pwriterRec->PixMap));
119
 
}
120
 
 
121
 
int PsychAddVideoFrameToMovie(int moviehandle, int frameDurationUnits, psych_bool isUpsideDown)
122
 
{
123
 
        PsychMovieWriterRecordType* pwriterRec = PsychGetMovieWriter(moviehandle, FALSE);
124
 
 
125
 
        OSErr                           myErr = noErr;
126
 
        int                                     x, y, w, h;
127
 
        unsigned char*          pixptr   = (unsigned char*) GetPixBaseAddr(pwriterRec->PixMap);
128
 
        unsigned int*           wordptr  = (unsigned int*) GetPixBaseAddr(pwriterRec->PixMap);
129
 
        unsigned int            *wordptr2, *wordptr1;
130
 
        unsigned int            dummy;
131
 
 
132
 
        if (NULL == pwriterRec->Media) return(0);
133
 
 
134
 
        if ((frameDurationUnits < 1) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING:In AddFrameToMovie: Negative or zero 'frameduration' %i units for moviehandle %i provided! Sounds like trouble ahead.\n", frameDurationUnits, moviehandle);
135
 
 
136
 
        // Draw testpattern: Disabled at compile-time by default:
137
 
        if (FALSE) {
138
 
                for (y = 0; y < pwriterRec->height; y++) {
139
 
                        for (x = 0; x < pwriterRec->width; x++) {
140
 
                                *(pixptr++) = (unsigned char) 255; // alpha
141
 
                                *(pixptr++) = (unsigned char) y; // Red
142
 
                                *(pixptr++) = (unsigned char) x; // Green
143
 
                                *(pixptr++) = (unsigned char) 0; // Blue
144
 
                        }
145
 
                }
146
 
        }
147
 
        
148
 
        // Imagebuffer is upside-down: Need to flip it vertically:
149
 
        if (isUpsideDown) {
150
 
                h = pwriterRec->height - pwriterRec->padding; // Hack pwriterRec->padding !
151
 
                w = pwriterRec->width;
152
 
                wordptr1 = wordptr;
153
 
                for (y = 0; y < h/2; y++) {
154
 
                        wordptr2 = wordptr;
155
 
                        wordptr2 += ((h - 1 - y) * w);
156
 
                        for (x = 0; x < w; x++) {
157
 
                                dummy = *wordptr1;
158
 
                                *(wordptr1++) = *wordptr2;
159
 
                                *(wordptr2++) = dummy;                           
160
 
                        }
161
 
                }
162
 
        }
163
 
        
164
 
        // Apply codec to compress image:
165
 
        myErr = CompressImage(  pwriterRec->PixMap, 
166
 
                                                        &pwriterRec->Rect, 
167
 
                                                        pwriterRec->CodecQuality,
168
 
                                                        pwriterRec->CodecType,
169
 
                                                        pwriterRec->ImageDesc, 
170
 
                                                        pwriterRec->ComprDataPtr);
171
 
        if (myErr != noErr) {
172
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In AddFrameToMovie: Video compression on current frame for moviehandle %i failed [CompessImage() returned QT error code %i]!\n", moviehandle, (int) myErr);
173
 
                goto bail;
174
 
        }
175
 
        
176
 
        // Add encoded buffer to movie:
177
 
        myErr = AddMediaSample( pwriterRec->Media, 
178
 
                                                        pwriterRec->ComprDataHdl,
179
 
                                                        0,                                                              // no offset in data
180
 
                                                        (**(pwriterRec->ImageDesc)).dataSize, 
181
 
                                                        frameDurationUnits,                     // frame duration
182
 
                                                        (SampleDescriptionHandle) pwriterRec->ImageDesc, 
183
 
                                                        1,                                                              // one sample
184
 
                                                        0,                                                              // self-contained samples
185
 
                                                        NULL);
186
 
        if (myErr != noErr) {
187
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In AddFrameToMovie: Adding current frame to moviehandle %i failed [AddMediaSample() returned QT error code %i]!\n", moviehandle, (int) myErr);
188
 
                goto bail;
189
 
        }
190
 
 
191
 
        if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG:In AddFrameToMovie: Added new videoframe with %i units duration and upsidedown = %i to moviehandle %i.\n", frameDurationUnits, (int) isUpsideDown, moviehandle);
192
 
 
193
 
bail:
194
 
        return(myErr);
195
 
}
196
 
 
197
 
int PsychCreateNewMovieFile(char* moviefile, int width, int height, double framerate, char* movieoptions)
198
 
{
199
 
        PsychMovieWriterRecordType* pwriterRec = NULL;
200
 
        int                                             moviehandle = 0;
201
 
        long                                    myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
202
 
        OSErr                                   myErr = noErr;
203
 
        char*                                   poption;
204
 
        int                                             dummyInt;
205
 
        float                                   dummyFloat;
206
 
        char                                    myfourcc[4];
207
 
 
208
 
        // Still capacity left?
209
 
        if (moviewritercount >= PSYCH_MAX_MOVIEWRITERDEVICES) PsychErrorExitMsg(PsychError_user, "Maximum number of movie writers exceeded. Please close some first!");
210
 
 
211
 
        // Find first free (i.e., NULL) slot and assign moviehandle:
212
 
        while ((pwriterRec = PsychGetMovieWriter(moviehandle, TRUE)) && pwriterRec->Movie) moviehandle++;
213
 
 
214
 
        if (firsttime) {
215
 
#if PSYCH_SYSTEM == PSYCH_WINDOWS
216
 
        // Initialize Quicktime for Windows compatibility layer: This will fail if
217
 
        // QT isn't installed on the Windows machine...
218
 
        myErr = InitializeQTML(0);
219
 
        if (myErr!=noErr) {
220
 
            printf("PTB-ERROR: Quicktime Media Layer initialization failed with error code %i in call to InitializeQTML(0): Quicktime not properly installed?!?", (int) myErr);
221
 
            PsychErrorExitMsg(PsychError_system, "Quicktime Media Layer initialization failed. Quicktime not properly installed or not installed at all?!?");
222
 
        }
223
 
#endif
224
 
 
225
 
        // Initialize Quicktime-Subsystem:
226
 
        myErr = EnterMovies();
227
 
        if (myErr!=noErr) {
228
 
            printf("PTB-ERROR: Quicktime initialization failed with error code %i in call to EnterMovies().", (int) myErr);
229
 
            PsychErrorExitMsg(PsychError_system, "Quicktime initialization in EnterMovies() failed!!!");
230
 
        }
231
 
                firsttime = FALSE;
232
 
        }
233
 
 
234
 
        // Translate char string with movie name to FSSpec:
235
 
        NativePathNameToFSSpec(moviefile, &pwriterRec->File, 0);
236
 
 
237
 
        pwriterRec->CodecType = kH264CodecType;
238
 
        pwriterRec->CodecQuality = codecNormalQuality; 
239
 
        pwriterRec->ResID = movieInDataForkResID;       
240
 
        pwriterRec->height = height;
241
 
        pwriterRec->width = width;
242
 
        pwriterRec->padding = (PSYCH_SYSTEM == PSYCH_OSX) ? 1 : 0;
243
 
        
244
 
        // Assign numeric 32-bit FOURCC equivalent code to select codec:
245
 
        // This is optional. We default to kH264CodecType:
246
 
        if ((poption = strstr(movieoptions, "CodecFOURCCId="))) {
247
 
                if (sscanf(poption, "CodecFOURCCId=%i", &dummyInt) == 1) {
248
 
                        pwriterRec->CodecType = (CodecType) dummyInt;
249
 
                        if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Codec with FOURCC numeric id %i selected for encoding of movie %i [%s].\n", dummyInt, moviehandle, moviefile);
250
 
                }
251
 
                else PsychErrorExitMsg(PsychError_user, "Invalid CodecFOURCCId= parameter provided in movieoptions parameter. Parse error!");
252
 
        }
253
 
 
254
 
        // Assign 4 character string FOURCC code to select codec:
255
 
        if ((poption = strstr(movieoptions, "CodecFOURCC="))) {
256
 
                if (sscanf(poption, "CodecFOURCC=%c%c%c%c", &myfourcc[3], &myfourcc[2], &myfourcc[1], &myfourcc[0]) == 4) {
257
 
                        pwriterRec->CodecType = (CodecType) (*((unsigned int*) (&myfourcc[0])));
258
 
                        if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Codec with FOURCC '%c%c%c%c' = numeric id %i selected for encoding of movie %i [%s].\n", myfourcc[3], myfourcc[2], myfourcc[1], myfourcc[0], (int) pwriterRec->CodecType, moviehandle, moviefile);
259
 
                }
260
 
                else PsychErrorExitMsg(PsychError_user, "Invalid CodecFOURCC= parameter provided in movieoptions parameter. Must be exactly 4 characters! Parse error!");
261
 
        }
262
 
 
263
 
        // Assign numeric encoding quality level:
264
 
        // This is optional. We default to "normal quality":
265
 
        if ((poption = strstr(movieoptions, "EncodingQuality="))) {
266
 
                if (sscanf(poption, "EncodingQuality=%f", &dummyFloat) == 1) {
267
 
                        // Map floating point quality level between 0.0 and 1.0 to 10 discrete levels:
268
 
                        dummyInt = (int)(10.0 * dummyFloat + 0.5);
269
 
                        dummyInt = (dummyInt < 0)  ?  0 : dummyInt;
270
 
                        dummyInt = (dummyInt > 10) ? 10 : dummyInt;
271
 
                        
272
 
                        // Assign one of Quicktime's 6 code quality setting to the 10 levels:
273
 
                        switch(dummyInt) {
274
 
                                case 0:
275
 
                                        pwriterRec->CodecQuality = codecMinQuality;
276
 
                                break;
277
 
 
278
 
                                case 1:
279
 
                                        pwriterRec->CodecQuality = codecMinQuality;
280
 
                                break;
281
 
 
282
 
                                case 2:
283
 
                                        pwriterRec->CodecQuality = codecLowQuality;
284
 
                                break;
285
 
 
286
 
                                case 3:
287
 
                                        pwriterRec->CodecQuality = codecLowQuality;
288
 
                                break;
289
 
 
290
 
                                case 4:
291
 
                                        pwriterRec->CodecQuality = codecNormalQuality;
292
 
                                break;
293
 
 
294
 
                                case 5:
295
 
                                        pwriterRec->CodecQuality = codecNormalQuality;
296
 
                                break;
297
 
 
298
 
                                case 6:
299
 
                                        pwriterRec->CodecQuality = codecNormalQuality;
300
 
                                break;
301
 
 
302
 
                                case 7:
303
 
                                        pwriterRec->CodecQuality = codecHighQuality;
304
 
                                break;
305
 
 
306
 
                                case 8:
307
 
                                        pwriterRec->CodecQuality = codecHighQuality;
308
 
                                break;
309
 
 
310
 
                                case 9:
311
 
                                        pwriterRec->CodecQuality = codecMaxQuality;
312
 
                                break;
313
 
 
314
 
                                case 10:
315
 
                                        pwriterRec->CodecQuality = codecLosslessQuality;
316
 
                                break;
317
 
                                
318
 
                        }
319
 
                        
320
 
                        if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Encoding quality level %i selected for encoding of movie %i [%s].\n", dummyInt, moviehandle, moviefile);
321
 
                }
322
 
                else PsychErrorExitMsg(PsychError_user, "Invalid EncodingQuality= parameter provided in movieoptions parameter. Parse error!");
323
 
        }
324
 
 
325
 
        // Check for valid parameters. Also warn if some parameters are borderline for certain codecs:
326
 
        if ((framerate < 1) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING:In CreateMovie: Negative or zero 'framerate' %f units for moviehandle %i provided! Sounds like trouble ahead.\n", (float) framerate, moviehandle);
327
 
        if (width < 1) PsychErrorExitMsg(PsychError_user, "In CreateMovie: Invalid zero or negative 'width' for video frame size provided!");
328
 
        if ((width < 4) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING:In CreateMovie: 'width' of %i pixels for moviehandle %i provided! Some video codecs may malfunction with such a small width.\n", width, moviehandle);
329
 
        if ((width % 4 != 0) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING:In CreateMovie: 'width' of %i pixels for moviehandle %i provided! Some video codecs may malfunction with a width which is not a multiple of 4 or 16.\n", width, moviehandle);
330
 
        if (height < 1) PsychErrorExitMsg(PsychError_user, "In CreateMovie: Invalid zero or negative 'height' for video frame size provided!");
331
 
        if ((height < 4) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING:In CreateMovie: 'height' of %i pixels for moviehandle %i provided! Some video codecs may malfunction with such a small height.\n", height, moviehandle);
332
 
 
333
 
        // Create a movie file for the destination movie:
334
 
        myErr = CreateMovieFile(&pwriterRec->File, FOUR_CHAR_CODE('TVOD'), smCurrentScript, myFlags, &pwriterRec->ResRefNum, &pwriterRec->Movie);
335
 
        if (myErr != noErr) {
336
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [CreateMovieFile() returned QT error code %i]!\n", moviehandle, moviefile, (int) myErr);
337
 
                if ((myErr == -47) && (PsychPrefStateGet_Verbosity() > 0)) printf("PTB-ERROR:In CreateMovie: Do you have this file open or highlighted in some other application like Quicktime player or Finder?!?\n");
338
 
                goto bail;
339
 
        }
340
 
 
341
 
        // Create the movie track and media:
342
 
        pwriterRec->Track = NewMovieTrack(pwriterRec->Movie, FixRatio(width, 1), FixRatio(height, 1), kNoVolume);
343
 
        myErr = GetMoviesError();
344
 
        if (myErr != noErr) {
345
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating track with videoframes of size %i x %i pixels for movie file %i [%s] failed [NewMovieTrack() returned QT error code %i]!\n", width, height, moviehandle, moviefile, (int) myErr);
346
 
                goto bail;
347
 
        }
348
 
                
349
 
        pwriterRec->Media = NewTrackMedia(pwriterRec->Track, VideoMediaType, (int) framerate, NULL, 0);
350
 
        myErr = GetMoviesError();
351
 
        if (myErr != noErr) {
352
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating video media stream with framerate %i for file with handle %i [%s] failed [NewTrackMedia() returned QT error code %i]!\n", (int) framerate, moviehandle, moviefile, (int) myErr);
353
 
                goto bail;
354
 
        }
355
 
 
356
 
        // Create the media samples:
357
 
        myErr = BeginMediaEdits(pwriterRec->Media);
358
 
        if (myErr != noErr) {
359
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [BeginMediaEdits() returned QT error code %i]!\n", moviehandle, moviefile, (int) myErr);
360
 
                goto bail;
361
 
        }
362
 
 
363
 
        // Create a GWorld as target with a pixedepth of 32 bpp:
364
 
        // Hack hack pwriterRec->padding!!
365
 
        MacSetRect(&pwriterRec->Rect, 0, 0, width - pwriterRec->padding, height - pwriterRec->padding);
366
 
        myErr = NewGWorld(&pwriterRec->GWorld, 32, &pwriterRec->Rect, NULL, NULL, (GWorldFlags)0);
367
 
        if (myErr != noErr) {
368
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [NewGWorld(rectsize = %i,%i and padding %i) returned QT error code %i]!\n", moviehandle, moviefile, width - pwriterRec->padding, height - pwriterRec->padding, pwriterRec->padding, (int) myErr);
369
 
                goto bail;
370
 
        }
371
 
 
372
 
        pwriterRec->PixMap = GetGWorldPixMap(pwriterRec->GWorld);
373
 
        if (pwriterRec->PixMap == NULL) {
374
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [GetGWorldPixMap() returned NULL-Ptr]!\n", moviehandle, moviefile);
375
 
                goto bail;
376
 
        }
377
 
 
378
 
        LockPixels(pwriterRec->PixMap);
379
 
        myErr = GetMaxCompressionSize(  pwriterRec->PixMap,
380
 
                                                                        &pwriterRec->Rect, 
381
 
                                                                        0,                                                      // let ICM choose depth
382
 
                                                                        pwriterRec->CodecQuality, 
383
 
                                                                        pwriterRec->CodecType, 
384
 
                                                                        (CompressorComponent) anyCodec,
385
 
                                                                        &pwriterRec->MaxComprSize);
386
 
        if (myErr != noErr) {
387
 
                if (PsychPrefStateGet_Verbosity() > 0) {
388
 
                        printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [GetMaxCompressionSize() returned QT error code %i]!\n", moviehandle, moviefile, (int) myErr);
389
 
                        if (myErr == noCodecErr) printf("PTB-ERROR:In CreateMovie: The system doesn't know or support the requested type of video movie codec.\n");
390
 
                }
391
 
                goto bail;
392
 
        }
393
 
 
394
 
        pwriterRec->ComprDataHdl = NewHandle(pwriterRec->MaxComprSize);
395
 
        if (pwriterRec->ComprDataHdl == NULL) {
396
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [NewHandle(for compressor) returned NULL-Ptr]!\n", moviehandle, moviefile);
397
 
                goto bail;
398
 
        }
399
 
 
400
 
        HLockHi(pwriterRec->ComprDataHdl);
401
 
        pwriterRec->ComprDataPtr = *(pwriterRec->ComprDataHdl);
402
 
 
403
 
        pwriterRec->ImageDesc = (ImageDescriptionHandle)NewHandle(4);
404
 
        if (pwriterRec->ImageDesc == NULL) {
405
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In CreateMovie: Creating movie file with handle %i [%s] failed [NewHandle(4) returned NULL-Ptr]!\n", moviehandle, moviefile);
406
 
                goto bail;
407
 
        }
408
 
 
409
 
        SetGWorld(pwriterRec->GWorld, NULL);
410
 
        
411
 
        // Increment count of open movie writers:
412
 
        moviewritercount++;
413
 
        
414
 
        if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Moviehandle %i successfully opened for movie writing into file '%s'.\n", moviehandle, moviefile);
415
 
 
416
 
        // Return new handle:
417
 
        return(moviehandle);
418
 
 
419
 
bail:
420
 
 
421
 
        if (pwriterRec->ComprDataHdl != NULL)
422
 
                DisposeHandle(pwriterRec->ComprDataHdl);
423
 
 
424
 
        if (pwriterRec->GWorld != NULL)
425
 
                DisposeGWorld(pwriterRec->GWorld);
426
 
                
427
 
        if (pwriterRec->ResRefNum != 0)
428
 
                CloseMovieFile(pwriterRec->ResRefNum);
429
 
 
430
 
        if (pwriterRec->Movie != NULL)
431
 
                DisposeMovie(pwriterRec->Movie);
432
 
 
433
 
        pwriterRec->Movie = NULL;
434
 
        pwriterRec->Track = NULL;
435
 
        pwriterRec->Media = NULL;
436
 
        pwriterRec->ResRefNum = 0;
437
 
        pwriterRec->GWorld = NULL;
438
 
        pwriterRec->PixMap = NULL;
439
 
        pwriterRec->MaxComprSize = 0L;
440
 
        pwriterRec->ComprDataHdl = NULL;
441
 
        pwriterRec->ComprDataPtr = NULL;
442
 
        pwriterRec->ImageDesc = NULL;
443
 
        pwriterRec->SavedPort = NULL;
444
 
        pwriterRec->SavedDevice = NULL;
445
 
 
446
 
        // Return failure:
447
 
        return(-1);
448
 
}
449
 
 
450
 
int PsychFinalizeNewMovieFile(int movieHandle)
451
 
{
452
 
        OSErr                                   myErr = noErr;
453
 
 
454
 
        PsychMovieWriterRecordType* pwriterRec = PsychGetMovieWriter(movieHandle, FALSE);
455
 
 
456
 
        if (NULL == pwriterRec->Media) return(0);
457
 
 
458
 
        myErr = EndMediaEdits(pwriterRec->Media);
459
 
        if (myErr != noErr) {
460
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In FinalizeMovie: Finalizing/Closing movie file with handle %i failed [EndMediaEdits() returned QT error code %i]!\n", movieHandle, (int) myErr);
461
 
                goto bail;
462
 
        }
463
 
        
464
 
        // add the media to the track
465
 
        myErr = InsertMediaIntoTrack(pwriterRec->Track, 0, 0, GetMediaDuration(pwriterRec->Media), fixed1);
466
 
        if (myErr != noErr) {
467
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In FinalizeMovie: Finalizing/Closing movie file with handle %i failed [InsertMediaIntoTrack() returned QT error code %i]!\n", movieHandle, (int) myErr);
468
 
                goto bail;
469
 
        }
470
 
        
471
 
        // add the movie atom to the movie file
472
 
        myErr = AddMovieResource(pwriterRec->Movie, pwriterRec->ResRefNum, &pwriterRec->ResID, NULL);
473
 
        if (myErr != noErr) {
474
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In FinalizeMovie: Finalizing/Closing movie file with handle %i failed [AddMovieResource() returned QT error code %i]!\n", movieHandle, (int) myErr);
475
 
                goto bail;
476
 
        }
477
 
 
478
 
bail:
479
 
        if (pwriterRec->ImageDesc != NULL)
480
 
                DisposeHandle((Handle)pwriterRec->ImageDesc);
481
 
 
482
 
        if (pwriterRec->ComprDataHdl != NULL)
483
 
                DisposeHandle(pwriterRec->ComprDataHdl);
484
 
 
485
 
        if (pwriterRec->GWorld != NULL)
486
 
                DisposeGWorld(pwriterRec->GWorld);
487
 
 
488
 
        if (pwriterRec->ResRefNum != 0)
489
 
                CloseMovieFile(pwriterRec->ResRefNum);
490
 
 
491
 
        if (pwriterRec->Movie != NULL)
492
 
                DisposeMovie(pwriterRec->Movie);
493
 
 
494
 
        myErr = GetMoviesError();
495
 
        if (myErr != noErr) {
496
 
                if (PsychPrefStateGet_Verbosity() > 0) printf("PTB-ERROR:In FinalizeMovie: Finalizing/Closing movie file with handle %i failed [CloseMovieFile() or DisposeMovie() returned QT error code %i]!\n", movieHandle, (int) myErr);
497
 
        }
498
 
 
499
 
        pwriterRec->Movie = NULL;
500
 
        pwriterRec->Track = NULL;
501
 
        pwriterRec->Media = NULL;
502
 
        pwriterRec->ResRefNum = 0;
503
 
        pwriterRec->GWorld = NULL;
504
 
        pwriterRec->PixMap = NULL;
505
 
        pwriterRec->MaxComprSize = 0L;
506
 
        pwriterRec->ComprDataHdl = NULL;
507
 
        pwriterRec->ComprDataPtr = NULL;
508
 
        pwriterRec->ImageDesc = NULL;
509
 
        pwriterRec->SavedPort = NULL;
510
 
        pwriterRec->SavedDevice = NULL;
511
 
        
512
 
        // Decrement count of active writers:
513
 
        moviewritercount--;
514
 
 
515
 
        // Return success/fail status:
516
 
        if ((myErr == noErr) && (PsychPrefStateGet_Verbosity() > 3)) printf("PTB-INFO: Moviehandle %i successfully closed and movie written to filesystem.\n", movieHandle);
517
 
        return(myErr == 0);
518
 
}
519
 
 
520
 
psych_bool PsychAddAudioBufferToMovie(int moviehandle, unsigned int nrChannels, unsigned int nrSamples, double* buffer)
521
 
{
522
 
    PsychErrorExitMsg(PsychError_unimplemented, "Sorry, storing audio tracks in movies is not supported by the Quicktime based movie writing functions.");
523
 
    return(0);
524
 
}
525
 
 
526
 
// End of routines.
527
 
#endif
528
 
#endif