Various DLNA Optimizations

This commit is contained in:
BaronGreenback 2021-04-02 19:06:38 +01:00
parent 557a2ad715
commit d9a50cb510
5 changed files with 68 additions and 76 deletions

View File

@ -208,7 +208,8 @@ namespace Emby.Dlna.Didl
var targetWidth = streamInfo.TargetWidth; var targetWidth = streamInfo.TargetWidth;
var targetHeight = streamInfo.TargetHeight; var targetHeight = streamInfo.TargetHeight;
var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader( var contentFeatureList = ContentFeatureBuilder.BuildVideoHeader(
_profile,
streamInfo.Container, streamInfo.Container,
streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetVideoCodec.FirstOrDefault(),
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),
@ -599,7 +600,8 @@ namespace Emby.Dlna.Didl
? MimeTypes.GetMimeType(filename) ? MimeTypes.GetMimeType(filename)
: mediaProfile.MimeType; : mediaProfile.MimeType;
var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader( var contentFeatures = ContentFeatureBuilder.BuildAudioHeader(
_profile,
streamInfo.Container, streamInfo.Container,
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),
targetAudioBitrate, targetAudioBitrate,
@ -1033,8 +1035,7 @@ namespace Emby.Dlna.Didl
var width = albumartUrlInfo.width ?? maxWidth; var width = albumartUrlInfo.width ?? maxWidth;
var height = albumartUrlInfo.height ?? maxHeight; var height = albumartUrlInfo.height ?? maxHeight;
var contentFeatures = new ContentFeatureBuilder(_profile) var contentFeatures = ContentFeatureBuilder.BuildImageHeader(_profile, format, width, height, imageInfo.IsDirectStream, org_Pn);
.BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
writer.WriteAttributeString( writer.WriteAttributeString(
"protocolInfo", "protocolInfo",

View File

@ -499,8 +499,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Audio) if (streamInfo.MediaType == DlnaProfileType.Audio)
{ {
return new ContentFeatureBuilder(profile) return ContentFeatureBuilder.BuildAudioHeader(
.BuildAudioHeader( profile,
streamInfo.Container, streamInfo.Container,
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),
streamInfo.TargetAudioBitrate, streamInfo.TargetAudioBitrate,
@ -514,8 +514,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Video) if (streamInfo.MediaType == DlnaProfileType.Video)
{ {
var list = new ContentFeatureBuilder(profile) var list = ContentFeatureBuilder.BuildVideoHeader(
.BuildVideoHeader( profile,
streamInfo.Container, streamInfo.Container,
streamInfo.TargetVideoCodec.FirstOrDefault(), streamInfo.TargetVideoCodec.FirstOrDefault(),
streamInfo.TargetAudioCodec.FirstOrDefault(), streamInfo.TargetAudioCodec.FirstOrDefault(),

View File

@ -306,7 +306,8 @@ namespace Jellyfin.Api.Helpers
if (!state.IsVideoRequest) if (!state.IsVideoRequest)
{ {
responseHeaders.Add("contentFeatures.dlna.org", new ContentFeatureBuilder(profile).BuildAudioHeader( responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader(
profile,
state.OutputContainer, state.OutputContainer,
audioCodec, audioCodec,
state.OutputAudioBitrate, state.OutputAudioBitrate,
@ -323,7 +324,7 @@ namespace Jellyfin.Api.Helpers
responseHeaders.Add( responseHeaders.Add(
"contentFeatures.dlna.org", "contentFeatures.dlna.org",
new ContentFeatureBuilder(profile).BuildVideoHeader(state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty);
} }
} }

View File

@ -10,14 +10,8 @@ namespace MediaBrowser.Model.Dlna
{ {
public class ContentFeatureBuilder public class ContentFeatureBuilder
{ {
private readonly DeviceProfile _profile; public static string BuildImageHeader(
DeviceProfile profile,
public ContentFeatureBuilder(DeviceProfile profile)
{
_profile = profile;
}
public string BuildImageHeader(
string container, string container,
int? width, int? width,
int? height, int? height,
@ -38,27 +32,31 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}", ";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue)); DlnaMaps.FlagsToString(flagValue));
ResponseProfile mediaProfile = _profile.GetImageMediaProfile(
container,
width,
height);
if (string.IsNullOrEmpty(orgPn)) if (string.IsNullOrEmpty(orgPn))
{ {
ResponseProfile mediaProfile = profile.GetImageMediaProfile(
container,
width,
height);
orgPn = mediaProfile?.OrgPn; orgPn = mediaProfile?.OrgPn;
if (string.IsNullOrEmpty(orgPn))
{
orgPn = GetImageOrgPnValue(container, width, height);
}
} }
if (string.IsNullOrEmpty(orgPn)) if (string.IsNullOrEmpty(orgPn))
{ {
orgPn = GetImageOrgPnValue(container, width, height); return orgOp.TrimStart(';') + orgCi + dlnaflags;
} }
string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn; return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
} }
public string BuildAudioHeader( public static string BuildAudioHeader(
DeviceProfile profile,
string container, string container,
string audioCodec, string audioCodec,
int? audioBitrate, int? audioBitrate,
@ -94,7 +92,7 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}", ";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue)); DlnaMaps.FlagsToString(flagValue));
ResponseProfile mediaProfile = _profile.GetAudioMediaProfile( ResponseProfile mediaProfile = profile.GetAudioMediaProfile(
container, container,
audioCodec, audioCodec,
audioChannels, audioChannels,
@ -109,12 +107,16 @@ namespace MediaBrowser.Model.Dlna
orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels); orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels);
} }
string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn; if (string.IsNullOrEmpty(orgPn))
{
return orgOp.TrimStart(';') + orgCi + dlnaflags;
}
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
} }
public List<string> BuildVideoHeader( public static List<string> BuildVideoHeader(
DeviceProfile profile,
string container, string container,
string videoCodec, string videoCodec,
string audioCodec, string audioCodec,
@ -163,7 +165,7 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}", ";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue)); DlnaMaps.FlagsToString(flagValue));
ResponseProfile mediaProfile = _profile.GetVideoMediaProfile( ResponseProfile mediaProfile = profile.GetVideoMediaProfile(
container, container,
audioCodec, audioCodec,
videoCodec, videoCodec,
@ -192,9 +194,9 @@ namespace MediaBrowser.Model.Dlna
} }
else else
{ {
foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp)) foreach (var s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
{ {
orgPnValues.Add(s); orgPnValues.Add(s.ToString());
break; break;
} }
} }
@ -203,20 +205,20 @@ namespace MediaBrowser.Model.Dlna
foreach (string orgPn in orgPnValues) foreach (string orgPn in orgPnValues)
{ {
string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn; if (string.IsNullOrEmpty(orgPn))
{
var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags);
continue;
contentFeatureList.Add(value); }
else
{
contentFeatureList.Add("DLNA.ORG_PN=" + orgPn + orgCi + dlnaflags);
}
} }
if (orgPnValues.Count == 0) if (orgPnValues.Count == 0)
{ {
string contentFeatures = string.Empty; contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags);
var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
contentFeatureList.Add(value);
} }
return contentFeatureList; return contentFeatureList;
@ -224,19 +226,14 @@ namespace MediaBrowser.Model.Dlna
private static string GetImageOrgPnValue(string container, int? width, int? height) private static string GetImageOrgPnValue(string container, int? width, int? height)
{ {
MediaFormatProfile? format = new MediaFormatProfileResolver() MediaFormatProfile? format = MediaFormatProfileResolver.ResolveImageFormat(container, width, height);
.ResolveImageFormat(
container,
width,
height);
return format.HasValue ? format.Value.ToString() : null; return format.HasValue ? format.Value.ToString() : null;
} }
private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels) private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
{ {
MediaFormatProfile? format = new MediaFormatProfileResolver() MediaFormatProfile? format = MediaFormatProfileResolver.ResolveAudioFormat(
.ResolveAudioFormat(
container, container,
audioBitrate, audioBitrate,
audioSampleRate, audioSampleRate,
@ -245,9 +242,9 @@ namespace MediaBrowser.Model.Dlna
return format.HasValue ? format.Value.ToString() : null; return format.HasValue ? format.Value.ToString() : null;
} }
private static string[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp) private static MediaFormatProfile[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
{ {
return new MediaFormatProfileResolver().ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp); return MediaFormatProfileResolver.ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
} }
} }
} }

View File

@ -9,16 +9,9 @@ using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Dlna namespace MediaBrowser.Model.Dlna
{ {
public class MediaFormatProfileResolver public static class MediaFormatProfileResolver
{ {
public string[] ResolveVideoFormat(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType) public static MediaFormatProfile[] ResolveVideoFormat(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{
return ResolveVideoFormatInternal(container, videoCodec, audioCodec, width, height, timestampType)
.Select(i => i.ToString())
.ToArray();
}
private MediaFormatProfile[] ResolveVideoFormatInternal(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{ {
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
{ {
@ -84,7 +77,7 @@ namespace MediaBrowser.Model.Dlna
return Array.Empty<MediaFormatProfile>(); return Array.Empty<MediaFormatProfile>();
} }
private MediaFormatProfile[] ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType) private static MediaFormatProfile[] ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{ {
string suffix = string.Empty; string suffix = string.Empty;
@ -209,12 +202,12 @@ namespace MediaBrowser.Model.Dlna
return Array.Empty<MediaFormatProfile>(); return Array.Empty<MediaFormatProfile>();
} }
private MediaFormatProfile ValueOf(string value) private static MediaFormatProfile ValueOf(string value)
{ {
return (MediaFormatProfile)Enum.Parse(typeof(MediaFormatProfile), value, true); return (MediaFormatProfile)Enum.Parse(typeof(MediaFormatProfile), value, true);
} }
private MediaFormatProfile? ResolveVideoMP4Format(string videoCodec, string audioCodec, int? width, int? height) private static MediaFormatProfile? ResolveVideoMP4Format(string videoCodec, string audioCodec, int? width, int? height)
{ {
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{ {
@ -287,7 +280,7 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
private MediaFormatProfile? ResolveVideo3GPFormat(string videoCodec, string audioCodec) private static MediaFormatProfile? ResolveVideo3GPFormat(string videoCodec, string audioCodec)
{ {
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{ {
@ -317,7 +310,7 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
private MediaFormatProfile? ResolveVideoASFFormat(string videoCodec, string audioCodec, int? width, int? height) private static MediaFormatProfile? ResolveVideoASFFormat(string videoCodec, string audioCodec, int? width, int? height)
{ {
if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase) && if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase) &&
(string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "wmapro", StringComparison.OrdinalIgnoreCase))) (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "wmapro", StringComparison.OrdinalIgnoreCase)))
@ -371,7 +364,7 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
public MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels) public static MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels)
{ {
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
{ {
@ -413,7 +406,7 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
private MediaFormatProfile ResolveAudioASFFormat(int? bitrate) private static MediaFormatProfile ResolveAudioASFFormat(int? bitrate)
{ {
if (bitrate.HasValue && bitrate.Value <= 193) if (bitrate.HasValue && bitrate.Value <= 193)
{ {
@ -423,7 +416,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.WMA_FULL; return MediaFormatProfile.WMA_FULL;
} }
private MediaFormatProfile? ResolveAudioLPCMFormat(int? frequency, int? channels) private static MediaFormatProfile? ResolveAudioLPCMFormat(int? frequency, int? channels)
{ {
if (frequency.HasValue && channels.HasValue) if (frequency.HasValue && channels.HasValue)
{ {
@ -453,7 +446,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.LPCM16_48_STEREO; return MediaFormatProfile.LPCM16_48_STEREO;
} }
private MediaFormatProfile ResolveAudioMP4Format(int? bitrate) private static MediaFormatProfile ResolveAudioMP4Format(int? bitrate)
{ {
if (bitrate.HasValue && bitrate.Value <= 320) if (bitrate.HasValue && bitrate.Value <= 320)
{ {
@ -463,7 +456,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.AAC_ISO; return MediaFormatProfile.AAC_ISO;
} }
private MediaFormatProfile ResolveAudioADTSFormat(int? bitrate) private static MediaFormatProfile ResolveAudioADTSFormat(int? bitrate)
{ {
if (bitrate.HasValue && bitrate.Value <= 320) if (bitrate.HasValue && bitrate.Value <= 320)
{ {
@ -473,7 +466,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.AAC_ADTS; return MediaFormatProfile.AAC_ADTS;
} }
public MediaFormatProfile? ResolveImageFormat(string container, int? width, int? height) public static MediaFormatProfile? ResolveImageFormat(string container, int? width, int? height)
{ {
if (string.Equals(container, "jpeg", StringComparison.OrdinalIgnoreCase) || if (string.Equals(container, "jpeg", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "jpg", StringComparison.OrdinalIgnoreCase)) string.Equals(container, "jpg", StringComparison.OrdinalIgnoreCase))
@ -499,7 +492,7 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
private MediaFormatProfile ResolveImageJPGFormat(int? width, int? height) private static MediaFormatProfile ResolveImageJPGFormat(int? width, int? height)
{ {
if (width.HasValue && height.HasValue) if (width.HasValue && height.HasValue)
{ {
@ -524,7 +517,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.JPEG_SM; return MediaFormatProfile.JPEG_SM;
} }
private MediaFormatProfile ResolveImagePNGFormat(int? width, int? height) private static MediaFormatProfile ResolveImagePNGFormat(int? width, int? height)
{ {
if (width.HasValue && height.HasValue) if (width.HasValue && height.HasValue)
{ {