Closed kanehekili closed 4 months ago
Asking upstream, I got an answer about the "glue code" (aka python-mpv) - which I didn't quite understand. To make things easier, I've created a gist-could you have a look at it?
@kanehekili I think you just called MPV.play
too early, before the MPVRenderContext
was registered, which caused libmpv to fall back to the standard opengl vo. I've modified the code from your gist, and it works on my machine. It plays the test file from the tests
dir of this repo when you press the play button:
#!/usr/bin/env python
'''
Created on 3 May 2024
@author: matze
(modified by jaseg)
'''
from PyQt6 import QtWidgets
"""
based on:
https://github.com/mpv-player/mpv-examples/blob/master/libmpv/qt_opengl/mpvwidget.cpp
https://gitlab.com/robozman/python-mpv-qml-example/-/blob/master/main.py?ref_type=heads
"""
from PyQt6.QtWidgets import QApplication
from PyQt6.QtGui import QOpenGLContext, QPainter, QBrush, QColor, QCloseEvent
from PyQt6.QtCore import QByteArray, pyqtSignal, pyqtSlot, Qt
from PyQt6.QtOpenGLWidgets import QOpenGLWidget
from mpv import MPV, MpvGlGetProcAddressFn, MpvRenderContext
import ctypes,sys
def get_process_address(_, name):
glctx = QOpenGLContext.currentContext()
address = int(glctx.getProcAddress(QByteArray(name)))
#return ctypes.cast(address, ctypes.c_void_p).value
return address
class Player(QOpenGLWidget):
onUpdate = pyqtSignal()
initialized = pyqtSignal()
def __init__(self, parent) -> None:
super().__init__(parent)
self.mpv = MPV(vo='libmpv')
self.ctx = None
self._proc_addr_wrapper = MpvGlGetProcAddressFn(get_process_address)
self.onUpdate.connect(self.do_update)
self.c = 0
self.setUpdateBehavior(QOpenGLWidget.UpdateBehavior.PartialUpdate)
def initializeGL(self) -> None:
self.ctx = MpvRenderContext(
self.mpv, 'opengl',
opengl_init_params={
'get_proc_address': self._proc_addr_wrapper
},
)
if self.ctx:
self.ctx.update_cb = self.on_update
self.initialized.emit()
def paintGL(self) -> None:
if self.c > 100:
self.c = 0
else:
self.c += 1
rect = self.rect()
if self.ctx:
fbo = self.defaultFramebufferObject()
self.ctx.render(flip_y=True, opengl_fbo={'w': rect.width(), 'h': rect.height(), 'fbo': fbo})
def do_update(self):
self.update()
@pyqtSlot()
def on_update(self):
self.onUpdate.emit()
def play(self, url):
self.mpv.play(url)
def closeEvent(self, event: QCloseEvent) -> None:
"""free mpv_context and terminate player brofre closing the widget"""
self.ctx.free()
self.mpv.terminate()
event.accept()
class MainFrame(QtWidgets.QMainWindow):
def __init__(self, qapp,aPath=None):
self._isStarted=False
self.__qapp=qapp
super(MainFrame, self).__init__()
self.initUI()
self.centerWindow()
self.show()
def initUI(self):
self.player = Player(self)
self.uiLabel= QtWidgets.QLabel(self)
self.uiLabel.setText("Player demo")
self.uiPlayButton = QtWidgets.QPushButton(" Play")
box = self._makeLayout()
wid = QtWidgets.QWidget(self)
self.setCentralWidget(wid)
wid.setLayout(box)
self.resize(500, 600)
self.uiPlayButton.clicked.connect(lambda: self.player.mpv.loadfile('https://raw.githubusercontent.com/jaseg/python-mpv/main/tests/test.webm'))
def _makeLayout(self):
mainBox = QtWidgets.QVBoxLayout() # for all
btn1Box = QtWidgets.QHBoxLayout() # test widgets
btn1Box.setSpacing(20)
btn1Box.addWidget(self.uiLabel)
btn1Box.addWidget(self.uiPlayButton)
mainBox.addWidget(self.player)
mainBox.addLayout(btn1Box)
return mainBox
def centerWindow(self):
frameGm = self.frameGeometry()
centerPoint = self.screen().availableGeometry().center()
frameGm.moveCenter(centerPoint)
self.move(frameGm.topLeft())
if __name__ == '__main__':
app = QApplication(sys.argv)
import locale
locale.setlocale(locale.LC_NUMERIC, "C")
WIN = MainFrame(app)
app.exec()
Well, thanks - but I need to have the first frame displayed on startup (used by videcut on GitHub). The crucial change was to set "vo:libmpv"
, which wasn't necessary before... Is there some kind of event that could notify me when the MPVRenderContext
is initialized?
Using your mpv.py for my project I'm embedding MPV with the QOpenGLWidget. With the latest libmpv.so a new window is created on X11. Not using OPENGL would render the application useless for the Wayland compositor. Is this a glitch in the underlying lib?
I can confirm that libmpv.so.2.2.0 works and libmpv.so.2.3.0 doesn't.