Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

threading-related crash after multiple video playbacks #88

Open
r41d opened this issue Jul 17, 2019 · 6 comments
Open

threading-related crash after multiple video playbacks #88

r41d opened this issue Jul 17, 2019 · 6 comments

Comments

@r41d
Copy link

r41d commented Jul 17, 2019

I have a program where mpv is called multiple times, like, every minute, but the previous playback is always done before a new one is started.
After about 16 times I get the following crash:

Fatal Python error: PyEval_SaveThread: NULL tstate

Thread 0x00007f343a012700 (most recent call first):
  File "/home/lbuhl/.local/lib/python3.7/site-packages/mpv.py", line 445 in _event_generator
  File "/home/lbuhl/.local/lib/python3.7/site-packages/mpv.py", line 452 in _event_loop
  File "/usr/lib/python3.7/threading.py", line 865 in run
  File "/usr/lib/python3.7/threading.py", line 917 in _bootstrap_inner
  File "/usr/lib/python3.7/threading.py", line 885 in _bootstrap

Thread 0x00007f346ce63740 (most recent call first):
  File "./main.py", line 239 in run
  File "./main.py", line 281 in <module>
Aborted (core dumped)

Unfortunately I have no idea how to deal with this crash :/

The code that invokes mpv looks like this (part of a game made with pygame):

    def play_demo_video(self, video_file_name):
        video_player = mpv.MPV(input_default_bindings=True, input_vo_keyboard=True)

        # When the video plays we want to disable input for the game
        self._disable_input_for_video = True

        def cleanup_mpv():
            # Clean up the helpers
            video_player.terminate()
            self._disable_input_for_video = False
            self.get_screen()._last_action_timestamp = datetime.now()
            # make pygame grab the focus again
            subprocess.call(["wmctrl", "-a", PROGRAM_NAME])

        # This ends MPV and sets up the game back to its normal state
        @video_player.on_key_press('q')
        def my_q_binding():
            cleanup_mpv()

        @video_player.event_callback('END_FILE')
        def video_finished_handler(event):
            cleanup_mpv()

        video_player.fullscreen = True
        video_player['vo'] = 'gpu'
        video_player.play(video_file_name)

Any advice would be appreciated.

@McSinyx
Copy link
Contributor

McSinyx commented Jul 18, 2019

Do you really need to create another MPV instance every call? If that is really needed, try video_player.quit() at the end of the function.

@r41d
Copy link
Author

r41d commented Jul 18, 2019

I tried out a bit and for me this works best:

    def play_demo_video(self, video_file_name):
        video_player = mpv.MPV(input_default_bindings=True, input_vo_keyboard=True)

        # When the video plays we want to disable gamepad input for the game
        self._disable_input_for_video = True

        # In order to quit the mpv on any button press, we use "antimicro" to map controller input to the q button
        # on demand and exit mpv that way. Don't know if there's a better option or not
        antimicro = subprocess.Popen(["antimicro", "-d", "--hidden", "--profile", "controller_q_map.gamecontroller.amgp"])

        def cleanup_mpv():
            # Clean up the helpers
            self._disable_input_for_video = False
            self.get_screen()._last_action_timestamp = datetime.now()
            # make pygame grab the focus again
            subprocess.call(["wmctrl", "-a", PROGRAM_NAME])

        @video_player.on_key_press('q')
        def my_q_binding():
            video_player.quit()
            cleanup_mpv()

        @video_player.event_callback('END_FILE')
        def video_finished_handler(event):
            video_player.terminate()
            cleanup_mpv()

        ...

With the quit for when we press q and the terminate for when the file ended. Most other combinations lead to Core Dump crashes...

@McSinyx
Copy link
Contributor

McSinyx commented Jul 18, 2019

If you use mpv to play videos (since I assume normal human cannot watch more than one video at the same time), why don't you keep an MPV instance as a variable in the scope of the game that call it, or a attribute of the class if you're doing OO?

@r41d
Copy link
Author

r41d commented Jul 18, 2019

I want to go back to the game when no video is playing.
For this I would need the MPV window to go away without shutting down the mpv instance.
How would I achieve that?

@McSinyx
Copy link
Contributor

McSinyx commented Jul 19, 2019

You can try to cycle the video property either through the API or by the binding _.

@jaseg
Copy link
Owner

jaseg commented Nov 10, 2019

What might work is providing mpv with a window to draw into using the --wid option. As far as I know that "window" can be a GUI component such as a panel that is part of another window on most platforms and GUI frameworks. Perhaps it is then possible to hide/show that GUI component, thereby hiding/showing the mpv window. The PyQt embedding example might be a good starting point for experiments here.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants