Build: Include coders specific to hwaccell APIs

This commit is contained in:
Ross Patterson 2019-08-09 15:10:29 -07:00
parent ca427cb904
commit 130457ffe1
3 changed files with 63 additions and 19 deletions

View File

@ -40,6 +40,8 @@ CODEC_DESCRIPTION_RE = re.compile(
CODEC_CODERS_RE = re.compile(
r' \((?P<type>(de|en)coders): (?P<coders>[^)]+) \)')
HWACCEL_SYNONYMS = dict(cuvid=['nvenc', 'nvdec', 'cuda'])
FILTER_RE = re.compile(
r'^ (?P<timeline>[T.])(?P<slice>[S.])(?P<command>[C.]) '
r'(?P<name>[^ ]+) +(?P<io>[^ ]+) +(?P<description>.+)$',
@ -248,22 +250,53 @@ def get_hw_devices(cmd='ffmpeg'):
def get_hwaccels(cmd='ffmpeg'):
"""
Extract the hwaccels of the ffmpeg build.
Extract the hwaccels of the ffmpeg build, including specific codecs.
Return all the hardware acceleration APIs supported by this build
including all the codecs that are specific to the API.
"""
data = dict(codecs=get_codecs(cmd=cmd), hwaccels=[])
stdout = _run([cmd, '-hwaccels'])
return stdout.split('\n')[1:-2]
hwaccel_names = stdout.split('\n')[1:-2]
for hwaccel_name in hwaccel_names:
hwaccel = dict(name=hwaccel_name)
data['hwaccels'].append(hwaccel)
hwaccel['codecs'] = hwaccel_codecs = {}
for codec_name, codec in data['codecs'].items():
hwaccel_codec = {}
for coders_key in ('decoders', 'encoders'):
matching_coders = []
for coder in codec.get(coders_key, []):
for synonym in (
[hwaccel_name] +
HWACCEL_SYNONYMS.get(hwaccel_name, [])):
if (
coder == synonym or
'_' + synonym in coder or
synonym + '_' in coder):
matching_coders.append(coder)
break
if matching_coders:
hwaccel_codec[coders_key] = matching_coders
if hwaccel_codec:
hwaccel_codecs[codec_name] = hwaccel_codec
return data
def get_build_data(cmd='ffmpeg'):
"""
Extract details about the ffmpeg build.
"""
hwaccels_data = get_hwaccels(cmd=cmd)
return dict(
version=get_version(cmd=cmd),
formats=get_formats(cmd=cmd),
demuxers=get_demuxers(cmd=cmd),
muxers=get_muxers(cmd=cmd),
codecs=get_codecs(cmd=cmd),
codecs=hwaccels_data['codecs'],
bsfs=get_bsfs(cmd=cmd),
protocols=get_protocols(cmd=cmd),
filters=get_filters(cmd=cmd),
@ -273,7 +306,7 @@ def get_build_data(cmd='ffmpeg'):
colors=get_colors(cmd=cmd),
devices=get_devices(cmd=cmd),
hw_devices=get_hw_devices(cmd=cmd),
hwaccels=get_hwaccels(cmd=cmd))
hwaccels=hwaccels_data['hwaccels'])
__all__ = [
'get_build_data',

View File

@ -43,10 +43,6 @@ HWACCELS_BY_PERFORMANCE = [
'qsv', 'd3d11va', 'dxva2', 'vaapi', 'drm']
# Loaded from JSON
DATA = None
# Some accelerated codecs use a different prefix than the base codec
CODEC_SYNONYMS = {
'mpeg1video': 'mpeg1',
'mpeg2video': 'mpeg2'}
def detect_gpu():
@ -67,14 +63,15 @@ def detect_hwaccels(hwaccels=None, cmd='ffmpeg'):
Extract details about the ffmpeg build.
"""
# Filter against what's available in the ffmpeg build
build_hwaccels = ffmpeg.get_hwaccels(cmd=cmd)
hwaccels_data = ffmpeg.get_hwaccels(cmd=cmd)
if hwaccels is None:
# Consider all the available hwaccels
hwaccels = build_hwaccels
hwaccels = hwaccels_data['hwaccels']
else:
# Support passing in a restricted set of hwaccels
hwaccels = [
hwaccel for hwaccel in hwaccels if hwaccel in build_hwaccels]
hwaccel for hwaccel in hwaccels_data['hwaccels']
if hwaccel['name'] in hwaccels]
# Filter against which APIs are available on this OS+GPU
data = _get_data()
@ -82,16 +79,18 @@ def detect_hwaccels(hwaccels=None, cmd='ffmpeg'):
gpu = detect_gpu()
api_avail = data['hwaccels']['api_avail'][plat_sys][
gpu['vendor'].replace(' Corporation', '')]
hwaccels = [hwaccel for hwaccel in hwaccels if hwaccel in api_avail]
hwaccels = [
hwaccel for hwaccel in hwaccels if hwaccel['name'] in api_avail]
hwaccels.sort(key=lambda hwaccel: (
# Sort unranked hwaccels last, but in the order given by ffmpeg
hwaccel not in HWACCELS_BY_PERFORMANCE,
hwaccel['name'] in HWACCELS_BY_PERFORMANCE and 1 or 0,
(
# Sort ranked hwaccels per the constant
hwaccel in HWACCELS_BY_PERFORMANCE and
HWACCELS_BY_PERFORMANCE.index(hwaccel))))
return hwaccels
hwaccel['name'] in HWACCELS_BY_PERFORMANCE and
HWACCELS_BY_PERFORMANCE.index(hwaccel['name']))))
hwaccels_data['hwaccels'] = hwaccels
return hwaccels_data
def detect_coder(

View File

@ -727,7 +727,16 @@ def test__build_data():
assert isinstance(data['version'], str)
for fields_key in {'formats', 'demuxers', 'muxers', 'codecs', 'filters'}:
assert isinstance(data['codecs'], dict)
for codec, coders in data['codecs'].items():
assert isinstance(codec, str)
assert isinstance(coders, dict)
assert isinstance(data['hwaccels'], list)
for hwaccel in data['hwaccels']:
assert isinstance(hwaccel, dict)
assert 'name' in hwaccel
for fields_key in {'formats', 'demuxers', 'muxers', 'filters'}:
assert isinstance(data[fields_key], dict)
list_keys = {'bsfs'}
@ -741,10 +750,13 @@ def test__build_data():
def test__detect():
for hwaccels in [
for hwaccels_data in [
ffmpeg.detect_hwaccels(),
ffmpeg.detect_hwaccels(['foohwaccel'])]:
assert isinstance(hwaccels, list)
assert isinstance(hwaccels_data['hwaccels'], list)
for hwaccel in hwaccels_data['hwaccels']:
assert isinstance(hwaccel, dict)
assert 'name' in hwaccel
for codecs in [
ffmpeg.detect_codecs('h264', 'h264'),