PyQt5 QtMultimedia 在播放 H.264 视频时显示黑屏

PyQt5 QtMultimedia 在播放 H.264 视频时显示黑屏

我们正在使用基于 PyQt5 的工具进行一些视频处理。几天以来,一些用户抱怨该工具只显示黑屏而不是视频。声音仍然有效。我们能够使用一个小脚本重现此问题:

import os
from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, path, parent=None):
        super(MainWindow, self).__init__(parent)

        video_widget = QtMultimediaWidgets.QVideoWidget()
        self.setCentralWidget(video_widget)
        self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(video_widget)
        self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(path)))
        self.player.play()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    file = "<file>.MP4"
    w = MainWindow(file)
    w.show()
    sys.exit(app.exec_())

奇怪的是,所有用户都使用基于 Ubuntu 18.04 的相同桌面,但只有少数用户受到此问题的影响。我看不出他们的安装有任何可能与此问题相关的差异。我发现了许多相关问题,其中大多数都已过时。这似乎是某种 gstreamer 问题。但我不知道如何深入研究这个主题。

答案1

不同系统上某些用户的管道不同,而其他用户则不同,这表明 VAAPI 存在问题。按照以下说明禁用 VAAPI 后,一切正常:暂时跳过decodebin中的vaapi解码器


有时,禁用 gstreamer 自动插入逻辑中的 vaapi 会很有用,例如当存在未决问题时,或者当需要强制在 decryptbin 中选择解码器以进行测试时。

标准可能性包括:

  • 彻底删除 gstreamer-vaapi
  • 覆盖插件排名系统以将 vaapi 插件降级到其他替代方案以下 - 这需要使用 gstreamer API,但 gst-launch 或 totem 无法使用。

我发现了一种更简单的方法:将 LIBVA_DRIVER_NAME 定义为一个假值,这将强制 vaapi 初始化失败,从而跳过其插件。

例如:

LIBVA_DRIVER_NAME=fakedriver gst-launch-1.0 playbin uri=file:///tmp/file.mp4

没有它:

$ gst-launch-1.0 playbin uri=file://`pwd`/bbb-1920-1080-30.mp4
Got context from element 'vaapisink0': gst.vaapi.Display=context, gst.vaapi.Display=(GstVaapiDisplay)"\(GstVaapiDisplayGLX\)\ vaapidisplayglx0";

通过环境变量,我们可以看到已经选择了 avdec_h264:

LIBVA_DRIVER_NAME=fakedriver gst-launch-1.0 playbin uri=file://`pwd`/bbb-1920-1080-30.mp4 -v
...
/GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/avdec_h264:avdec_h264-0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, level=(string)4.1, profile=(string)high, codec_data=(buffer)01640029ffe1001b67640029acca501e0089f970110000030001000003003c8f18319601000568e93b2c8b, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, parsed=(boolean)true

相关内容