在 Raspberry Pi 5 上使用 ffmpeg 和 SDL2 播放视频

问题描述 投票:0回答:1

我想创建一个 python 脚本,解码 h264 1080p 视频并通过 Raspberry Pi 5 上的 SDL2 输出。Raspberry Pi 5 能够使用 VLC 毫无问题地播放 h264 1080p 视频。 VLC 的总 CPU 负载约为 10%。然而,使用 ffmpeg 解码并通过 SDL2 输出使用大约 70% 的 CPU 负载。由于我希望能够在两个输出视频之间无缝切换,因此我需要同时解码两个视频。因此,一个转码后的 1080p 视频的 70% CPU 负载是不可接受的。如何使代码更高效?为什么 VLC 如此高效?

这是我当前的Python脚本:

import numpy as np
import ffmpeg  # ffmpeg-python
import sdl2.ext

in_file = ffmpeg.input('bbb1080_x264.mp4', re=None)

width = 1920
height = 1080

process1 = (
    in_file
    .output('pipe:', format='rawvideo', pix_fmt='bgra')
    .run_async(pipe_stdout=True)
)

sdl2.ext.init()
window = sdl2.ext.Window("Hello World!", size=(width, height))
window.show()
windowsurface = sdl2.SDL_GetWindowSurface(window.window)
windowArray = sdl2.ext.pixels3d(windowsurface.contents)

sdl2.ext.mouse.hide_cursor()

while True:
    in_bytes = process1.stdout.read(width * height * 4)

    if not in_bytes:
        break

    in_frame = (
        np
        .frombuffer(in_bytes, np.uint8)
        .reshape([height, width, 4])
        .transpose(1, 0, 2)
    )

    for event in sdl2.ext.get_events():
        if event.type == sdl2.SDL_QUIT:
            exit()

    windowArray[:] = in_frame
    window.refresh()

process1.wait()

有趣的是,当我在 Raspberry Pi 5 上启动 VLC 时,这是终端上的输出

[00007fff78c1a550] avcodec decoder error: cannot start codec (h264_v4l2m2m)
Fontconfig warning: ignoring UTF-8: not a valid region tag
[00007fff68002d70] gles2 generic error: parent window not available
[00007fff68002d70] xcb generic error: window not available
[00007fff680013f0] mmal_xsplitter vout display: Try drm
[00007fff68002d70] drm_vout generic: <<< OpenDrmVout: Fmt=I420
[00007fff68002d70] drm_vout generic error: Failed to get xlease`

这表明VLC没有使用h264_v4l2m2m硬件加速。

python ffmpeg raspberry-pi sdl-2 ffmpeg-python
1个回答
0
投票

我想出了如何减少处理器负载:

  1. 启用解码硬件加速
  2. 禁用格式转换
  3. 避免标准输出

更改后的代码:

in_file = ffmpeg.input('bbb1080_hevc.mp4', hwaccel='auto')

width = 1920
height = 1080

process1 = (
    in_file
    .output('/dev/null', format='rawvideo')
    .run_async(pipe_stdout=True)
)

但是这个代码现在当然无法使用了。我需要处理 python 中的格式转换并找出标准输出如此慢的原因。我改用 C,因为我应该从一开始就这样做,@qwr 已经在他的评论中建议了。

© www.soinside.com 2019 - 2024. All rights reserved.