QMediaPlayer crashes when created in response to drop event

122 Views Asked by At

I'm trying to play a video with QMediaPlayer in response to a drag and drop event, and I find that it works or doesn't work depending on where the player is instantiated. Am I doing something obviously wrong here?

Details: Qt 6.4.2, Python 3.11.2, Apple M2 Pro, macOS 13.2.1

(Background: My app allows (a variable number of) videos to be loaded simultaneously when the user drops videos, and I want each to have its own QMediaPlayer. Hence the need to instantiate the player in response to a drop event.)

Here is a minimal example highlighting the issue. This works fine when EARLY = True, and gives a segfault when EARLY = False.

#!/usr/bin/env python3
# encoding: utf-8

import os
import sys
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QUrl, qVersion
from PySide6.QtWidgets import QMainWindow
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget

# Drag and drop a video file into the window to play it
# e.g., http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4
#
# Crashes on macOS when EARLY = False; works when EARLY = True
# (Qt 6.4.2, Python 3.11.2, Apple M2 Pro, macOS 13.2.1)

EARLY = True     # segfault when `False`

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(800, 600)
        self.setWindowTitle('Qt6 Video Player')
        self.setAcceptDrops(True)

        if EARLY:
            self.player = QMediaPlayer()

    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls():
            e.acceptProposedAction()

    def dropEvent(self, e):
        paths = [os.path.abspath(url.toLocalFile())
                 for url in e.mimeData().urls()]

        if not EARLY:
            self.player = QMediaPlayer()

        videoWidget = QVideoWidget()
        self.setCentralWidget(videoWidget)

        self.player.errorOccurred.connect(self.mediaErrorOccured)
        self.player.setVideoOutput(videoWidget)
        self.player.setSource(QUrl.fromLocalFile(paths[0]))
        self.player.play()

    def mediaErrorOccured(self, error, message):
        print('error:', error, message)


if __name__ == '__main__':
    print(f'Qt version {qVersion()}')
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()
0

There are 0 best solutions below