def seek(self, timestamp): timestamp = timestamp_to_wmf(timestamp) prop = PROPVARIANT() prop.vt = VT_I8 prop.llVal = timestamp pos_com = com.GUID(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) self._source_reader.SetCurrentPosition(pos_com, prop)
def get_image(self, bitmap, target_fmt=GUID_WICPixelFormat32bppBGRA): """Get's image from bitmap, specifying target format, bitmap is released before returning.""" width = UINT() height = UINT() bitmap.GetSize(byref(width), byref(height)) width = int(width.value) height = int(height.value) # Get image pixel format pf = com.GUID(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) bitmap.GetPixelFormat(byref(pf)) fmt = 'BGRA' # If target format is not what we want (32bit BGRA) convert it. if pf != target_fmt: converter = IWICFormatConverter() self._factory.CreateFormatConverter(byref(converter)) conversion_possible = BOOL() converter.CanConvert(pf, target_fmt, byref(conversion_possible)) # 99% of the time conversion will be possible to default. # However, we check to be safe and fallback to 24 bit BGR if not possible. if not conversion_possible: target_fmt = GUID_WICPixelFormat24bppBGR fmt = 'BGR' converter.Initialize(bitmap, target_fmt, WICBitmapDitherTypeNone, None, 0, WICBitmapPaletteTypeCustom) bitmap.Release() bitmap = converter # Most images are loaded with a negative pitch, which requires list comprehension to fix. # Create a flipped bitmap through the decoder rather through Python to increase performance. flipper = IWICBitmapFlipRotator() self._factory.CreateBitmapFlipRotator(byref(flipper)) flipper.Initialize(bitmap, WICBitmapTransformFlipVertical) stride = len(fmt) * width buffer_size = stride * height buffer = (BYTE * buffer_size)() flipper.CopyPixels(None, stride, buffer_size, byref(buffer)) flipper.Release() bitmap.Release() # Can be converter. return ImageData(width, height, fmt, buffer)
def seek(self, timestamp): timestamp = min(timestamp, self._duration) if self._duration else timestamp prop = PROPVARIANT() prop.vt = VT_I8 prop.llVal = timestamp_to_wmf(timestamp) pos_com = com.GUID(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) try: self._source_reader.SetCurrentPosition(pos_com, prop) except OSError as e: warnings.warn(e) ole32.PropVariantClear(ctypes.byref(prop))
DIPH_DEVICE = 0 DIPH_BYOFFSET = 1 DIPH_BYID = 2 DIPH_BYUSAGE = 3 DISCL_EXCLUSIVE = 0x00000001 DISCL_NONEXCLUSIVE = 0x00000002 DISCL_FOREGROUND = 0x00000004 DISCL_BACKGROUND = 0x00000008 DISCL_NOWINKEY = 0x00000010 DIPROP_BUFFERSIZE = 1 GUID_XAxis = \ com.GUID(0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00) class DIDEVICEINSTANCE(ctypes.Structure): _fields_ = (('dwSize', DWORD), ('guidInstance', com.GUID), ('guidProduct', com.GUID), ('dwDevType', DWORD), ('tszInstanceName', WCHAR * MAX_PATH), ('tszProductName', WCHAR * MAX_PATH), ('guidFFDriver', com.GUID), ('wUsagePage', WORD), ('wUsage', WORD)) LPDIDEVICEINSTANCE = ctypes.POINTER(DIDEVICEINSTANCE) LPDIENUMDEVICESCALLBACK = ctypes.WINFUNCTYPE(BOOL, LPDIDEVICEINSTANCE, LPVOID)
import warnings from pyglet.image import * from pyglet.image.codecs import * from pyglet import com from pyglet.libs.win32.constants import * from pyglet.libs.win32.types import * from pyglet.libs.win32 import _kernel32 as kernel32 from pyglet.libs.win32 import _ole32 as ole32 CLSID_WICImagingFactory1 = com.GUID(0xcacaf262, 0x9370, 0x4615, 0xa1, 0x3b, 0x9f, 0x55, 0x39, 0xda, 0x4c, 0xa) CLSID_WICImagingFactory2 = com.GUID(0x317d06e8, 0x5f24, 0x433d, 0xbd, 0xf7, 0x79, 0xce, 0x68, 0xd8, 0xab, 0xc2) # This is available with Windows 7 with a Platform Update, but unable to detect as it wasn't a version change to the OS, # but a KB update. Available in atleast 8+. if WINDOWS_8_OR_GREATER: CLSID_WICImagingFactory = CLSID_WICImagingFactory2 else: CLSID_WICImagingFactory = CLSID_WICImagingFactory1 CLSCTX_INPROC_SERVER = 0x1 WICBitmapCreateCacheOption = UINT WICBitmapNoCache = 0 WICBitmapCacheOnDemand = 0x1 WICBitmapCacheOnLoad = 0x2 WICBITMAPCREATECACHEOPTION_FORCE_DWORD = 0x7fffffff WICBitmapPaletteType = UINT WICBitmapPaletteTypeCustom = 0
def _load_video(self, stream=MF_SOURCE_READER_FIRST_VIDEO_STREAM): self._video_stream_index = stream # Get what the native/real media type is (video only) imfmedia = IMFMediaType() try: self._source_reader.GetCurrentMediaType(self._video_stream_index, ctypes.byref(imfmedia)) except OSError as err: if err.winerror == MF_E_INVALIDSTREAMNUMBER: assert _debug('WMFVideoDecoder: No video stream found.') return assert _debug('WMFVideoDecoder: Found Video Stream') # All video is basically compressed, try to decompress. uncompressed_mt = IMFMediaType() MFCreateMediaType(ctypes.byref(uncompressed_mt)) imfmedia.CopyAllItems(uncompressed_mt) imfmedia.Release() uncompressed_mt.SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32) uncompressed_mt.SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive) uncompressed_mt.SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1) guid_type = com.GUID( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # TODO: Make GUID take no arguments for a null version. uncompressed_mt.GetGUID(MF_MT_SUBTYPE, ctypes.byref(guid_type)) try: self._source_reader.SetCurrentMediaType(self._video_stream_index, None, uncompressed_mt) except OSError as err: # Can't decode codec. raise MediaDecodeException(err) from None height, width = self._get_attribute_size(uncompressed_mt, MF_MT_FRAME_SIZE) self.video_format = VideoFormat(width=width, height=height) assert _debug('WMFVideoDecoder: Frame width: {} height: {}'.format( width, height)) # Frame rate den, num = self._get_attribute_size(uncompressed_mt, MF_MT_FRAME_RATE) self.video_format.frame_rate = num / den assert _debug('WMFVideoDecoder: Frame Rate: {} / {} = {}'.format( num, den, self.video_format.frame_rate)) # Sometimes it can return negative? Variable bit rate? Needs further tests and examples. if self.video_format.frame_rate < 0: self.video_format.frame_rate = 30000 / 1001 assert _debug( 'WARNING: Negative frame rate, attempting to use default, but may experience issues.' ) # Pixel ratio den, num = self._get_attribute_size(uncompressed_mt, MF_MT_PIXEL_ASPECT_RATIO) self.video_format.sample_aspect = num / den assert _debug('WMFVideoDecoder: Pixel Ratio: {} / {} = {}'.format( num, den, self.video_format.sample_aspect))
def _load_audio(self, stream=MF_SOURCE_READER_FIRST_AUDIO_STREAM): """ Prepares the audio stream for playback by detecting if it's compressed and attempting to decompress to PCM. Default: Only get the first available audio stream. """ # Will be an audio file. self._audio_stream_index = stream # Get what the native/real media type is (audio only) imfmedia = IMFMediaType() try: self._source_reader.GetNativeMediaType(self._audio_stream_index, 0, ctypes.byref(imfmedia)) except OSError as err: if err.winerror == MF_E_INVALIDSTREAMNUMBER: assert _debug('WMFAudioDecoder: No audio stream found.') return # Get Major media type (Audio, Video, etc) guid_audio_type = com.GUID( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # TODO: Make GUID take no arguments for a null version. imfmedia.GetGUID(MF_MT_MAJOR_TYPE, ctypes.byref(guid_audio_type)) if guid_audio_type == MFMediaType_Audio: assert _debug('WMFAudioDecoder: Found Audio Stream.') # Deselect any other streams if we don't need them. (Small speedup) if not self.decode_video: self._source_reader.SetStreamSelection( MF_SOURCE_READER_ANY_STREAM, False) # Select first audio stream. self._source_reader.SetStreamSelection( MF_SOURCE_READER_FIRST_AUDIO_STREAM, True) # Check sub media type, AKA what kind of codec guid_compressed = com.GUID(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) imfmedia.GetGUID(MF_MT_SUBTYPE, ctypes.byref(guid_compressed)) if guid_compressed == MFAudioFormat_PCM or guid_compressed == MFAudioFormat_Float: assert _debug('WMFAudioDecoder: Found Uncompressed Audio:', guid_compressed) else: assert _debug('WMFAudioDecoder: Found Compressed Audio:', guid_compressed) # If audio is compressed, attempt to decompress it by forcing source reader to use PCM mf_mediatype = IMFMediaType() MFCreateMediaType(ctypes.byref(mf_mediatype)) mf_mediatype.SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio) mf_mediatype.SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM) try: self._source_reader.SetCurrentMediaType( self._audio_stream_index, None, mf_mediatype) except OSError as err: # Can't decode codec. raise MediaDecodeException(err) from None # Current media type should now be properly decoded at this point. decoded_media_type = IMFMediaType( ) # Maybe reusing older IMFMediaType will work? self._source_reader.GetCurrentMediaType( self._audio_stream_index, ctypes.byref(decoded_media_type)) wfx_length = ctypes.c_uint32() wfx = POINTER(WAVEFORMATEX)() MFCreateWaveFormatExFromMFMediaType(decoded_media_type, ctypes.byref(wfx), ctypes.byref(wfx_length), 0) self._wfx = wfx.contents self.audio_format = AudioFormat( channels=self._wfx.nChannels, sample_size=self._wfx.wBitsPerSample, sample_rate=self._wfx.nSamplesPerSec) else: assert _debug('WMFAudioDecoder: Audio stream not found')
mfreadwrite_lib = ctypes.windll.LoadLibrary(mfreadwrite) mfplat_lib = ctypes.windll.LoadLibrary(mfplat) except OSError: # Doesn't exist? Should stop import of library. raise ImportError('Could not load WMF library.') MF_SOURCE_READERF_ERROR = 0x00000001 MF_SOURCE_READERF_ENDOFSTREAM = 0x00000002 MF_SOURCE_READERF_NEWSTREAM = 0x00000004 MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED = 0x00000010 MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED = 0x00000020 MF_SOURCE_READERF_STREAMTICK = 0x00000100 # Audio attributes MF_LOW_LATENCY = com.GUID(0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee) # Audio information MF_MT_ALL_SAMPLES_INDEPENDENT = com.GUID(0xc9173739, 0x5e56, 0x461c, 0xb7, 0x13, 0x46, 0xfb, 0x99, 0x5c, 0xb9, 0x5f) MF_MT_FIXED_SIZE_SAMPLES = com.GUID(0xb8ebefaf, 0xb718, 0x4e04, 0xb0, 0xa9, 0x11, 0x67, 0x75, 0xe3, 0x32, 0x1b) MF_MT_SAMPLE_SIZE = com.GUID(0xdad3ab78, 0x1990, 0x408b, 0xbc, 0xe2, 0xeb, 0xa6, 0x73, 0xda, 0xcc, 0x10) MF_MT_COMPRESSED = com.GUID(0x3afd0cee, 0x18f2, 0x4ba5, 0xa1, 0x10, 0x8b, 0xea, 0x50, 0x2e, 0x1f, 0x92) MF_MT_WRAPPED_TYPE = com.GUID(0x4d3f7b23, 0xd02f, 0x4e6c, 0x9b, 0xee, 0xe4, 0xbf, 0x2c, 0x6c, 0x69, 0x5d) MF_MT_AUDIO_NUM_CHANNELS = com.GUID(0x37e48bf5, 0x645e, 0x4c5b, 0x89, 0xde, 0xad, 0xa9, 0xe2, 0x9b, 0x69, 0x6a)
import warnings from pyglet.image import * from pyglet.image.codecs import * from pyglet import com from pyglet.libs.win32.constants import * from pyglet.libs.win32.types import * from pyglet.libs.win32 import _kernel32 as kernel32 from pyglet.libs.win32 import _ole32 as ole32 CLSID_WICImagingFactory1 = com.GUID(0xcacaf262, 0x9370, 0x4615, 0xa1, 0x3b, 0x9f, 0x55, 0x39, 0xda, 0x4c, 0xa) CLSID_WICImagingFactory2 = com.GUID(0x317d06e8, 0x5f24, 0x433d, 0xbd, 0xf7, 0x79, 0xce, 0x68, 0xd8, 0xab, 0xc2) # This is available with Windows 7 with a Platform Update, but unable to detect as it wasn't a version change to the OS, # but a KB update. Available in atleast 8+. if WINDOWS_8_OR_GREATER: CLSID_WICImagingFactory = CLSID_WICImagingFactory2 else: CLSID_WICImagingFactory = CLSID_WICImagingFactory1 WICBitmapCreateCacheOption = UINT WICBitmapNoCache = 0 WICBitmapCacheOnDemand = 0x1 WICBitmapCacheOnLoad = 0x2 WICBITMAPCREATECACHEOPTION_FORCE_DWORD = 0x7fffffff WICBitmapPaletteType = UINT WICBitmapPaletteTypeCustom = 0 WICBitmapTransformOptions = UINT
class PROPERTYKEY(ctypes.Structure): _fields_ = [ ('fmtid', com.GUID), ('pid', DWORD), ] def __repr__(self): return "PROPERTYKEY({}, pid={})".format(self.fmtid, self.pid) REFPROPERTYKEY = PROPERTYKEY PKEY_Device_FriendlyName = PROPERTYKEY( com.GUID(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), 14) PKEY_Device_DeviceDesc = PROPERTYKEY( com.GUID(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0), 2) PKEY_DeviceInterface_FriendlyName = PROPERTYKEY( com.GUID(0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22), 2) class IPropertyStore(com.pIUnknown): _methods_ = [ ('GetCount', com.STDMETHOD(POINTER(DWORD))), ('GetAt', com.STDMETHOD(DWORD, POINTER(PROPERTYKEY))), ('GetValue', com.STDMETHOD(REFPROPERTYKEY, POINTER(PROPVARIANT))), ('SetValue', com.STDMETHOD()), ('Commit', com.STDMETHOD()),
com.STDMETHOD(LPWAVEFORMATEX)), ('SetVolume', com.STDMETHOD(LONG)), ('SetPan', com.STDMETHOD(LONG)), ('SetFrequency', com.STDMETHOD(DWORD)), ('Stop', com.STDMETHOD()), ('Unlock', com.STDMETHOD(ctypes.c_void_p, DWORD, ctypes.c_void_p, DWORD)), ('Restore', com.STDMETHOD()), ] IID_IDirectSound3DListener = com.GUID( 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60) class IDirectSound3DListener(com.IUnknown): _methods_ = [ ('GetAllParameters', com.STDMETHOD(LPDS3DLISTENER)), ('GetDistanceFactor', com.STDMETHOD(PD3DVALUE)), ('GetDopplerFactor', com.STDMETHOD(PD3DVALUE)), ('GetOrientation', com.STDMETHOD(PD3DVECTOR, PD3DVECTOR)), ('GetPosition', com.STDMETHOD(PD3DVECTOR)), ('GetRolloffFactor', com.STDMETHOD(PD3DVALUE)),
('CreateDevice', com.STDMETHOD(ctypes.POINTER(com.GUID), ctypes.POINTER(IDirectInputDevice8), ctypes.c_void_p)), ('EnumDevices', com.STDMETHOD(DWORD, LPDIENUMDEVICESCALLBACK, LPVOID, DWORD)), ('GetDeviceStatus', com.STDMETHOD()), ('RunControlPanel', com.STDMETHOD()), ('Initialize', com.STDMETHOD()), ('FindDevice', com.STDMETHOD()), ('EnumDevicesBySemantics', com.STDMETHOD()), ('ConfigureDevices', com.STDMETHOD()), ] IID_IDirectInput8W = \ com.GUID(0xBF798031, 0x483A, 0x4DA2, 0xAA, 0x99, 0x5D, 0x64, 0xED, 0x36, 0x97, 0x00) lib.DirectInput8Create.argtypes = \ (ctypes.c_void_p, DWORD, com.LPGUID, ctypes.c_void_p, ctypes.c_void_p) class Element: value = None def __init__(self, object_instance): self.name = object_instance.tszName self._flags = object_instance.dwFlags self._guid = object_instance.guidType self._type = object_instance.dwType def get_value(self):