Skip to content
New issue

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

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

Already on GitHub? Sign in 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.

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

No branches or pull requests

3 participants