2014-06-01 04:11:04 +00:00
|
|
|
|
using MediaBrowser.Model.Extensions;
|
|
|
|
|
using MediaBrowser.Model.MediaInfo;
|
2014-04-29 03:56:20 +00:00
|
|
|
|
using System;
|
2016-12-13 17:04:37 +00:00
|
|
|
|
using System.Collections.Generic;
|
2016-10-22 02:08:34 +00:00
|
|
|
|
using System.Globalization;
|
2016-12-13 17:04:37 +00:00
|
|
|
|
using System.Linq;
|
2014-04-24 05:08:10 +00:00
|
|
|
|
|
|
|
|
|
namespace MediaBrowser.Model.Dlna
|
|
|
|
|
{
|
|
|
|
|
public class ConditionProcessor
|
|
|
|
|
{
|
|
|
|
|
public bool IsVideoConditionSatisfied(ProfileCondition condition,
|
|
|
|
|
int? width,
|
|
|
|
|
int? height,
|
|
|
|
|
int? bitDepth,
|
|
|
|
|
int? videoBitrate,
|
|
|
|
|
string videoProfile,
|
|
|
|
|
double? videoLevel,
|
2014-06-23 16:05:19 +00:00
|
|
|
|
float? videoFramerate,
|
2014-04-24 05:08:10 +00:00
|
|
|
|
int? packetLength,
|
2014-06-22 16:25:47 +00:00
|
|
|
|
TransportStreamTimestamp? timestamp,
|
2014-09-09 01:15:31 +00:00
|
|
|
|
bool? isAnamorphic,
|
2015-03-30 16:16:34 +00:00
|
|
|
|
int? refFrames,
|
|
|
|
|
int? numVideoStreams,
|
2015-10-19 16:05:03 +00:00
|
|
|
|
int? numAudioStreams,
|
2016-10-03 06:28:45 +00:00
|
|
|
|
string videoCodecTag,
|
2016-12-14 20:58:55 +00:00
|
|
|
|
bool? isAvc )
|
2014-04-24 05:08:10 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Property)
|
|
|
|
|
{
|
2014-06-22 16:25:47 +00:00
|
|
|
|
case ProfileConditionValue.IsAnamorphic:
|
|
|
|
|
return IsConditionSatisfied(condition, isAnamorphic);
|
2016-10-03 06:28:45 +00:00
|
|
|
|
case ProfileConditionValue.IsAvc:
|
|
|
|
|
return IsConditionSatisfied(condition, isAvc);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionValue.VideoFramerate:
|
|
|
|
|
return IsConditionSatisfied(condition, videoFramerate);
|
|
|
|
|
case ProfileConditionValue.VideoLevel:
|
|
|
|
|
return IsConditionSatisfied(condition, videoLevel);
|
|
|
|
|
case ProfileConditionValue.VideoProfile:
|
|
|
|
|
return IsConditionSatisfied(condition, videoProfile);
|
2015-10-19 16:05:03 +00:00
|
|
|
|
case ProfileConditionValue.VideoCodecTag:
|
|
|
|
|
return IsConditionSatisfied(condition, videoCodecTag);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionValue.PacketLength:
|
|
|
|
|
return IsConditionSatisfied(condition, packetLength);
|
|
|
|
|
case ProfileConditionValue.VideoBitDepth:
|
|
|
|
|
return IsConditionSatisfied(condition, bitDepth);
|
|
|
|
|
case ProfileConditionValue.VideoBitrate:
|
|
|
|
|
return IsConditionSatisfied(condition, videoBitrate);
|
|
|
|
|
case ProfileConditionValue.Height:
|
|
|
|
|
return IsConditionSatisfied(condition, height);
|
|
|
|
|
case ProfileConditionValue.Width:
|
|
|
|
|
return IsConditionSatisfied(condition, width);
|
2014-09-09 01:15:31 +00:00
|
|
|
|
case ProfileConditionValue.RefFrames:
|
|
|
|
|
return IsConditionSatisfied(condition, refFrames);
|
2015-03-30 16:16:34 +00:00
|
|
|
|
case ProfileConditionValue.NumAudioStreams:
|
|
|
|
|
return IsConditionSatisfied(condition, numAudioStreams);
|
|
|
|
|
case ProfileConditionValue.NumVideoStreams:
|
|
|
|
|
return IsConditionSatisfied(condition, numVideoStreams);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionValue.VideoTimestamp:
|
|
|
|
|
return IsConditionSatisfied(condition, timestamp);
|
|
|
|
|
default:
|
2015-10-19 16:05:03 +00:00
|
|
|
|
return true;
|
2014-04-24 05:08:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsImageConditionSatisfied(ProfileCondition condition, int? width, int? height)
|
|
|
|
|
{
|
|
|
|
|
switch (condition.Property)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionValue.Height:
|
|
|
|
|
return IsConditionSatisfied(condition, height);
|
|
|
|
|
case ProfileConditionValue.Width:
|
|
|
|
|
return IsConditionSatisfied(condition, width);
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Unexpected condition on image file: " + condition.Property);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsAudioConditionSatisfied(ProfileCondition condition, int? audioChannels, int? audioBitrate)
|
|
|
|
|
{
|
|
|
|
|
switch (condition.Property)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionValue.AudioBitrate:
|
|
|
|
|
return IsConditionSatisfied(condition, audioBitrate);
|
|
|
|
|
case ProfileConditionValue.AudioChannels:
|
|
|
|
|
return IsConditionSatisfied(condition, audioChannels);
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Unexpected condition on audio file: " + condition.Property);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-22 02:08:34 +00:00
|
|
|
|
public bool IsVideoAudioConditionSatisfied(ProfileCondition condition,
|
|
|
|
|
int? audioChannels,
|
2014-04-29 03:56:20 +00:00
|
|
|
|
int? audioBitrate,
|
2015-03-30 16:16:34 +00:00
|
|
|
|
string audioProfile,
|
|
|
|
|
bool? isSecondaryTrack)
|
2014-04-24 05:08:10 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Property)
|
|
|
|
|
{
|
2014-04-28 15:05:28 +00:00
|
|
|
|
case ProfileConditionValue.AudioProfile:
|
2014-04-29 03:56:20 +00:00
|
|
|
|
return IsConditionSatisfied(condition, audioProfile);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionValue.AudioBitrate:
|
|
|
|
|
return IsConditionSatisfied(condition, audioBitrate);
|
|
|
|
|
case ProfileConditionValue.AudioChannels:
|
|
|
|
|
return IsConditionSatisfied(condition, audioChannels);
|
2015-03-30 16:16:34 +00:00
|
|
|
|
case ProfileConditionValue.IsSecondaryAudio:
|
|
|
|
|
return IsConditionSatisfied(condition, isSecondaryTrack);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Unexpected condition on audio file: " + condition.Property);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, int? currentValue)
|
|
|
|
|
{
|
|
|
|
|
if (!currentValue.HasValue)
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int expected;
|
2016-10-22 02:08:34 +00:00
|
|
|
|
if (int.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out expected))
|
2014-04-24 05:08:10 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionType.Equals:
|
|
|
|
|
return currentValue.Value.Equals(expected);
|
|
|
|
|
case ProfileConditionType.GreaterThanEqual:
|
|
|
|
|
return currentValue.Value >= expected;
|
|
|
|
|
case ProfileConditionType.LessThanEqual:
|
|
|
|
|
return currentValue.Value <= expected;
|
|
|
|
|
case ProfileConditionType.NotEquals:
|
|
|
|
|
return !currentValue.Value.Equals(expected);
|
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, string currentValue)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(currentValue))
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-08 20:44:17 +00:00
|
|
|
|
string expected = condition.Value;
|
2014-04-24 05:08:10 +00:00
|
|
|
|
|
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
2014-10-09 22:22:04 +00:00
|
|
|
|
case ProfileConditionType.EqualsAny:
|
2016-10-22 02:08:34 +00:00
|
|
|
|
{
|
|
|
|
|
return ListHelper.ContainsIgnoreCase(expected.Split('|'), currentValue);
|
|
|
|
|
}
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionType.Equals:
|
2014-06-01 04:11:04 +00:00
|
|
|
|
return StringHelper.EqualsIgnoreCase(currentValue, expected);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
case ProfileConditionType.NotEquals:
|
2014-06-01 04:11:04 +00:00
|
|
|
|
return !StringHelper.EqualsIgnoreCase(currentValue, expected);
|
2014-04-24 05:08:10 +00:00
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-06-22 16:25:47 +00:00
|
|
|
|
|
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, bool? currentValue)
|
|
|
|
|
{
|
|
|
|
|
if (!currentValue.HasValue)
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool expected;
|
2016-10-23 19:47:34 +00:00
|
|
|
|
if (bool.TryParse(condition.Value, out expected))
|
2014-06-22 16:25:47 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionType.Equals:
|
|
|
|
|
return currentValue.Value == expected;
|
|
|
|
|
case ProfileConditionType.NotEquals:
|
|
|
|
|
return currentValue.Value != expected;
|
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-06-29 19:59:52 +00:00
|
|
|
|
|
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, float? currentValue)
|
|
|
|
|
{
|
|
|
|
|
if (!currentValue.HasValue)
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float expected;
|
2016-10-23 19:47:34 +00:00
|
|
|
|
if (float.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out expected))
|
2014-06-29 19:59:52 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionType.Equals:
|
|
|
|
|
return currentValue.Value.Equals(expected);
|
|
|
|
|
case ProfileConditionType.GreaterThanEqual:
|
|
|
|
|
return currentValue.Value >= expected;
|
|
|
|
|
case ProfileConditionType.LessThanEqual:
|
|
|
|
|
return currentValue.Value <= expected;
|
|
|
|
|
case ProfileConditionType.NotEquals:
|
|
|
|
|
return !currentValue.Value.Equals(expected);
|
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-10-22 02:08:34 +00:00
|
|
|
|
|
2014-04-24 05:08:10 +00:00
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, double? currentValue)
|
|
|
|
|
{
|
|
|
|
|
if (!currentValue.HasValue)
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double expected;
|
2016-10-23 19:47:34 +00:00
|
|
|
|
if (double.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out expected))
|
2014-04-24 05:08:10 +00:00
|
|
|
|
{
|
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionType.Equals:
|
|
|
|
|
return currentValue.Value.Equals(expected);
|
|
|
|
|
case ProfileConditionType.GreaterThanEqual:
|
|
|
|
|
return currentValue.Value >= expected;
|
|
|
|
|
case ProfileConditionType.LessThanEqual:
|
|
|
|
|
return currentValue.Value <= expected;
|
|
|
|
|
case ProfileConditionType.NotEquals:
|
|
|
|
|
return !currentValue.Value.Equals(expected);
|
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-10-22 02:08:34 +00:00
|
|
|
|
|
2014-04-25 02:45:06 +00:00
|
|
|
|
private bool IsConditionSatisfied(ProfileCondition condition, TransportStreamTimestamp? timestamp)
|
2014-04-24 05:08:10 +00:00
|
|
|
|
{
|
2014-04-25 02:45:06 +00:00
|
|
|
|
if (!timestamp.HasValue)
|
|
|
|
|
{
|
|
|
|
|
// If the value is unknown, it satisfies if not marked as required
|
|
|
|
|
return !condition.IsRequired;
|
|
|
|
|
}
|
2016-10-22 02:08:34 +00:00
|
|
|
|
|
2014-05-08 20:44:17 +00:00
|
|
|
|
TransportStreamTimestamp expected = (TransportStreamTimestamp)Enum.Parse(typeof(TransportStreamTimestamp), condition.Value, true);
|
2016-10-22 02:08:34 +00:00
|
|
|
|
|
2014-04-24 05:08:10 +00:00
|
|
|
|
switch (condition.Condition)
|
|
|
|
|
{
|
|
|
|
|
case ProfileConditionType.Equals:
|
|
|
|
|
return timestamp == expected;
|
|
|
|
|
case ProfileConditionType.NotEquals:
|
|
|
|
|
return timestamp != expected;
|
|
|
|
|
default:
|
|
|
|
|
throw new InvalidOperationException("Unexpected ProfileConditionType");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|