aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-04-18 13:16:25 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-04-18 13:16:25 -0400
commit5170042eb5efee7be005dcc5aca863b66c23a6f2 (patch)
treebd54e8945bee9cc987e3e38720fe97eb435788d1
parentb7b6f64f0089d7ce4ff8c3c5682fd8ede7311b1b (diff)
support more dlna resource properties
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs4
-rw-r--r--MediaBrowser.Dlna/DlnaManager.cs10
-rw-r--r--MediaBrowser.Dlna/Server/ControlHandler.cs64
-rw-r--r--MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs2
-rw-r--r--MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs4
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs3
-rw-r--r--MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs126
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs6
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs146
-rw-r--r--MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json4
11 files changed, 271 insertions, 99 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 04deea3cf..ff9596757 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -380,7 +380,7 @@ namespace MediaBrowser.Api.Playback
if (isVc1)
{
- profileScore ++;
+ profileScore++;
// Max of 2
profileScore = Math.Min(profileScore, 2);
}
@@ -445,7 +445,7 @@ namespace MediaBrowser.Api.Playback
{
if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
{
- volParam = ",volume=2.000000";
+ volParam = ",volume=" + ServerConfigurationManager.Configuration.DownMixAudioBoost.ToString(UsCulture);
}
}
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index 9993b0e21..c2a7ee35f 100644
--- a/MediaBrowser.Dlna/DlnaManager.cs
+++ b/MediaBrowser.Dlna/DlnaManager.cs
@@ -516,7 +516,15 @@ namespace MediaBrowser.Dlna
var serverAddress = device.Descriptor.ToString().Substring(0, device.Descriptor.ToString().IndexOf("/dlna", StringComparison.OrdinalIgnoreCase));
- return new ControlHandler(_logger, _userManager, _libraryManager, profile, serverAddress, _dtoService, _imageProcessor, _userDataManager)
+ return new ControlHandler(
+ _logger,
+ _userManager,
+ _libraryManager,
+ profile,
+ serverAddress,
+ _dtoService,
+ _imageProcessor,
+ _userDataManager)
.ProcessControlRequest(request);
}
diff --git a/MediaBrowser.Dlna/Server/ControlHandler.cs b/MediaBrowser.Dlna/Server/ControlHandler.cs
index c3a3c0bf0..ba325a66b 100644
--- a/MediaBrowser.Dlna/Server/ControlHandler.cs
+++ b/MediaBrowser.Dlna/Server/ControlHandler.cs
@@ -89,6 +89,8 @@ namespace MediaBrowser.Dlna.Server
sparams.Add(e.LocalName, e.InnerText.Trim());
}
+ var deviceId = "fgd";
+
var env = new XmlDocument();
env.AppendChild(env.CreateXmlDeclaration("1.0", "utf-8", "yes"));
var envelope = env.CreateElement("SOAP-ENV", "Envelope", NS_SOAPENV);
@@ -116,7 +118,7 @@ namespace MediaBrowser.Dlna.Server
result = HandleGetSystemUpdateID();
break;
case "Browse":
- result = HandleBrowse(sparams, user);
+ result = HandleBrowse(sparams, user, deviceId);
break;
case "X_GetFeatureList":
result = HandleXGetFeatureList();
@@ -235,7 +237,7 @@ namespace MediaBrowser.Dlna.Server
return builder.ToString();
}
- private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams, User user)
+ private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams, User user, string deviceId)
{
var id = sparams["ObjectID"];
var flag = sparams["BrowseFlag"];
@@ -298,7 +300,7 @@ namespace MediaBrowser.Dlna.Server
}
else
{
- Browse_AddItem(result, i, user);
+ Browse_AddItem(result, i, user, deviceId);
}
}
}
@@ -366,7 +368,7 @@ namespace MediaBrowser.Dlna.Server
}
}
- private void Browse_AddItem(XmlDocument result, BaseItem item, User user)
+ private void Browse_AddItem(XmlDocument result, BaseItem item, User user, string deviceId)
{
var element = result.CreateElement(string.Empty, "item", NS_DIDL);
element.SetAttribute("restricted", "1");
@@ -389,13 +391,13 @@ namespace MediaBrowser.Dlna.Server
var audio = item as Audio;
if (audio != null)
{
- AddAudioResource(element, audio);
+ AddAudioResource(element, audio, deviceId);
}
var video = item as Video;
if (video != null)
{
- AddVideoResource(element, video);
+ AddVideoResource(element, video, deviceId);
}
AddCover(item, element);
@@ -403,12 +405,7 @@ namespace MediaBrowser.Dlna.Server
result.DocumentElement.AppendChild(element);
}
- private string GetDeviceId()
- {
- return "erer";
- }
-
- private void AddVideoResource(XmlElement container, Video video)
+ private void AddVideoResource(XmlElement container, Video video, string deviceId)
{
var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
@@ -421,7 +418,7 @@ namespace MediaBrowser.Dlna.Server
ItemId = video.Id.ToString("N"),
MediaSources = sources,
Profile = _profile,
- DeviceId = GetDeviceId(),
+ DeviceId = deviceId,
MaxBitrate = maxBitrateSetting
});
@@ -435,17 +432,21 @@ namespace MediaBrowser.Dlna.Server
res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
}
- if (streamInfo.IsDirectStream && mediaSource.Size.HasValue)
+ if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
{
- res.SetAttribute("size", mediaSource.Size.Value.ToString(_usCulture));
+ var size = streamInfo.TargetSize;
+
+ if (size.HasValue)
+ {
+ res.SetAttribute("size", size.Value.ToString(_usCulture));
+ }
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video && !string.Equals(i.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase));
- var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
- var targetAudioBitrate = streamInfo.AudioBitrate ?? (audioStream == null ? null : audioStream.BitRate);
- var targetSampleRate = audioStream == null ? null : audioStream.SampleRate;
- var targetChannels = streamInfo.MaxAudioChannels ?? (audioStream == null ? null : audioStream.Channels);
+ var targetAudioBitrate = streamInfo.TargetAudioBitrate;
+ var targetSampleRate = streamInfo.TargetAudioSampleRate;
+ var targetChannels = streamInfo.TargetAudioChannels;
var targetWidth = streamInfo.MaxWidth ?? (videoStream == null ? null : videoStream.Width);
var targetHeight = streamInfo.MaxHeight ?? (videoStream == null ? null : videoStream.Height);
@@ -454,9 +455,7 @@ namespace MediaBrowser.Dlna.Server
? (videoStream == null ? null : videoStream.Codec)
: streamInfo.VideoCodec;
- var targetAudioCodec = streamInfo.IsDirectStream
- ? (audioStream == null ? null : audioStream.Codec)
- : streamInfo.AudioCodec;
+ var targetAudioCodec = streamInfo.TargetAudioCodec;
var targetBitrate = maxBitrateSetting ?? mediaSource.Bitrate;
@@ -506,7 +505,7 @@ namespace MediaBrowser.Dlna.Server
container.AppendChild(res);
}
- private void AddAudioResource(XmlElement container, Audio audio)
+ private void AddAudioResource(XmlElement container, Audio audio, string deviceId)
{
var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
@@ -517,7 +516,7 @@ namespace MediaBrowser.Dlna.Server
ItemId = audio.Id.ToString("N"),
MediaSources = sources,
Profile = _profile,
- DeviceId = GetDeviceId()
+ DeviceId = deviceId
});
var url = streamInfo.ToDlnaUrl(_serverAddress);
@@ -530,16 +529,19 @@ namespace MediaBrowser.Dlna.Server
res.SetAttribute("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture));
}
- if (streamInfo.IsDirectStream && mediaSource.Size.HasValue)
+ if (streamInfo.IsDirectStream || streamInfo.EstimateContentLength)
{
- res.SetAttribute("size", mediaSource.Size.Value.ToString(_usCulture));
- }
+ var size = streamInfo.TargetSize;
- var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
+ if (size.HasValue)
+ {
+ res.SetAttribute("size", size.Value.ToString(_usCulture));
+ }
+ }
- var targetAudioBitrate = streamInfo.AudioBitrate ?? (audioStream == null ? null : audioStream.BitRate);
- var targetSampleRate = audioStream == null ? null : audioStream.SampleRate;
- var targetChannels = streamInfo.MaxAudioChannels ?? (audioStream == null ? null : audioStream.Channels);
+ var targetAudioBitrate = streamInfo.TargetAudioBitrate;
+ var targetSampleRate = streamInfo.TargetAudioSampleRate;
+ var targetChannels = streamInfo.TargetAudioChannels;
if (targetChannels.HasValue)
{
diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
index 33286a474..4d3ccf9a0 100644
--- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
+++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
@@ -57,7 +57,7 @@ namespace MediaBrowser.Dlna.Server
private void AppendDeviceProperties(StringBuilder builder)
{
- builder.Append("<UDN>" + SecurityElement.Escape(_serverUdn) + "</UDN>");
+ builder.Append("<UDN>uuid:" + SecurityElement.Escape(_serverUdn) + "</UDN>");
builder.Append("<dlna:X_DLNACAP>" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + "</dlna:X_DLNACAP>");
if (!string.IsNullOrWhiteSpace(_profile.XDlnaDoc))
diff --git a/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs b/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs
index 050d89f49..d7a34c699 100644
--- a/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs
+++ b/MediaBrowser.Dlna/Server/DlnaServerEntryPoint.cs
@@ -1,11 +1,11 @@
-using System.Linq;
-using MediaBrowser.Common;
+using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using System;
+using System.Linq;
using System.Net;
namespace MediaBrowser.Dlna.Server
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 932d5d63d..ca5f569ed 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -222,6 +222,8 @@ namespace MediaBrowser.Model.Configuration
public DlnaOptions DlnaOptions { get; set; }
+ public double DownMixAudioBoost { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>
@@ -242,6 +244,7 @@ namespace MediaBrowser.Model.Configuration
EnablePeoplePrefixSubFolders = true;
EnableUPnP = true;
+ DownMixAudioBoost = 2;
MinResumePct = 5;
MaxResumePct = 90;
diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
index 76480930f..8b5966c9a 100644
--- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
+++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
@@ -35,17 +35,23 @@ namespace MediaBrowser.Model.Dlna
private MediaFormatProfile ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, int? bitrate, TransportStreamTimestamp timestampType)
{
- // String suffix = "";
- // if (isNoTimestamp(timestampType))
- // suffix = "_ISO";
- // else if (timestampType == TransportStreamTimestamp.VALID) {
- // suffix = "_T";
- // }
+ var suffix = "";
- // String resolution = "S";
- // if ((width.intValue() > 720) || (height.intValue() > 576)) {
- // resolution = "H";
- // }
+ switch (timestampType)
+ {
+ case TransportStreamTimestamp.NONE:
+ suffix = "_ISO";
+ break;
+ case TransportStreamTimestamp.VALID:
+ suffix = "_T";
+ break;
+ }
+
+ String resolution = "S";
+ if ((width.HasValue && width.Value > 720) || (height.HasValue && height.Value > 576))
+ {
+ resolution = "H";
+ }
// if (videoCodec == VideoCodec.MPEG2)
// {
@@ -55,54 +61,60 @@ namespace MediaBrowser.Model.Dlna
// profiles.add(MediaFormatProfile.MPEG_TS_JP_T);
// }
// return profiles;
- // }if (videoCodec == VideoCodec.H264)
- // {
- // if (audioCodec == AudioCodec.LPCM)
- // return Collections.singletonList(MediaFormatProfile.AVC_TS_HD_50_LPCM_T);
- // if (audioCodec == AudioCodec.DTS) {
- // if (isNoTimestamp(timestampType)) {
- // return Collections.singletonList(MediaFormatProfile.AVC_TS_HD_DTS_ISO);
- // }
- // return Collections.singletonList(MediaFormatProfile.AVC_TS_HD_DTS_T);
- // }
- // if (audioCodec == AudioCodec.MP2) {
- // if (isNoTimestamp(timestampType)) {
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_HP_%sD_MPEG1_L2_ISO", cast(Object[])[ resolution ])));
- // }
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_HP_%sD_MPEG1_L2_T", cast(Object[])[ resolution ])));
- // }
-
- // if (audioCodec == AudioCodec.AAC)
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_AAC_MULT5%s", cast(Object[])[ resolution, suffix ])));
- // if (audioCodec == AudioCodec.MP3)
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_MPEG1_L3%s", cast(Object[])[ resolution, suffix ])));
- // if ((audioCodec is null) || (audioCodec == AudioCodec.AC3)) {
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_AC3%s", cast(Object[])[ resolution, suffix ])));
- // }
- // }
- // else if (videoCodec == VideoCodec.VC1) {
- // if ((audioCodec is null) || (audioCodec == AudioCodec.AC3))
- // {
- // if ((width.intValue() > 720) || (height.intValue() > 576)) {
- // return Collections.singletonList(MediaFormatProfile.VC1_TS_AP_L2_AC3_ISO);
- // }
- // return Collections.singletonList(MediaFormatProfile.VC1_TS_AP_L1_AC3_ISO);
- // }
- // if (audioCodec == AudioCodec.DTS) {
- // suffix = suffix.equals("_ISO") ? suffix : "_T";
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("VC1_TS_HD_DTS%s", cast(Object[])[ suffix ])));
- // }
- // } else if ((videoCodec == VideoCodec.MPEG4) || (videoCodec == VideoCodec.MSMPEG4)) {
- // if (audioCodec == AudioCodec.AAC)
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AAC%s", cast(Object[])[ suffix ])));
- // if (audioCodec == AudioCodec.MP3)
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG1_L3%s", cast(Object[])[ suffix ])));
- // if (audioCodec == AudioCodec.MP2)
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG2_L2%s", cast(Object[])[ suffix ])));
- // if ((audioCodec is null) || (audioCodec == AudioCodec.AC3)) {
- // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AC3%s", cast(Object[])[ suffix ])));
- // }
// }
+ if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
+ {
+ if (string.Equals(audioCodec, "lpcm", StringComparison.OrdinalIgnoreCase))
+ return MediaFormatProfile.AVC_TS_HD_50_LPCM_T;
+
+ if (string.Equals(audioCodec, "dts", StringComparison.OrdinalIgnoreCase))
+ {
+ if (timestampType == TransportStreamTimestamp.NONE)
+ {
+ return MediaFormatProfile.AVC_TS_HD_DTS_ISO;
+ }
+ return MediaFormatProfile.AVC_TS_HD_DTS_T;
+ }
+ //if (audioCodec == AudioCodec.MP2) {
+ // if (isNoTimestamp(timestampType)) {
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_HP_%sD_MPEG1_L2_ISO", cast(Object[])[ resolution ])));
+ // }
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_HP_%sD_MPEG1_L2_T", cast(Object[])[ resolution ])));
+ //}
+
+ //if (audioCodec == AudioCodec.AAC)
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_AAC_MULT5%s", cast(Object[])[ resolution, suffix ])));
+ //if (audioCodec == AudioCodec.MP3)
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_MPEG1_L3%s", cast(Object[])[ resolution, suffix ])));
+ //if ((audioCodec is null) || (audioCodec == AudioCodec.AC3)) {
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("AVC_TS_MP_%sD_AC3%s", cast(Object[])[ resolution, suffix ])));
+ //}
+ }
+ else if (string.Equals(videoCodec, "vc1", StringComparison.OrdinalIgnoreCase))
+ {
+ if (string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase))
+ {
+ if ((width.HasValue && width.Value > 720) || (height.HasValue && height.Value > 576))
+ {
+ return MediaFormatProfile.VC1_TS_AP_L2_AC3_ISO;
+ }
+ return MediaFormatProfile.VC1_TS_AP_L1_AC3_ISO;
+ }
+ // if (audioCodec == AudioCodec.DTS) {
+ // suffix = suffix.equals("_ISO") ? suffix : "_T";
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("VC1_TS_HD_DTS%s", cast(Object[])[ suffix ])));
+ // }
+ //} else if ((videoCodec == VideoCodec.MPEG4) || (videoCodec == VideoCodec.MSMPEG4)) {
+ // if (audioCodec == AudioCodec.AAC)
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AAC%s", cast(Object[])[ suffix ])));
+ // if (audioCodec == AudioCodec.MP3)
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG1_L3%s", cast(Object[])[ suffix ])));
+ // if (audioCodec == AudioCodec.MP2)
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG2_L2%s", cast(Object[])[ suffix ])));
+ // if ((audioCodec is null) || (audioCodec == AudioCodec.AC3)) {
+ // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AC3%s", cast(Object[])[ suffix ])));
+ // }
+ }
throw new ArgumentException("Mpeg video file does not match any supported DLNA profile");
}
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index d975b1c4b..0c007d694 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -81,7 +81,7 @@ namespace MediaBrowser.Model.Dlna
{
ItemId = options.ItemId,
MediaType = DlnaProfileType.Audio,
- MediaSourceId = item.Id,
+ MediaSource = item,
RunTimeTicks = item.RunTimeTicks
};
@@ -116,6 +116,7 @@ namespace MediaBrowser.Model.Dlna
{
playlistItem.IsDirectStream = false;
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
+ playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
playlistItem.Container = transcodingProfile.Container;
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
@@ -152,7 +153,7 @@ namespace MediaBrowser.Model.Dlna
{
ItemId = options.ItemId,
MediaType = DlnaProfileType.Video,
- MediaSourceId = item.Id,
+ MediaSource = item,
RunTimeTicks = item.RunTimeTicks
};
@@ -196,6 +197,7 @@ namespace MediaBrowser.Model.Dlna
{
playlistItem.IsDirectStream = false;
playlistItem.Container = transcodingProfile.Container;
+ playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',').FirstOrDefault();
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 6ba7fe399..b46d95af8 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
namespace MediaBrowser.Model.Dlna
{
@@ -12,8 +14,6 @@ namespace MediaBrowser.Model.Dlna
{
public string ItemId { get; set; }
- public string MediaSourceId { get; set; }
-
public bool IsDirectStream { get; set; }
public DlnaProfileType MediaType { get; set; }
@@ -50,6 +50,18 @@ namespace MediaBrowser.Model.Dlna
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
+ public bool EstimateContentLength { get; set; }
+
+ public MediaSourceInfo MediaSource { get; set; }
+
+ public string MediaSourceId
+ {
+ get
+ {
+ return MediaSource == null ? null : MediaSource.Id;
+ }
+ }
+
public string ToUrl(string baseUrl)
{
return ToDlnaUrl(baseUrl);
@@ -102,6 +114,136 @@ namespace MediaBrowser.Model.Dlna
return string.Format("Params={0}", string.Join(";", list.ToArray()));
}
+ /// <summary>
+ /// Returns the audio stream that will be used
+ /// </summary>
+ public MediaStream TargetAudioStream
+ {
+ get
+ {
+ if (MediaSource != null)
+ {
+ var audioStreams = MediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio);
+
+ if (AudioStreamIndex.HasValue)
+ {
+ return audioStreams.FirstOrDefault(i => i.Index == AudioStreamIndex.Value);
+ }
+
+ return audioStreams.FirstOrDefault();
+ }
+
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Returns the video stream that will be used
+ /// </summary>
+ public MediaStream TargetVideoStream
+ {
+ get
+ {
+ if (MediaSource != null)
+ {
+ return MediaSource.MediaStreams
+ .FirstOrDefault(i => i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1);
+ }
+
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio sample rate that will be in the output stream
+ /// </summary>
+ public int? TargetAudioSampleRate
+ {
+ get
+ {
+ var stream = TargetAudioStream;
+ return stream == null ? null : stream.SampleRate;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio bitrate that will be in the output stream
+ /// </summary>
+ public int? TargetAudioBitrate
+ {
+ get
+ {
+ var stream = TargetAudioStream;
+ return AudioBitrate.HasValue && !IsDirectStream
+ ? AudioBitrate
+ : stream == null ? null : stream.BitRate;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio channels that will be in the output stream
+ /// </summary>
+ public int? TargetAudioChannels
+ {
+ get
+ {
+ var stream = TargetAudioStream;
+
+ return MaxAudioChannels.HasValue && !IsDirectStream
+ ? (stream.Channels.HasValue ? Math.Min(MaxAudioChannels.Value, stream.Channels.Value) : MaxAudioChannels.Value)
+ : stream == null ? null : stream.Channels;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio codec that will be in the output stream
+ /// </summary>
+ public string TargetAudioCodec
+ {
+ get
+ {
+ var stream = TargetAudioStream;
+
+ return IsDirectStream
+ ? (stream == null ? null : stream.Codec)
+ : AudioCodec;
+ }
+ }
+
+ /// <summary>
+ /// Predicts the audio channels that will be in the output stream
+ /// </summary>
+ public long? TargetSize
+ {
+ get
+ {
+ if (IsDirectStream)
+ {
+ return MediaSource.Bitrate;
+ }
+
+ if (RunTimeTicks.HasValue)
+ {
+ var totalBitrate = 0;
+
+ if (AudioBitrate.HasValue)
+ {
+ totalBitrate += AudioBitrate.Value;
+ }
+ if (VideoBitrate.HasValue)
+ {
+ totalBitrate += VideoBitrate.Value;
+ }
+
+ return Convert.ToInt64(totalBitrate * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds);
+ }
+ var stream = TargetAudioStream;
+
+ return MaxAudioChannels.HasValue && !IsDirectStream
+ ? (stream.Channels.HasValue ? Math.Min(MaxAudioChannels.Value, stream.Channels.Value) : MaxAudioChannels.Value)
+ : stream == null ? null : stream.Channels;
+ }
+ }
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index 3672afbc2..629d21df6 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -356,6 +356,7 @@ namespace MediaBrowser.Server.Implementations.Localization
new LocalizatonOption{ Name="Greek", Value="el"},
new LocalizatonOption{ Name="Hebrew", Value="he"},
new LocalizatonOption{ Name="Italian", Value="it"},
+ new LocalizatonOption{ Name="Kazakh", Value="kk"},
new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"},
new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"},
new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"},
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index d16e0be99..b91cfdd84 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -515,5 +515,7 @@
"ServerUpToDate": "Media Browser Server is up to date",
"ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
"LabelComponentsUpdated": "The following components have been installed or updated:",
- "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates."
+ "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
+ "LabelDownMixAudioScale": "Down mix audio boost scale:",
+ "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value."
} \ No newline at end of file