You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.3 KiB
105 lines
3.3 KiB
import typing
|
|
from decimal import Decimal, InvalidOperation
|
|
from logging import NullHandler, getLogger
|
|
|
|
from knowit.core import Rule
|
|
|
|
logger = getLogger(__name__)
|
|
logger.addHandler(NullHandler())
|
|
|
|
|
|
class AtmosRule(Rule):
|
|
"""Atmos rule."""
|
|
|
|
def __init__(self, config: typing.Mapping[str, typing.Mapping], name: str,
|
|
**kwargs):
|
|
"""Initialize an Atmos rule."""
|
|
super().__init__(name, **kwargs)
|
|
self.audio_codecs = getattr(config, 'AudioCodec')
|
|
|
|
def execute(self, props, pv_props, context):
|
|
"""Execute the rule against properties."""
|
|
profile = context.get('profile') or 'default'
|
|
format_commercial = pv_props.get('format_commercial')
|
|
if 'codec' in props and format_commercial and 'atmos' in format_commercial.lower():
|
|
props['codec'] = [props['codec'],
|
|
getattr(self.audio_codecs['ATMOS'], profile)]
|
|
|
|
|
|
class AudioChannelsRule(Rule):
|
|
"""Audio Channel rule."""
|
|
|
|
mapping = {
|
|
1: '1.0',
|
|
2: '2.0',
|
|
6: '5.1',
|
|
8: '7.1',
|
|
}
|
|
|
|
def execute(self, props, pv_props, context):
|
|
"""Execute the rule against properties."""
|
|
count = props.get('channels_count')
|
|
if count is None:
|
|
return
|
|
|
|
channels = self.mapping.get(count) if isinstance(count, int) else None
|
|
positions = pv_props.get('channel_positions') or []
|
|
positions = positions if isinstance(positions, list) else [positions]
|
|
candidate = 0
|
|
for position in positions:
|
|
if not position:
|
|
continue
|
|
|
|
c = Decimal('0.0')
|
|
for i in position.split('/'):
|
|
try:
|
|
c += Decimal(i.replace('.?', ''))
|
|
except (ValueError, InvalidOperation):
|
|
logger.debug('Invalid %s: %s', self.description, i)
|
|
pass
|
|
|
|
c_count = int(c) + int(round((c - int(c)) * 10))
|
|
if c_count == count:
|
|
return str(c)
|
|
|
|
candidate = max(candidate, c)
|
|
|
|
if channels:
|
|
return channels
|
|
|
|
if candidate:
|
|
return candidate
|
|
|
|
self.report(positions, context)
|
|
|
|
|
|
class DtsHdRule(Rule):
|
|
"""DTS-HD rule."""
|
|
|
|
def __init__(self, config: typing.Mapping[str, typing.Mapping], name: str,
|
|
**kwargs):
|
|
"""Initialize a DTS-HD Rule."""
|
|
super().__init__(name, **kwargs)
|
|
self.audio_codecs = getattr(config, 'AudioCodec')
|
|
self.audio_profiles = getattr(config, 'AudioProfile')
|
|
|
|
@classmethod
|
|
def _redefine(cls, props, name, index):
|
|
actual = props.get(name)
|
|
if isinstance(actual, list):
|
|
value = actual[index]
|
|
if value is None:
|
|
del props[name]
|
|
else:
|
|
props[name] = value
|
|
|
|
def execute(self, props, pv_props, context):
|
|
"""Execute the rule against properties."""
|
|
profile = context.get('profile') or 'default'
|
|
|
|
if props.get('codec') == getattr(self.audio_codecs['DTS'],
|
|
profile) and props.get('profile') in (
|
|
getattr(self.audio_profiles['MA'], profile),
|
|
getattr(self.audio_profiles['HRA'], profile)):
|
|
props['codec'] = getattr(self.audio_codecs['DTS-HD'], profile)
|