Skip to content

Commit

Permalink
Auto select gpu for hwaccel presets (blakeblackshear#5406)
Browse files Browse the repository at this point in the history
* Add ability to GPU device to be automatically detected when multiple exist

* Add logging info

* Fix access

* Fix

* Formatting

* Fix path of device

* Use log error instead of raise

* Remove log which could apply to other caess

* Set default value

* rework logic and support auto gpu selection for encoding gpu as well
  • Loading branch information
NickM-27 authored Feb 11, 2023
1 parent babd976 commit 562e262
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
47 changes: 43 additions & 4 deletions frigate/ffmpeg_presets.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
"""Handles inserting and maintaining ffmpeg presets."""

import logging
import os

from typing import Any

from frigate.version import VERSION
from frigate.const import BTBN_PATH
from frigate.util import vainfo_hwaccel


logger = logging.getLogger(__name__)


class LibvaGpuSelector:
"Automatically selects the correct libva GPU."

_selected_gpu = None

def get_selected_gpu(self) -> str:
"""Get selected libva GPU."""
if not os.path.exists("/dev/dri"):
return ""

if self._selected_gpu:
return self._selected_gpu

devices = list(filter(lambda d: d.startswith("render"), os.listdir("/dev/dri")))

if len(devices) < 2:
self._selected_gpu = "/dev/dri/renderD128"
return self._selected_gpu

for device in devices:
check = vainfo_hwaccel(device_name=device)

logger.debug(f"{device} return vainfo status code: {check.returncode}")

if check.returncode == 0:
self._selected_gpu = f"/dev/dri/{device}"
return self._selected_gpu

return ""


TIMEOUT_PARAM = "-timeout" if os.path.exists(BTBN_PATH) else "-stimeout"

_gpu_selector = LibvaGpuSelector()
_user_agent_args = [
"-user_agent",
f"FFmpeg Frigate/{VERSION}",
Expand All @@ -23,15 +61,15 @@
"-hwaccel",
"vaapi",
"-hwaccel_device",
"/dev/dri/renderD128",
_gpu_selector.get_selected_gpu(),
"-hwaccel_output_format",
"vaapi",
],
"preset-intel-qsv-h264": [
"-hwaccel",
"qsv",
"-qsv_device",
"/dev/dri/renderD128",
_gpu_selector.get_selected_gpu(),
"-hwaccel_output_format",
"qsv",
"-c:v",
Expand All @@ -43,7 +81,7 @@
"-hwaccel",
"qsv",
"-qsv_device",
"/dev/dri/renderD128",
_gpu_selector.get_selected_gpu(),
"-hwaccel_output_format",
"qsv",
"-c:v",
Expand Down Expand Up @@ -95,7 +133,7 @@
PRESETS_HW_ACCEL_ENCODE = {
"preset-rpi-32-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m -g 50 -bf 0 {1}",
"preset-rpi-64-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m -g 50 -bf 0 {1}",
"preset-vaapi": "ffmpeg -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi {0} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {1}",
"preset-vaapi": "ffmpeg -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device {2} {0} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {1}",
"preset-intel-qsv-h264": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}",
"preset-intel-qsv-h265": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}",
"preset-nvidia-h264": "ffmpeg -hide_banner {0} -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll {1}",
Expand Down Expand Up @@ -143,6 +181,7 @@ def parse_preset_hardware_acceleration_encode(arg: Any, input: str, output: str)
return PRESETS_HW_ACCEL_ENCODE.get(arg, PRESETS_HW_ACCEL_ENCODE["default"]).format(
input,
output,
_gpu_selector.get_selected_gpu(),
)


Expand Down
10 changes: 7 additions & 3 deletions frigate/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from collections import Counter
from collections.abc import Mapping
from multiprocessing import shared_memory
from typing import Any, AnyStr, Tuple
from typing import Any, AnyStr, Optional, Tuple

import cv2
import numpy as np
Expand Down Expand Up @@ -976,9 +976,13 @@ def ffprobe_stream(path: str) -> sp.CompletedProcess:
return sp.run(ffprobe_cmd, capture_output=True)


def vainfo_hwaccel() -> sp.CompletedProcess:
def vainfo_hwaccel(device_name: Optional[str] = None) -> sp.CompletedProcess:
"""Run vainfo."""
ffprobe_cmd = ["vainfo"]
ffprobe_cmd = (
["vainfo"]
if not device_name
else ["vainfo", "--display", "drm", "--device", f"/dev/dri/{device_name}"]
)
return sp.run(ffprobe_cmd, capture_output=True)


Expand Down

0 comments on commit 562e262

Please sign in to comment.