def _get_data_ref(self, file, filename): self._data_hold = data = create_string_buffer(file.read()) dataref = carbon.NewHandle(sizeof(PointerDataRefRecord)) datarec = cast(dataref, POINTER(POINTER(PointerDataRefRecord))).contents.contents datarec.data = addressof(data) datarec.dataLength = len(data) self._data_handler_holder = data_handler = ComponentInstance() r = quicktime.OpenADataHandler(dataref, PointerDataHandlerSubType, None, 0, None, kDataHCanRead, byref(data_handler)) _oscheck(r) extension_handle = Handle() self._filename_hold = filename = Str255(filename) r = carbon.PtrToHand(filename, byref(extension_handle), len(filename)) r = quicktime.DataHSetDataRefExtension(data_handler, extension_handle, kDataRefExtensionFileName) _oscheck(r) quicktime.DisposeHandle(extension_handle) quicktime.DisposeHandle(dataref) dataref = c_void_p() r = quicktime.DataHGetDataRef(data_handler, byref(dataref)) _oscheck(r) quicktime.CloseComponent(data_handler) return dataref
def decode_animation(self, file, filename): # TODO: Stop playing chicken with the GC # TODO: Cleanup in errors quicktime.EnterMovies() data_ref = self._get_data_ref(file, filename) if not data_ref: raise ImageDecodeException(filename or file) movie = c_void_p() id = c_short() result = quicktime.NewMovieFromDataRef(byref(movie), newMovieActive, 0, data_ref, PointerDataHandlerSubType) if not movie: #_oscheck(result) raise ImageDecodeException(filename or file) quicktime.GoToBeginningOfMovie(movie) time_scale = float(quicktime.GetMovieTimeScale(movie)) format, qtformat = self._get_formats() # Get movie width and height rect = Rect() quicktime.GetMovieBox(movie, byref(rect)) width = rect.right height = rect.bottom pitch = len(format) * width # Set gworld buffer = (c_byte * (width * height * len(format)))() world = GWorldPtr() quicktime.QTNewGWorldFromPtr(byref(world), qtformat, byref(rect), c_void_p(), c_void_p(), 0, buffer, len(format) * width) quicktime.SetGWorld(world, 0) quicktime.SetMovieGWorld(movie, world, 0) visual = quicktime.GetMovieIndTrackType(movie, 1, VisualMediaCharacteristic, movieTrackCharacteristic) if not visual: raise ImageDecodeException('No video track') time = 0 interesting_time = c_int() quicktime.GetTrackNextInterestingTime( visual, nextTimeMediaSample, time, 1, byref(interesting_time), None) duration = interesting_time.value / time_scale frames = [] while time >= 0: result = quicktime.GetMoviesError() if result == noErr: # force redraw result = quicktime.UpdateMovie(movie) if result == noErr: # process movie quicktime.MoviesTask(movie, 0) result = quicktime.GetMoviesError() _oscheck(result) buffer_copy = (c_byte * len(buffer))() memmove(buffer_copy, buffer, len(buffer)) image = ImageData(width, height, format, buffer_copy, -pitch) frames.append(AnimationFrame(image, duration)) interesting_time = c_int() duration = c_int() quicktime.GetTrackNextInterestingTime( visual, nextTimeMediaSample, time, 1, byref(interesting_time), byref(duration)) quicktime.SetMovieTimeValue(movie, interesting_time) time = interesting_time.value duration = duration.value / time_scale if duration <= 0.01: duration = 0.1 quicktime.DisposeMovie(movie) carbon.DisposeHandle(data_ref) quicktime.ExitMovies() return Animation(frames)