-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput_source.py
More file actions
94 lines (86 loc) · 3.56 KB
/
Copy pathinput_source.py
File metadata and controls
94 lines (86 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import sys
import imageio_ffmpeg
import subprocess as sp
class InputSource:
@staticmethod
def get_cam_inputname(index):
if sys.platform.startswith("win"):
CAM_FORMAT = "dshow" # dshow or vfwcap
elif sys.platform.startswith("linux"):
CAM_FORMAT = "video4linux2"
elif sys.platform.startswith("darwin"):
CAM_FORMAT = "avfoundation"
else: # pragma: no cover
CAM_FORMAT = "unknown-cam-format"
if sys.platform.startswith("linux"):
name_ = f"<video{index}>"
return "/dev/" + name[1:-1]
elif sys.platform.startswith("win"):
# Ask ffmpeg for list of dshow device names
ffmpeg_api = imageio_ffmpeg
cmd = [
ffmpeg_api.get_ffmpeg_exe(),
"-list_devices",
"true",
"-f",
CAM_FORMAT,
"-i",
"dummy",
]
# Set `shell=True` in sp.run to prevent popup of a command
# line window in frozen applications. Note: this would be a
# security vulnerability if user-input goes into the cmd.
# Note that the ffmpeg process returns with exit code 1 when
# using `-list_devices` (or `-list_options`), even if the
# command is successful, so we set `check=False` explicitly.
completed_process = sp.run(
cmd,
stdout=sp.PIPE,
stderr=sp.PIPE,
encoding="utf-8",
shell=True,
check=False,
)
# Return device name at index
try:
name = InputSource._parse_device_names(completed_process.stderr)[index]
except IndexError:
raise IndexError("No ffdshow camera at index %i." % index)
return "video=%s" % name
elif sys.platform.startswith("darwin"):
name = str(index)
return name
else: # pragma: no cover
return "??"
@staticmethod
def _parse_device_names(ffmpeg_output):
"""Parse the output of the ffmpeg -list-devices command"""
device_names = []
in_video_devices = False
for line in ffmpeg_output.splitlines():
if line.startswith("[dshow"):
line = line.split("]", 1)[1].strip()
if in_video_devices and line.startswith('"'):
friendly_name = line[1:-1]
device_names.append([friendly_name, ""])
elif in_video_devices and line.lower().startswith("alternative name"):
alt_name = line.split(" name ", 1)[1].strip()[1:-1]
if sys.platform.startswith("win"):
alt_name = alt_name.replace("&", "^&")
else:
alt_name = alt_name.replace("&", "\\&")
device_names[-1][-1] = alt_name
elif "video devices" in line:
in_video_devices = True
elif "devices" in line:
# set False for subsequent "devices" sections
in_video_devices = False
device_names2 = []
for friendly_name, alt_name in device_names:
if friendly_name not in device_names2:
device_names2.append(friendly_name)
elif alt_name:
device_names2.append(alt_name)
else:
device_names2.append(friendly_name) # duplicate, but not much we can do
return device_names2