1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Video file reader, using QuickTime 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# This module was quickly ripped out of another software package, so there is a good 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# chance that it does not work as-is and it needs some hacking. 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Jack Jansen, August 2000 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom warnings import warnpy3k 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehwarnpy3k("In 3.x, the videoreader module is removed.", stacklevel=2) 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import Qt 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import QuickTime 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import Qd 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import Qdoffs 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import QDOffscreen 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom Carbon import Res 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from Carbon import MediaDescr 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError: 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _audiodescr(data): 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehelse: 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _audiodescr(data): 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return MediaDescr.SoundDescription.decode(data) 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from imgformat import macrgb 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept ImportError: 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh macrgb = "Macintosh RGB format" 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# import audio.format 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass VideoFormat: 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, name, descr, width, height, format): 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__name = name 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__descr = descr 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__width = width 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__height = height 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__format = format 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getname(self): 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__name 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getdescr(self): 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__descr 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getsize(self): 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__width, self.__height 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def getformat(self): 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.__format 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass _Reader: 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, path): 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fd = Qt.OpenMovieFile(path, 0) 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0) 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movietimescale = self.movie.GetMovieTimeScale() 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiotrack = self.movie.GetMovieIndTrackType(1, 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic) 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiomedia = self.audiotrack.GetTrackMedia() 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except Qt.Error: 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiotrack = self.audiomedia = None 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiodescr = {} 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh handle = Res.Handle('') 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh n = self.audiomedia.GetMediaSampleDescriptionCount() 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiomedia.GetMediaSampleDescription(1, handle) 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiodescr = _audiodescr(handle.data) 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiotimescale = self.audiomedia.GetMediaTimeScale() 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh del handle 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videotrack = self.movie.GetMovieIndTrackType(1, 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic) 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videomedia = self.videotrack.GetTrackMedia() 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except Qt.Error: 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videotrack = self.videomedia = self.videotimescale = None 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.videotrack: 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videotimescale = self.videomedia.GetMediaTimeScale() 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh x0, y0, x1, y1 = self.movie.GetMovieBox() 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videodescr = {'width':(x1-x0), 'height':(y1-y0)} 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._initgworld() 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videocurtime = None 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiocurtime = None 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __del__(self): 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiomedia = None 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiotrack = None 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videomedia = None 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videotrack = None 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie = None 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _initgworld(self): 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh old_port, old_dev = Qdoffs.GetGWorld() 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh movie_w = self.videodescr['width'] 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh movie_h = self.videodescr['height'] 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh movie_rect = (0, 0, movie_w, movie_h) 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal) 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.pixmap = self.gworld.GetGWorldPixMap() 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Qdoffs.LockPixels(self.pixmap) 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None) 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Qd.EraseRect(movie_rect) 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None) 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.SetMovieBox(movie_rect) 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.SetMovieActive(1) 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.MoviesTask(0) 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # XXXX framerate 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Qdoffs.SetGWorld(old_port, old_dev) 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _gettrackduration_ms(self, track): 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tracktime = track.GetTrackDuration() 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._movietime_to_ms(tracktime) 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _movietime_to_ms(self, time): 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000) 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return value 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _videotime_to_ms(self, time): 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000) 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return value 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _audiotime_to_ms(self, time): 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000) 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return value 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _videotime_to_movietime(self, time): 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movietimescale) 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return value 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def HasAudio(self): 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return not self.audiotrack is None 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def HasVideo(self): 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return not self.videotrack is None 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetAudioDuration(self): 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.audiotrack: 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 0 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._gettrackduration_ms(self.audiotrack) 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetVideoDuration(self): 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.videotrack: 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 0 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._gettrackduration_ms(self.videotrack) 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetAudioFormat(self): 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.audiodescr: 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None, None, None, None, None 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bps = self.audiodescr['sampleSize'] 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nch = self.audiodescr['numChannels'] 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if nch == 1: 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh channels = ['mono'] 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif nch == 2: 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh channels = ['left', 'right'] 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh channels = map(lambda x: str(x+1), range(nch)) 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if bps % 8: 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Funny bits-per sample. We pretend not to understand 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh blocksize = 0 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fpb = 0 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # QuickTime is easy (for as far as we support it): samples are always a whole 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # number of bytes, so frames are nchannels*samplesize, and there's one frame per block. 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh blocksize = (bps/8)*nch 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fpb = 1 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.audiodescr['dataFormat'] == 'raw ': 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = 'linear-excess' 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif self.audiodescr['dataFormat'] == 'twos': 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = 'linear-signed' 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat'] 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format', 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps) 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return channels, encoding, blocksize, fpb, bps 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetAudioFrameRate(self): 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.audiodescr: 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(self.audiodescr['sampleRate']) 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetVideoFormat(self): 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh width = self.videodescr['width'] 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh height = self.videodescr['height'] 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb) 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def GetVideoFrameRate(self): 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tv = self.videocurtime 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tv is None: 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tv = 0 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0) 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dur = self._videotime_to_ms(dur) 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int((1000.0/dur)+0.5) 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ReadAudio(self, nframes, time=None): 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not time is None: 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiocurtime = time 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.audiocurtime is None: 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiocurtime = 0 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0) 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tv < 0 or (self.audiocurtime and tv < self.audiocurtime): 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._audiotime_to_ms(self.audiocurtime), None 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh h = Res.Handle('') 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh desc_h = Res.Handle('') 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh size, actualtime, sampleduration, desc_index, actualcount, flags = \ 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes) 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.audiocurtime = actualtime + actualcount*sampleduration 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._audiotime_to_ms(actualtime), h.data 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def ReadVideo(self, time=None): 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not time is None: 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videocurtime = time 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags = QuickTime.nextTimeStep 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.videocurtime is None: 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags = flags | QuickTime.nextTimeEdgeOK 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videocurtime = 0 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0) 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if tv < 0 or (self.videocurtime and tv <= self.videocurtime): 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._videotime_to_ms(self.videocurtime), None 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.videocurtime = tv 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh moviecurtime = self._videotime_to_movietime(self.videocurtime) 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.SetMovieTimeValue(moviecurtime) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.movie.MoviesTask(0) 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent() 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def _getpixmapcontent(self): 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Shuffle the offscreen PixMap data, because it may have funny stride values""" 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rowbytes = Qdoffs.GetPixRowBytes(self.pixmap) 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh width = self.videodescr['width'] 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh height = self.videodescr['height'] 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start = 0 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rv = [] 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(height): 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4) 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh start = start + rowbytes 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rv.append(nextline) 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return ''.join(rv) 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef reader(url): 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rdr = _Reader(url) 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError: 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return rdr 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _test(): 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import EasyDialogs 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from PIL import Image 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except ImportError: 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Image = None 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import MacOS 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Qt.EnterMovies() 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh path = EasyDialogs.AskFileForOpen(message='Video to convert') 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not path: sys.exit(0) 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rdr = reader(path) 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not rdr: 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.exit(1) 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dstdir = EasyDialogs.AskFileForSave(message='Name for output folder') 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not dstdir: sys.exit(0) 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh num = 0 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.mkdir(dstdir) 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh videofmt = rdr.GetVideoFormat() 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh imgfmt = videofmt.getformat() 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh imgw, imgh = videofmt.getsize() 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestamp, data = rdr.ReadVideo() 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh while data: 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fname = 'frame%04.4d.jpg'%num 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh num = num+1 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pname = os.path.join(dstdir, fname) 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not Image: print 'Not', 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data)) 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if Image: 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh img = Image.fromstring("RGBA", (imgw, imgh), data) 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh img.save(pname, 'JPEG') 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestamp, data = rdr.ReadVideo() 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG') 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if num > 20: 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'stopping at 20 frames so your disk does not fill up:-)' 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh break 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print 'Total frames:', num 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == '__main__': 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _test() 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.exit(1) 295