hzeller / rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
GNU General Public License v2.0
3.62k stars 1.15k forks source link

MPV player conflicting with LED matrix #1400

Open creating-worlds opened 2 years ago

creating-worlds commented 2 years ago

Hi there,

first of all thank you for this amazing library. It works like a charm!

My setup:

    options.rows = 32
    options.cols = 704
    options.chain_length = 1
    options.hardware_mapping = 'adafruit-hat-pwm'
    options.gpio_slowdown = 3
    options.brightness = 100
    options.pwm_lsb_nanoseconds=100
    options.pwm_bits = 7
    options.pwm_dither_bits = 0

Hardware:

Raspberry Pi 4
Raspberry Pi OS Bullseye (Headless)
Adafruit Bonnet with PWM fix

I am trying to play a video on an additional screen via HDMI (I am NOT trying to output a video on the Matrix). I am using the MPV Player (python-mpv) to output the video.

Here is my code (at least the important bits)

import mpv
import time
import threading
import socketio
import json
from rgbmatrix import RGBMatrix, RGBMatrixOptions, graphics

class SIO_Wrapper():
    current_channel = 0
    sio = socketio.Client()
   .......
    [MY SOCKETIO FUNCTIONS]
   .......

class VideoPlayer():

    def start_video_in_thread(self, video_name):
        thread = threading.Thread(target=self.play_video(video_name))
        thread.start()

    def play_video(self, video_name):
        print("start video")
        player = mpv.MPV(vo="gpu", gpu_context="drm", hwdec="rkmpp")  
        player.play("/path/to/vid/{}.mp4".format(video_name))
        player.wait_for_playback()
        print("stop video")

class MatrixManager():

    options = RGBMatrixOptions()
    options.rows = 32
    options.cols = 64
    options.chain_length = 1
    options.hardware_mapping = 'adafruit-hat-pwm'
    options.gpio_slowdown = 3
    options.brightness = 100
    options.pwm_lsb_nanoseconds=100
    options.pwm_bits = 7
    options.pwm_dither_bits = 0

    def __init__(self, *args, **kwargs):
        super(MatrixManager, self).__init__(*args, **kwargs)

    def initialize(self):      
        matrix = RGBMatrix(options = self.options)
        return matrix

if __name__ == "__main__":
    video_player=VideoPlayer()
    socket = SIO_Wrapper()
    socket.run()
    led_matrix = MatrixManager()
    matrix = led_matrix.initialize()

    while True:
        channel = socket.get_current_channel()
        if channel == 1:
            video_player.start_video_in_thread("TESTVIDEO")
            socket.set_current_channel(0)
            print("channel 0")   

First I thought this might be a threading issue with my socketio client but it turns out that there is a conflict with the matrix library. If I comment out matrix = led_matrix.initialize() the video plays perfectly. However, when the matrix was initialized before I try to play the video, it prints "start video" and without any output it prints "stop video" immediately after.

Do you have any idea why this is happening?

hzeller commented 2 years ago

I suspect you probably run into permission issues: when the matrix starts, it changes the permissions from root to an unprivileged user to minimize attack surface. However, if you then open files (such as, say, a movie file), that file needs to be able to be read by the new user (which is daemon).

So either make the file chmod a+r videofile.mp4 or set the runtime options of the matrix to not drop_privileges.