using System;
using System.Globalization;
using System.Text;
namespace Jellyfin.Api.Helpers;
///
/// Hls Codec string helpers.
///
public static class HlsCodecStringHelpers
{
///
/// Codec name for MP3.
///
public const string MP3 = "mp4a.40.34";
///
/// Codec name for AC-3.
///
public const string AC3 = "mp4a.a5";
///
/// Codec name for E-AC-3.
///
public const string EAC3 = "mp4a.a6";
///
/// Codec name for FLAC.
///
public const string FLAC = "flac";
///
/// Codec name for ALAC.
///
public const string ALAC = "alac";
///
/// Codec name for OPUS.
///
public const string OPUS = "opus";
///
/// Gets a MP3 codec string.
///
/// MP3 codec string.
public static string GetMP3String()
{
return MP3;
}
///
/// Gets an AAC codec string.
///
/// AAC profile.
/// AAC codec string.
public static string GetAACString(string? profile)
{
StringBuilder result = new StringBuilder("mp4a", 9);
if (string.Equals(profile, "HE", StringComparison.OrdinalIgnoreCase))
{
result.Append(".40.5");
}
else
{
// Default to LC if profile is invalid
result.Append(".40.2");
}
return result.ToString();
}
///
/// Gets an AC-3 codec string.
///
/// AC-3 codec string.
public static string GetAC3String()
{
return AC3;
}
///
/// Gets an E-AC-3 codec string.
///
/// E-AC-3 codec string.
public static string GetEAC3String()
{
return EAC3;
}
///
/// Gets an FLAC codec string.
///
/// FLAC codec string.
public static string GetFLACString()
{
return FLAC;
}
///
/// Gets an ALAC codec string.
///
/// ALAC codec string.
public static string GetALACString()
{
return ALAC;
}
///
/// Gets an OPUS codec string.
///
/// OPUS codec string.
public static string GetOPUSString()
{
return OPUS;
}
///
/// Gets a H.264 codec string.
///
/// H.264 profile.
/// H.264 level.
/// H.264 string.
public static string GetH264String(string? profile, int level)
{
StringBuilder result = new StringBuilder("avc1", 11);
if (string.Equals(profile, "high", StringComparison.OrdinalIgnoreCase))
{
result.Append(".6400");
}
else if (string.Equals(profile, "main", StringComparison.OrdinalIgnoreCase))
{
result.Append(".4D40");
}
else if (string.Equals(profile, "baseline", StringComparison.OrdinalIgnoreCase))
{
result.Append(".42E0");
}
else
{
// Default to constrained baseline if profile is invalid
result.Append(".4240");
}
string levelHex = level.ToString("X2", CultureInfo.InvariantCulture);
result.Append(levelHex);
return result.ToString();
}
///
/// Gets a H.265 codec string.
///
/// H.265 profile.
/// H.265 level.
/// H.265 string.
public static string GetH265String(string? profile, int level)
{
// The h265 syntax is a bit of a mystery at the time this comment was written.
// This is what I've found through various sources:
// FORMAT: [codecTag].[profile].[constraint?].L[level * 30].[UNKNOWN]
StringBuilder result = new StringBuilder("hvc1", 16);
if (string.Equals(profile, "main10", StringComparison.OrdinalIgnoreCase)
|| string.Equals(profile, "main 10", StringComparison.OrdinalIgnoreCase))
{
result.Append(".2.4");
}
else
{
// Default to main if profile is invalid
result.Append(".1.4");
}
result.Append(".L")
.Append(level)
.Append(".B0");
return result.ToString();
}
}