File: PsychMovieSupport.c

package info (click to toggle)
psychtoolbox-3 3.0.9%2Bsvn2579.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 63,408 kB
  • sloc: ansic: 73,310; cpp: 11,139; objc: 3,129; sh: 1,669; python: 382; php: 272; makefile: 172; java: 113
file content (410 lines) | stat: -rwxr-xr-x 13,160 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
137
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
237
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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/*
	PsychSourceGL/Source/Common/Screen/PsychMovieSupport.c
	
	PLATFORMS:	
	
		All.
				
	AUTHORS:
	
		Mario Kleiner           mk              mario.kleiner@tuebingen.mpg.de

	HISTORY:
	
        DESCRIPTION:
	
		Psychtoolbox functions for dealing with movies.

		This is the master dispatcher. Function herein get called by
		other parts of Psychtoolbox, most notably the SCREENxxx functions
		for movie playback. It dispatches into either the QuickTime based
		or GStreamer based implementations of the movie playback functions,
		depending on OS/Availability/Chosen configuration.

		On OS/X and Windows with 32-bit Matlab/Octave, usually Quicktime is
		used as movie playback engine. If GStreamer is supported on that
		platforms and enabled via Screen('Preference','OverrideMultimediaEngine', 1);
		then GStreamer is used.

		On all other platforms it is either GStreamer or nothing, as Quicktime
		isn't supported. These platforms are Window and OS/X with 64-bit Matlab/Octave,
		and Linux. As of 30.11.2010, only Linux is supported, 64-bit OS/X and
		Windows are planned.

	NOTES:

*/

#include "Screen.h"

#if PSYCH_SYSTEM != PSYCH_LINUX
#if !defined(__LP64__) && !defined(_M_IA64)
#define PSYCHQTAVAIL 1
#include "PsychMovieSupportQuickTime.h"
#endif
#endif

#if defined(__LP64__) || defined(_M_IA64)
#define PSYCHOTHER64BIT 1
#else
#define PSYCHOTHER64BIT 0
#endif

#ifdef PTB_USE_GSTREAMER
#include "PsychMovieSupportGStreamer.h"
#define USE_GSTREAMER 1
#else
#define USE_GSTREAMER 0
#endif

static psych_bool firstTime = TRUE;
static psych_bool doUsegs   = FALSE;

static psych_bool usegs(void) {
	// First invocation since module load time?
	if (firstTime) {
		// Yes. Need to probe which engine to use:
		firstTime = FALSE;

		// Default to Quicktime instead of GStreamer,
		// override in detection code below if appropriate:
		doUsegs = FALSE;

		// We always use GStreamer if we are running on
		// Linux, or 64-Bit builds on OS/X or Windows, as
		// these systems only support GStreamer, but they
		// support it consistently:
		if ((PSYCH_SYSTEM == PSYCH_LINUX) || PSYCHOTHER64BIT) {
			// Yep: Unconditionally use GStreamer:
			doUsegs = TRUE;
		} else {
			// This is a 32-bit build on Windows or OS/X.
			// We use GStreamer if it is supported and usercode
			// wants to use it, according to preference setting:
			if (USE_GSTREAMER && (PsychPrefStateGet_UseGStreamer()==1)) {
				doUsegs = TRUE;
			}
		}
	}

	// Return cached engine use flag:
	return(doUsegs);
}

/*
 *     PsychMovieInit() -- Initialize movie subsystem.
 *     This routine is called by Screen's RegisterProject.c PsychModuleInit()
 *     routine at Screen load-time. It clears out the movieRecordBANK to
 *     bring the subsystem into a clean initial state.
 */
void PsychMovieInit(void)
{
	#ifdef PTB_USE_GSTREAMER
	// This will also first-time initialize Glib's threading system:
	PsychGSMovieInit();
	#endif

	#ifdef PSYCHQTAVAIL
	PsychQTMovieInit();
	#endif

	// Reset firstTime flag:
	firstTime = TRUE;
	return;
}

int PsychGetMovieCount(void)
{
	if (usegs()) {
	#ifdef PTB_USE_GSTREAMER
	return(PsychGSGetMovieCount());
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	return(PsychQTGetMovieCount());
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
	return(0);
}

/*
 *      PsychAsyncCreateMovie() -- Open a movie file in the background.
 *
 *      This function is called by SCREENOpenMovie as main-function of
 *      a new Posix-Thread for background movie loading. It simply calls
 *      PsychCreateMovie(), waiting for it to return a new moviehandle.
 *      Then it returns those info and terminates.
 *      -> By calling PsychCreateMovie from the run-function of a dedicated
 *      Posix-Thread which runs independent of the main Matlab/PTB Thread with
 *      non-realtime priority, we can do the work of opening a Quicktime movie
 *      in the background, hopefully not affecting the timing of the main PTB
 *      thread too much.
 */
void* PsychAsyncCreateMovie(void* inmovieinfo)
{
    int rc;
	PsychAsyncMovieInfo* movieinfo = (PsychAsyncMovieInfo*) inmovieinfo;
	
    // The special value -1000 tells PsychCreateMovie to not output any error-
    // messages as this could easily crash Matlab/Octave.
    int mymoviehandle=-1000;

    // Reduce our scheduling priority to the minimum value of zero, so
    // we do not interfere too much with the PTB main thread:
    if ((rc=PsychSetThreadPriority(NULL, 0, 0))!=0) {
        printf("PTB-WARNING: In PsychAsyncCreateMovie(): Failed to lower my priority to non-realtime [System errorcode %i]. Expect timing problems for movie playback!", rc);
    }
    
    // Execute our normal OpenMovie function: This does the hard work:
    PsychCreateMovie(&(movieinfo->windowRecord), movieinfo->moviename, movieinfo->preloadSecs, &mymoviehandle, movieinfo->asyncFlag, movieinfo->specialFlags1);
	
    // Ok, either we have a moviehandle to a valid movie, or we failed, which would
    // be signalled to the calling function via some negative moviehandle:
    movieinfo->moviehandle = mymoviehandle; // Return moviehandle.
    movieinfo->asyncstate = 2; // Set state to "Completed"
    
    // Exit from the routine. This will automatically terminate our Thread.
    return(NULL);
}

/*
 *      PsychCreateMovie() -- Create a movie object.
 *
 *      This function tries to open a Quicktime-Moviefile and create an
 *      associated movie object for it.
 *
 *      win = Pointer to window record of associated onscreen window.
 *      moviename = char* with the name of the moviefile.
 *      moviehandle = handle to the new movie.
 */
void PsychCreateMovie(PsychWindowRecordType *win, const char* moviename, double preloadSecs, int* moviehandle, int asyncFlag, int specialFlags1)
{
	if (usegs()) {
	#ifdef PTB_USE_GSTREAMER
	PsychGSCreateMovie(win, moviename, preloadSecs, moviehandle, asyncFlag, specialFlags1);
	return;
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTCreateMovie(win, moviename, preloadSecs, moviehandle, specialFlags1);
	return;
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
}

/*
 *  PsychGetMovieInfo() - Return basic information about a movie.
 *
 *  framecount = Total number of video frames in the movie, determined by counting.
 *  durationsecs = Total playback duration of the movie, in seconds.
 *  framerate = Estimated video playback framerate in frames per second (fps).
 *  width = Width of movie images in pixels.
 *  height = Height of movie images in pixels.
 *  nrdroppedframes = Total count of videoframes that had to be dropped during last movie playback,
 *                    in order to keep the movie synced with the realtime clock.
 *  aspectRatio = Pixel aspect ratio of encoded pixels in movie frame. (GStreamer only).
 */
void PsychGetMovieInfos(int moviehandle, int* width, int* height, int* framecount, double* durationsecs, double* framerate, int* nrdroppedframes, double* aspectRatio)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	PsychGSGetMovieInfos(moviehandle, width, height, framecount, durationsecs, framerate, nrdroppedframes, aspectRatio);
	return;
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTGetMovieInfos(moviehandle, width, height, framecount, durationsecs, framerate, nrdroppedframes);
	if (aspectRatio) *aspectRatio = 1.0;
	return;
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
}

/*
 *  PsychDeleteMovie() -- Delete a movie object and release all associated ressources.
 */
void PsychDeleteMovie(int moviehandle)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	PsychGSDeleteMovie(moviehandle);
	return;
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTDeleteMovie(moviehandle);
	return;
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
}

/*
 *  PsychDeleteAllMovies() -- Delete all movie objects and release all associated ressources.
 */
void PsychDeleteAllMovies(void)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	PsychGSDeleteAllMovies();
	return;
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTDeleteAllMovies();
	return;
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
}

/*
 *  PsychGetTextureFromMovie() -- Create an OpenGL texture map from a specific videoframe from given movie object.
 *
 *  win = Window pointer of onscreen window for which a OpenGL texture should be created.
 *  moviehandle = Handle to the movie object.
 *  checkForImage = true == Just check if new image available, false == really retrieve the image, blocking if necessary.
 *  timeindex = When not in playback mode, this allows specification of a requested frame by presentation time.
 *              If set to -1, or if in realtime playback mode, this parameter is ignored and the next video frame is returned.
 *  out_texture = Pointer to the Psychtoolbox texture-record where the new texture should be stored.
 *  presentation_timestamp = A ptr to a double variable, where the presentation timestamp of the returned frame should be stored.
 *
 *  Returns true (1) on success, false (0) if no new image available, -1 if no new image available and there won't be any in future.
 */
int PsychGetTextureFromMovie(PsychWindowRecordType *win, int moviehandle, int checkForImage, double timeindex, PsychWindowRecordType *out_texture, double *presentation_timestamp)
{
	if (usegs()) {
	#ifdef PTB_USE_GSTREAMER
	return(PsychGSGetTextureFromMovie(win, moviehandle, checkForImage, timeindex, out_texture, presentation_timestamp));
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	return(PsychQTGetTextureFromMovie(win, moviehandle, checkForImage, timeindex, out_texture, presentation_timestamp));
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
	return(-1);
}

/*
 *  PsychFreeMovieTexture() - Release texture memory for a Quicktime texture.
 *
 *  This routine is called by PsychDeleteTexture() in PsychTextureSupport.c
 *  It performs the special cleanup necessary for Quicktime created textures.
 *
 */
void PsychFreeMovieTexture(PsychWindowRecordType *win)
{
	if (usegs()) {
	#ifdef PTB_USE_GSTREAMER
	PsychGSFreeMovieTexture(win);
	return;
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTFreeMovieTexture(win);
	return;
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
}

/*
 *  PsychPlaybackRate() - Start- and stop movieplayback, set playback parameters.
 *
 *  moviehandle = Movie to start-/stop.
 *  playbackrate = zero == Stop playback, non-zero == Play movie with spec. rate,
 *                 e.g., 1 = forward, 2 = double speed forward, -1 = backward, ...
 *  loop = 0 = Play once. 1 = Loop, aka rewind at end of movie and restart.
 *  soundvolume = 0 == Mute sound playback, between 0.0 and 1.0 == Set volume to 0 - 100 %.
 *  Returns Number of dropped frames to keep playback in sync.
 */
int PsychPlaybackRate(int moviehandle, double playbackrate, int loop, double soundvolume)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	return(PsychGSPlaybackRate(moviehandle, playbackrate, loop, soundvolume));
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	return(PsychQTPlaybackRate(moviehandle, playbackrate, loop, soundvolume));
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
	return(0);
}

/*
 *  void PsychExitMovies() - Shutdown handler.
 *
 *  This routine is called by Screen('CloseAll') and on clear Screen time to
 *  do final cleanup. It deletes all Quicktime textures and releases all Quicktime
 *  movie objects. Then it shuts down the Quicktime subsystem.
 *
 */
void PsychExitMovies(void)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	PsychGSExitMovies();
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	PsychQTExitMovies();
	#endif
	}

	// Reset firstTime flag:
	firstTime = TRUE;
	return;
}

/*
 *  PsychGetMovieTimeIndex()  -- Return current playback time of movie.
 */
double PsychGetMovieTimeIndex(int moviehandle)
{

	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	return(PsychGSGetMovieTimeIndex(moviehandle));
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	return(PsychQTGetMovieTimeIndex(moviehandle));
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
	return(0.0);
}

/*
 *  PsychSetMovieTimeIndex()  -- Set current playback time of movie.
 */
double PsychSetMovieTimeIndex(int moviehandle, double timeindex, psych_bool indexIsFrames)
{
	if (usegs()) {
        #ifdef PTB_USE_GSTREAMER
	return(PsychGSSetMovieTimeIndex(moviehandle, timeindex, indexIsFrames));
	#endif
	} else {
	#ifdef PSYCHQTAVAIL
	return(PsychQTSetMovieTimeIndex(moviehandle, timeindex, indexIsFrames));
	#endif
	}

	PsychErrorExitMsg(PsychError_unimplemented, "Sorry, Movie playback support not supported on your configuration.");
	return(0.0);
}