10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Video file reader, using QuickTime 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# This module was quickly ripped out of another software package, so there is a good 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# chance that it does not work as-is and it needs some hacking. 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Jack Jansen, August 2000 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom warnings import warnpy3k 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaowarnpy3k("In 3.x, the videoreader module is removed.", stacklevel=2) 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys 140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Qt 150a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import QuickTime 160a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Qd 170a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Qdoffs 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import QDOffscreen 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Carbon import Res 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry: 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from Carbon import MediaDescr 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError: 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _audiodescr(data): 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return None 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse: 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _audiodescr(data): 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return MediaDescr.SoundDescription.decode(data) 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry: 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from imgformat import macrgb 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError: 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao macrgb = "Macintosh RGB format" 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# import audio.format 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass VideoFormat: 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, name, descr, width, height, format): 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.__name = name 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.__descr = descr 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.__width = width 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.__height = height 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.__format = format 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def getname(self): 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__name 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def getdescr(self): 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__descr 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def getsize(self): 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__width, self.__height 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def getformat(self): 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.__format 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass _Reader: 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, path): 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fd = Qt.OpenMovieFile(path, 0) 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie, d1, d2 = Qt.NewMovieFromFile(fd, 0, 0) 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movietimescale = self.movie.GetMovieTimeScale() 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiotrack = self.movie.GetMovieIndTrackType(1, 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao QuickTime.AudioMediaCharacteristic, QuickTime.movieTrackCharacteristic) 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiomedia = self.audiotrack.GetTrackMedia() 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except Qt.Error: 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiotrack = self.audiomedia = None 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiodescr = {} 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao handle = Res.Handle('') 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao n = self.audiomedia.GetMediaSampleDescriptionCount() 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiomedia.GetMediaSampleDescription(1, handle) 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiodescr = _audiodescr(handle.data) 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiotimescale = self.audiomedia.GetMediaTimeScale() 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao del handle 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videotrack = self.movie.GetMovieIndTrackType(1, 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao QuickTime.VisualMediaCharacteristic, QuickTime.movieTrackCharacteristic) 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videomedia = self.videotrack.GetTrackMedia() 790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except Qt.Error: 800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videotrack = self.videomedia = self.videotimescale = None 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.videotrack: 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videotimescale = self.videomedia.GetMediaTimeScale() 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao x0, y0, x1, y1 = self.movie.GetMovieBox() 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videodescr = {'width':(x1-x0), 'height':(y1-y0)} 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._initgworld() 860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videocurtime = None 870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiocurtime = None 880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __del__(self): 910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiomedia = None 920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiotrack = None 930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videomedia = None 940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videotrack = None 950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie = None 960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _initgworld(self): 980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao old_port, old_dev = Qdoffs.GetGWorld() 990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao movie_w = self.videodescr['width'] 1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao movie_h = self.videodescr['height'] 1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao movie_rect = (0, 0, movie_w, movie_h) 1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.gworld = Qdoffs.NewGWorld(32, movie_rect, None, None, QDOffscreen.keepLocal) 1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.pixmap = self.gworld.GetGWorldPixMap() 1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Qdoffs.LockPixels(self.pixmap) 1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Qdoffs.SetGWorld(self.gworld.as_GrafPtr(), None) 1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Qd.EraseRect(movie_rect) 1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.SetMovieGWorld(self.gworld.as_GrafPtr(), None) 1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.SetMovieBox(movie_rect) 1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.SetMovieActive(1) 1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.MoviesTask(0) 1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.SetMoviePlayHints(QuickTime.hintsHighQuality, QuickTime.hintsHighQuality) 1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # XXXX framerate 1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao finally: 1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Qdoffs.SetGWorld(old_port, old_dev) 1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _gettrackduration_ms(self, track): 1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tracktime = track.GetTrackDuration() 1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._movietime_to_ms(tracktime) 1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _movietime_to_ms(self, time): 1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value, d1, d2 = Qt.ConvertTimeScale((time, self.movietimescale, None), 1000) 1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return value 1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _videotime_to_ms(self, time): 1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1000) 1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return value 1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _audiotime_to_ms(self, time): 1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value, d1, d2 = Qt.ConvertTimeScale((time, self.audiotimescale, None), 1000) 1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return value 1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _videotime_to_movietime(self, time): 1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao value, d1, d2 = Qt.ConvertTimeScale((time, self.videotimescale, None), 1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movietimescale) 1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return value 1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def HasAudio(self): 1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return not self.audiotrack is None 1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def HasVideo(self): 1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return not self.videotrack is None 1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetAudioDuration(self): 1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.audiotrack: 1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return 0 1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._gettrackduration_ms(self.audiotrack) 1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetVideoDuration(self): 1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.videotrack: 1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return 0 1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._gettrackduration_ms(self.videotrack) 1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetAudioFormat(self): 1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.audiodescr: 1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return None, None, None, None, None 1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao bps = self.audiodescr['sampleSize'] 1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao nch = self.audiodescr['numChannels'] 1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if nch == 1: 1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao channels = ['mono'] 1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif nch == 2: 1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao channels = ['left', 'right'] 1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao channels = map(lambda x: str(x+1), range(nch)) 1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if bps % 8: 1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # Funny bits-per sample. We pretend not to understand 1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao blocksize = 0 1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fpb = 0 1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # QuickTime is easy (for as far as we support it): samples are always a whole 1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # number of bytes, so frames are nchannels*samplesize, and there's one frame per block. 1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao blocksize = (bps/8)*nch 1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fpb = 1 1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.audiodescr['dataFormat'] == 'raw ': 1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao encoding = 'linear-excess' 1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao elif self.audiodescr['dataFormat'] == 'twos': 1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao encoding = 'linear-signed' 1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao encoding = 'quicktime-coding-%s'%self.audiodescr['dataFormat'] 1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao## return audio.format.AudioFormatLinear('quicktime_audio', 'QuickTime Audio Format', 1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao## channels, encoding, blocksize=blocksize, fpb=fpb, bps=bps) 1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return channels, encoding, blocksize, fpb, bps 1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetAudioFrameRate(self): 1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not self.audiodescr: 1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return None 1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return int(self.audiodescr['sampleRate']) 1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetVideoFormat(self): 1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao width = self.videodescr['width'] 1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao height = self.videodescr['height'] 1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return VideoFormat('dummy_format', 'Dummy Video Format', width, height, macrgb) 1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def GetVideoFrameRate(self): 1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tv = self.videocurtime 1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if tv is None: 1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tv = 0 1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK 1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tv, dur = self.videomedia.GetMediaNextInterestingTime(flags, tv, 1.0) 2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dur = self._videotime_to_ms(dur) 2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return int((1000.0/dur)+0.5) 2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def ReadAudio(self, nframes, time=None): 2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not time is None: 2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiocurtime = time 2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao flags = QuickTime.nextTimeStep|QuickTime.nextTimeEdgeOK 2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.audiocurtime is None: 2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiocurtime = 0 2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tv = self.audiomedia.GetMediaNextInterestingTimeOnly(flags, self.audiocurtime, 1.0) 2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if tv < 0 or (self.audiocurtime and tv < self.audiocurtime): 2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._audiotime_to_ms(self.audiocurtime), None 2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao h = Res.Handle('') 2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao desc_h = Res.Handle('') 2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao size, actualtime, sampleduration, desc_index, actualcount, flags = \ 2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiomedia.GetMediaSample(h, 0, tv, desc_h, nframes) 2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.audiocurtime = actualtime + actualcount*sampleduration 2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._audiotime_to_ms(actualtime), h.data 2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def ReadVideo(self, time=None): 2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not time is None: 2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videocurtime = time 2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao flags = QuickTime.nextTimeStep 2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.videocurtime is None: 2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao flags = flags | QuickTime.nextTimeEdgeOK 2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videocurtime = 0 2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao tv = self.videomedia.GetMediaNextInterestingTimeOnly(flags, self.videocurtime, 1.0) 2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if tv < 0 or (self.videocurtime and tv <= self.videocurtime): 2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._videotime_to_ms(self.videocurtime), None 2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.videocurtime = tv 2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao moviecurtime = self._videotime_to_movietime(self.videocurtime) 2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.SetMovieTimeValue(moviecurtime) 2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.movie.MoviesTask(0) 2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._videotime_to_ms(self.videocurtime), self._getpixmapcontent() 2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _getpixmapcontent(self): 2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """Shuffle the offscreen PixMap data, because it may have funny stride values""" 2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rowbytes = Qdoffs.GetPixRowBytes(self.pixmap) 2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao width = self.videodescr['width'] 2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao height = self.videodescr['height'] 2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao start = 0 2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rv = [] 2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for i in range(height): 2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao nextline = Qdoffs.GetPixMapBytes(self.pixmap, start, width*4) 2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao start = start + rowbytes 2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rv.append(nextline) 2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return ''.join(rv) 2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef reader(url): 2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rdr = _Reader(url) 2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except IOError: 2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return None 2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return rdr 2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _test(): 2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import EasyDialogs 2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao from PIL import Image 2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except ImportError: 2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Image = None 2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao import MacOS 2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Qt.EnterMovies() 2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao path = EasyDialogs.AskFileForOpen(message='Video to convert') 2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not path: sys.exit(0) 2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao rdr = reader(path) 2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not rdr: 2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.exit(1) 2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao dstdir = EasyDialogs.AskFileForSave(message='Name for output folder') 2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not dstdir: sys.exit(0) 2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao num = 0 2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao os.mkdir(dstdir) 2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao videofmt = rdr.GetVideoFormat() 2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao imgfmt = videofmt.getformat() 2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao imgw, imgh = videofmt.getsize() 2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao timestamp, data = rdr.ReadVideo() 2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao while data: 2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fname = 'frame%04.4d.jpg'%num 2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao num = num+1 2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pname = os.path.join(dstdir, fname) 2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not Image: print 'Not', 2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print 'Writing %s, size %dx%d, %d bytes'%(fname, imgw, imgh, len(data)) 2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if Image: 2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao img = Image.fromstring("RGBA", (imgw, imgh), data) 2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao img.save(pname, 'JPEG') 2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao timestamp, data = rdr.ReadVideo() 2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao MacOS.SetCreatorAndType(pname, 'ogle', 'JPEG') 2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if num > 20: 2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print 'stopping at 20 frames so your disk does not fill up:-)' 2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao break 2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print 'Total frames:', num 2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__': 2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao _test() 2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao sys.exit(1) 295