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