Skip to content

Instantly share code, notes, and snippets.

@virtuald
Last active May 5, 2017 06:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save virtuald/3acbb802b26cc595bbe6690346ece556 to your computer and use it in GitHub Desktop.
Save virtuald/3acbb802b26cc595bbe6690346ece556 to your computer and use it in GitHub Desktop.
GStreamer Windows Audio Thread Priority hack
#
# Proof of concept to hack around lack of thread priority in GStreamer on
# Windows. See https://bugzilla.gnome.org/show_bug.cgi?id=781998
#
from __future__ import print_function
from ctypes.wintypes import BOOL, DWORD, HANDLE, LPCWSTR
import ctypes as C
avrt_dll = C.windll.LoadLibrary("avrt.dll")
AvSetMmThreadCharacteristics = avrt_dll.AvSetMmThreadCharacteristicsW
AvSetMmThreadCharacteristics.argtypes = [LPCWSTR, C.POINTER(DWORD)]
AvSetMmThreadCharacteristics.restype = HANDLE
AvRevertMmThreadCharacteristics = avrt_dll.AvRevertMmThreadCharacteristics
AvRevertMmThreadCharacteristics.argtypes = [HANDLE]
AvRevertMmThreadCharacteristics.restype = BOOL
GetCurrentThreadId = C.windll.LoadLibrary("kernel32.dll").GetCurrentThreadId
GetCurrentThreadId.argtypes = []
GetCurrentThreadId.restype = DWORD
#
# GST playbin boilerplate
#
from os.path import abspath
import sys
#import os
#os.environ.setdefault('GST_DEBUG_DUMP_DOT_DIR', '.')
from gi.repository import Gst, GObject
def on_stream_status(bus, message):
status = message.parse_stream_status()
# A gstreamer thread starts
if status.type == Gst.StreamStatusType.ENTER:
obj = message.get_stream_status_object()
# note that we use "Pro Audio" because it gives a higher priority, and
# that's what Chrome does anyways...
unused = DWORD()
obj.task_handle = AvSetMmThreadCharacteristics("Pro Audio", C.byref(unused))
# A gstreamer thread ends
elif status.type == Gst.StreamStatusType.LEAVE:
obj = message.get_stream_status_object()
task_handle = getattr(obj, 'task_handle', None)
if task_handle:
AvRevertMmThreadCharacteristics(task_handle)
if __name__ == '__main__':
Gst.init(None)
player = Gst.ElementFactory.make('playbin')
player.props.uri = 'file:///%s' % abspath(sys.argv[1]).replace('\\', '/')
bus = player.get_bus()
bus.connect('sync-message::stream-status', on_stream_status)
bus.enable_sync_message_emission()
player.set_state(Gst.State.PLAYING)
ml = GObject.MainLoop()
ml.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment