function PlayMoviesWithoutGapDemo2(moviename) % PlayMoviesWithoutGapDemo2(moviename) % % This demo accepts a pattern for a valid moviename, e.g., % moviename='*.mpg', then it plays all movies in the current working % directory whose names match the provided pattern, e.g., the '*.mpg' % pattern would play all MPEG files in the current directory. % % Pressing ESC ends the demo. % % Movies are played one after each other. We try to minimize perceptible % gaps between end of movie i and start of movie i+1 by asynchronous % loading: While movie i is played back, we ask Psychtoolbox to load the % next movie i+1 in the background, so startup time for movie i+1 will be % minimized. % % This method uses only one 'movie' object for successive, gapless playback % of many movie files. The advantage is simplicity in use and maximum % quality in the sense that movies should play back-to-back without any % significant delays between them. The downside is loss in flexibility. % This method only works if all movies have exactly the same image size, % color depth and format, aspect ratio and playback framerate. They may % only differ in filename, content and duration. Any other difference will % cause malfunctions, even hard crashes of Matlab or Octave! % % If you need a method that is more flexible and can handle movies of % different format, use the method in PlayMoviesWithoutGapDemo1. That % method can handle arbitrary movies. The downside is a higher likelyhood % of small gaps between movies. % % History: 14.03.2012 mk Wrote it, derived from PlayMoviesWithoutGapDemo1. AssertOpenGL; if nargin < 1 moviename = '*.mov' %#ok end % Switch KbName into unified mode: It will use the names of the OS-X % platform on all platforms in order to make this script portable: KbName('UnifyKeyNames'); esc=KbName('ESCAPE'); try % Open onscreen window: screen=max(Screen('Screens')); win = Screen('OpenWindow', screen, 128); Screen('Flip',win); abortit = 0; % Return full list of movie files from directory+pattern: moviefiles=dir(moviename); for i=1:size(moviefiles,1) moviefiles(i).name = [ pwd filesep moviefiles(i).name ]; end % Playbackrate defaults to 1: rate=1; % Load first movie. This is a synchronous (blocking) load: iteration = 1; moviename=moviefiles(mod(iteration, size(moviefiles,1))+1).name; [movie movieduration fps imgw imgh] = Screen('OpenMovie', win, moviename); fprintf('ITER=%i::', iteration); fprintf('Movie: %s : %f seconds duration, %f fps, w x h = %i x %i...\n', moviename, movieduration, fps, imgw, imgh); % Start playback of movie. This will start % the realtime playback clock and playback of audio tracks, if any. % Play 'movie', at a playbackrate = rate, with 1.0 == 100% audio volume. Screen('PlayMovie', movie, rate, 0, 1.0); prefetched = 0; lastpts = -1; % Endless loop, runs until ESC key pressed: while abortit < 2 % Show basic info about next movie: Only the name, as we cannot access % other info (fps, duration, width and height) for all successor movies. % Not a big deal, as all properties have to match the known properties of % the first opened movie anyway - except for moviename and duration... fprintf('ITER=%i::', iteration); fprintf('Movie: %s ...\n', moviename); i=0; % Get moviename of next file (after the one that is currently playing): iteration=iteration + 1; moviename=moviefiles(mod(iteration, size(moviefiles,1))+1).name; t1 = GetSecs; % Playback loop: Fetch video frames and display them... while 1 i=i+1; if abs(rate) > 0 % Return next frame in movie, in sync with current playback % time and sound. % tex either the texture handle or zero if no new frame is % ready yet. pts = Presentation timestamp in seconds. [tex pts] = Screen('GetMovieImage', win, movie, 1); % Valid texture returned? if tex < 0 % No. This means that the end of this movie is reached. % This can't really happen, unless something went wrong % during playback, because we play all movies round-robin % completely seamless. break end if tex > 0 % Yes. Draw the new texture immediately to screen: Screen('DrawTexture', win, tex); % Update display: Screen('Flip', win); % Release texture: Screen('Close', tex); end end % Check for abortion by user: abortit = 0; [keyIsDown,secs,keyCode]=KbCheck; %#ok if (keyIsDown && keyCode(esc)) % Set the abort-demo flag. abortit = 2; break; end % We queue the next movie for playback, immediately % after start of playback of the current movie, as indicated % by the > 0 presentation timestamp: if prefetched==0 && pts > 0 % Queue for background async load operation: % We simply set the async flag to 2 and don't query any % return values. We pass in the 'movie' handle of the movie % which should be succeeded by the new movie 'moviename': Screen('OpenMovie', win, moviename, 2, movie); prefetched=1; end % Detect when the followup movie has started playback. We detect % the change due to a wraparound of the presentation timestamp: if prefetched==1 && pts < lastpts % New movie has started. Do a new outer-loop iteration to % select a new moviefile as successor: prefetched = 0; lastpts = -1; break; end % Keep track of playback time: lastpts = pts; end % Print some stats about last played movie: telapsed = GetSecs - t1 %#ok finalcount=i %#ok % As playback of the new movie has been started already, we can % simply reenter the playback loop: end % End of playback - stop & close the movie: Screen('PlayMovie', movie, 0); Screen('CloseMovie', movie); % Close screen: sca; % Done. return; catch %#ok % Error handling: Close all windows and movies, release all ressources. sca; psychrethrow(psychlasterror); end