added out of network bitrate limit

This commit is contained in:
Luke Pulverenti 2015-04-09 01:20:23 -04:00
parent 6e6ce82cf6
commit b9c656e859
24 changed files with 136 additions and 73 deletions

View File

@ -1,5 +1,4 @@
using System.Linq; using MediaBrowser.Common.IO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
@ -8,6 +7,7 @@ using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq;
using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat; using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat;
namespace Emby.Drawing.GDI namespace Emby.Drawing.GDI
@ -245,5 +245,10 @@ namespace Emby.Drawing.GDI
public void Dispose() public void Dispose()
{ {
} }
public string Name
{
get { return "GDI"; }
}
} }
} }

View File

@ -44,5 +44,10 @@ namespace Emby.Drawing
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
void CreateImageCollage(ImageCollageOptions options); void CreateImageCollage(ImageCollageOptions options);
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
} }
} }

View File

@ -206,6 +206,11 @@ namespace Emby.Drawing.ImageMagick
} }
} }
public string Name
{
get { return "ImageMagick"; }
}
private bool _disposed; private bool _disposed;
public void Dispose() public void Dispose()
{ {

View File

@ -433,7 +433,7 @@ namespace MediaBrowser.Api.LiveTv
var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false); var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedResult(result);
} }
public async Task<object> Get(GetRecommendedPrograms request) public async Task<object> Get(GetRecommendedPrograms request)
@ -450,7 +450,7 @@ namespace MediaBrowser.Api.LiveTv
var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false); var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedResult(result);
} }
public object Post(GetPrograms request) public object Post(GetPrograms request)
@ -473,7 +473,7 @@ namespace MediaBrowser.Api.LiveTv
}, CancellationToken.None).ConfigureAwait(false); }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedResult(result);
} }
public async Task<object> Get(GetRecording request) public async Task<object> Get(GetRecording request)

View File

@ -1627,7 +1627,7 @@ namespace MediaBrowser.Api.Playback
MediaSourceInfo mediaSource; MediaSourceInfo mediaSource;
if (string.IsNullOrWhiteSpace(request.LiveStreamId)) if (string.IsNullOrWhiteSpace(request.LiveStreamId))
{ {
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, false, cancellationToken).ConfigureAwait(false)).ToList(); var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
mediaSource = string.IsNullOrEmpty(request.MediaSourceId) mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
? mediaSources.First() ? mediaSources.First()

View File

@ -1,4 +1,6 @@
using MediaBrowser.Controller.Devices; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
@ -59,23 +61,27 @@ namespace MediaBrowser.Api.Playback
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly INetworkManager _networkManager;
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager) public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager)
{ {
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_config = config;
_networkManager = networkManager;
} }
public async Task<object> Get(GetPlaybackInfo request) public async Task<object> Get(GetPlaybackInfo request)
{ {
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false); var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
public async Task<object> Get(GetLiveMediaInfo request) public async Task<object> Get(GetLiveMediaInfo request)
{ {
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false); var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
@ -122,29 +128,38 @@ namespace MediaBrowser.Api.Playback
public async Task<object> Post(GetPostedPlaybackInfo request) public async Task<object> Post(GetPostedPlaybackInfo request)
{ {
var info = await GetPlaybackInfo(request.Id, request.UserId, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request); var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
var profile = request.DeviceProfile; var profile = request.DeviceProfile;
if (profile == null)
var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
if (caps != null)
{ {
var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); if (profile == null)
if (caps != null)
{ {
profile = caps.DeviceProfile; profile = caps.DeviceProfile;
} }
} }
var maxBitrate = request.MaxStreamingBitrate;
if (_config.Configuration.RemoteClientBitrateLimit > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp))
{
maxBitrate = Math.Min(maxBitrate ?? _config.Configuration.RemoteClientBitrateLimit, _config.Configuration.RemoteClientBitrateLimit);
}
var info = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
if (profile != null) if (profile != null)
{ {
var mediaSourceId = request.MediaSourceId; var mediaSourceId = request.MediaSourceId;
SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex); SetDeviceSpecificData(request.Id, info, profile, authInfo, maxBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex);
} }
return ToOptimizedResult(info); return ToOptimizedResult(info);
} }
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string mediaSourceId = null, string liveStreamId = null) private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null)
{ {
var result = new PlaybackInfoResponse(); var result = new PlaybackInfoResponse();
@ -153,7 +168,7 @@ namespace MediaBrowser.Api.Playback
IEnumerable<MediaSourceInfo> mediaSources; IEnumerable<MediaSourceInfo> mediaSources;
try try
{ {
mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, CancellationToken.None).ConfigureAwait(false); mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, supportedLiveMediaTypes, CancellationToken.None).ConfigureAwait(false);
} }
catch (PlaybackException ex) catch (PlaybackException ex)
{ {

View File

@ -136,11 +136,11 @@ namespace MediaBrowser.Api.Subtitles
_providerManager = providerManager; _providerManager = providerManager;
} }
public object Get(GetSubtitlePlaylist request) public async Task<object> Get(GetSubtitlePlaylist request)
{ {
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id)); var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
var mediaSource = _mediaSourceManager.GetStaticMediaSource(item, request.MediaSourceId, false); var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, false).ConfigureAwait(false);
var builder = new StringBuilder(); var builder = new StringBuilder();

View File

@ -101,12 +101,6 @@ namespace MediaBrowser.Common.Implementations
/// <value>The failed assemblies.</value> /// <value>The failed assemblies.</value>
public List<string> FailedAssemblies { get; protected set; } public List<string> FailedAssemblies { get; protected set; }
/// <summary>
/// Gets all types within all running assemblies
/// </summary>
/// <value>All types.</value>
public Type[] AllTypes { get; protected set; }
/// <summary> /// <summary>
/// Gets all concrete types. /// Gets all concrete types.
/// </summary> /// </summary>
@ -438,9 +432,10 @@ namespace MediaBrowser.Common.Implementations
Logger.Info("Loading {0}", assembly.FullName); Logger.Info("Loading {0}", assembly.FullName);
} }
AllTypes = assemblies.SelectMany(GetTypes).ToArray(); AllConcreteTypes = assemblies
.SelectMany(GetTypes)
AllConcreteTypes = AllTypes.Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType).ToArray(); .Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType)
.ToArray();
} }
/// <summary> /// <summary>

View File

@ -172,11 +172,11 @@ namespace MediaBrowser.Common.Implementations.Networking
Uri uri; Uri uri;
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri)) if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
{ {
var host = uri.DnsSafeHost;
Logger.Debug("Resolving host {0}", host);
try try
{ {
var host = uri.DnsSafeHost;
Logger.Debug("Resolving host {0}", host);
address = GetIpAddresses(host).FirstOrDefault(); address = GetIpAddresses(host).FirstOrDefault();
if (address != null) if (address != null)
@ -186,9 +186,13 @@ namespace MediaBrowser.Common.Implementations.Networking
return IsInLocalNetworkInternal(address.ToString(), false); return IsInLocalNetworkInternal(address.ToString(), false);
} }
} }
catch (InvalidOperationException)
{
// Can happen with reverse proxy or IIS url rewriting
}
catch (Exception ex) catch (Exception ex)
{ {
Logger.ErrorException("Error resovling hostname {0}", ex, host); Logger.ErrorException("Error resovling hostname", ex);
} }
} }
} }

View File

@ -43,18 +43,10 @@ namespace MediaBrowser.Controller.Library
/// <param name="id">The identifier.</param> /// <param name="id">The identifier.</param>
/// <param name="userId">The user identifier.</param> /// <param name="userId">The user identifier.</param>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param> /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
/// <param name="supportedLiveMediaTypes">The supported live media types.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns> /// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken); Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken);
/// <summary>
/// Gets the playack media sources.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;IEnumerable&lt;MediaSourceInfo&gt;&gt;.</returns>
Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the static media sources. /// Gets the static media sources.
@ -64,7 +56,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns> /// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null); IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
/// <summary> /// <summary>
/// Gets the static media source. /// Gets the static media source.
/// </summary> /// </summary>
@ -72,7 +64,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="mediaSourceId">The media source identifier.</param> /// <param name="mediaSourceId">The media source identifier.</param>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param> /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
/// <returns>MediaSourceInfo.</returns> /// <returns>MediaSourceInfo.</returns>
MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution); Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
/// <summary> /// <summary>
/// Opens the media source. /// Opens the media source.

View File

@ -1,5 +1,4 @@
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -892,7 +892,7 @@ namespace MediaBrowser.Dlna.PlayTo
request.MediaSource = hasMediaSources == null ? request.MediaSource = hasMediaSources == null ?
null : null :
mediaSourceManager.GetStaticMediaSource(hasMediaSources, request.MediaSourceId, false); mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, false).Result;

View File

@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, false, cancellationToken).ConfigureAwait(false); var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
var mediaSource = string.IsNullOrEmpty(request.MediaSourceId) var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
? mediaSources.First() ? mediaSources.First()

View File

@ -132,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int subtitleStreamIndex, int subtitleStreamIndex,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, false, cancellationToken).ConfigureAwait(false); var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
var mediaSource = mediaSources var mediaSource = mediaSources
.First(i => string.Equals(i.Id, mediaSourceId)); .First(i => string.Equals(i.Id, mediaSourceId));

View File

@ -208,6 +208,7 @@ namespace MediaBrowser.Model.Configuration
public bool EnableAudioArchiveFiles { get; set; } public bool EnableAudioArchiveFiles { get; set; }
public bool EnableVideoArchiveFiles { get; set; } public bool EnableVideoArchiveFiles { get; set; }
public int RemoteClientBitrateLimit { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class. /// Initializes a new instance of the <see cref="ServerConfiguration" /> class.

View File

@ -19,12 +19,14 @@ namespace MediaBrowser.Model.Session
public bool SupportsOfflineAccess { get; set; } public bool SupportsOfflineAccess { get; set; }
public DeviceProfile DeviceProfile { get; set; } public DeviceProfile DeviceProfile { get; set; }
public List<string> SupportedLiveMediaTypes { get; set; }
public ClientCapabilities() public ClientCapabilities()
{ {
PlayableMediaTypes = new List<string>(); PlayableMediaTypes = new List<string>();
SupportedCommands = new List<string>(); SupportedCommands = new List<string>();
SupportsPersistentIdentifier = true; SupportsPersistentIdentifier = true;
SupportedLiveMediaTypes = new List<string>();
} }
} }
} }

View File

@ -39,8 +39,9 @@ namespace MediaBrowser.Model.Users
public bool EnableLiveTvAccess { get; set; } public bool EnableLiveTvAccess { get; set; }
public bool EnableMediaPlayback { get; set; } public bool EnableMediaPlayback { get; set; }
public bool EnableMediaPlaybackTranscoding { get; set; } public bool EnableAudioPlaybackTranscoding { get; set; }
public bool EnableVideoPlaybackTranscoding { get; set; }
public bool EnableContentDeletion { get; set; } public bool EnableContentDeletion { get; set; }
public bool EnableContentDownloading { get; set; } public bool EnableContentDownloading { get; set; }
@ -68,8 +69,9 @@ namespace MediaBrowser.Model.Users
EnableSyncTranscoding = true; EnableSyncTranscoding = true;
EnableMediaPlayback = true; EnableMediaPlayback = true;
EnableMediaPlaybackTranscoding = true; EnableAudioPlaybackTranscoding = true;
EnableVideoPlaybackTranscoding = true;
EnableLiveTvManagement = true; EnableLiveTvManagement = true;
EnableLiveTvAccess = true; EnableLiveTvAccess = true;

View File

@ -129,12 +129,7 @@ namespace MediaBrowser.Server.Implementations.Library
return list; return list;
} }
public Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken) public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken)
{
return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken);
}
public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken)
{ {
var item = _libraryManager.GetItemById(id); var item = _libraryManager.GetItemById(id);
@ -184,9 +179,19 @@ namespace MediaBrowser.Server.Implementations.Library
{ {
if (user != null) if (user != null)
{ {
if (!user.Policy.EnableMediaPlaybackTranscoding) if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{ {
source.SupportsTranscoding = false; if (!user.Policy.EnableAudioPlaybackTranscoding)
{
source.SupportsTranscoding = false;
}
}
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
{
if (!user.Policy.EnableVideoPlaybackTranscoding)
{
source.SupportsTranscoding = false;
}
} }
} }
} }
@ -238,9 +243,12 @@ namespace MediaBrowser.Server.Implementations.Library
} }
} }
public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution) public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
{ {
return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video },
CancellationToken.None).ConfigureAwait(false);
return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
} }
public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null) public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)

View File

@ -122,7 +122,7 @@
"LabelFree": "Free", "LabelFree": "Free",
"HeaderPlaybackError": "Playback Error", "HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.", "MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
"MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.", "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.", "MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.", "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio", "HeaderSelectAudio": "Select Audio",

View File

@ -1410,6 +1410,10 @@
"LabelUploadSpeedLimit": "Upload speed limit (mbps):", "LabelUploadSpeedLimit": "Upload speed limit (mbps):",
"OptionAllowSyncTranscoding": "Allow syncing that requires transcoding", "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
"HeaderPlayback": "Media Playback", "HeaderPlayback": "Media Playback",
"OptionAllowMediaPlaybackTranscoding": "Allow media playback that requires transcoding", "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
"OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy." "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
"OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
"TabStreaming": "Streaming",
"LabelRemoteClientBitrateLimit": "Remote client bitrate limit (mbps):",
"LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle."
} }

View File

@ -305,12 +305,9 @@ namespace MediaBrowser.Server.Implementations.Session
} }
} }
private async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId) private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
{ {
var sources = await _mediaSourceManager.GetPlayackMediaSources(item.Id.ToString("N"), false, CancellationToken.None) return _mediaSourceManager.GetMediaSource(item, mediaSourceId, false);
.ConfigureAwait(false);
return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
} }
/// <summary> /// <summary>

View File

@ -195,17 +195,39 @@ namespace MediaBrowser.Server.Implementations.Sync
} }
}; };
var maxAudioChannels = supportsAc3 || supportsDca ? "5" : "2";
codecProfiles.Add(new CodecProfile codecProfiles.Add(new CodecProfile
{ {
Type = CodecType.VideoAudio, Type = CodecType.VideoAudio,
Codec = "ac3",
Conditions = new[] Conditions = new[]
{ {
new ProfileCondition new ProfileCondition
{ {
Condition = ProfileConditionType.LessThanEqual, Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.AudioChannels, Property = ProfileConditionValue.AudioChannels,
Value = maxAudioChannels, Value = "5",
IsRequired = true
},
new ProfileCondition
{
Condition = ProfileConditionType.Equals,
Property = ProfileConditionValue.IsSecondaryAudio,
Value = "false",
IsRequired = false
}
}
});
codecProfiles.Add(new CodecProfile
{
Type = CodecType.VideoAudio,
Codec = "ac3",
Conditions = new[]
{
new ProfileCondition
{
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.AudioChannels,
Value = "2",
IsRequired = true IsRequired = true
}, },
new ProfileCondition new ProfileCondition

View File

@ -482,6 +482,7 @@ namespace MediaBrowser.WebDashboard.Api
"selectserver.js", "selectserver.js",
"serversecurity.js", "serversecurity.js",
"songs.js", "songs.js",
"streamingsettings.js",
"supporterkeypage.js", "supporterkeypage.js",
"supporterpage.js", "supporterpage.js",
"syncactivity.js", "syncactivity.js",

View File

@ -150,6 +150,9 @@
<Content Include="dashboard-ui\scripts\selectserver.js"> <Content Include="dashboard-ui\scripts\selectserver.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\streamingsettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\syncjob.js"> <Content Include="dashboard-ui\scripts\syncjob.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -174,6 +177,9 @@
<Content Include="dashboard-ui\selectserver.html"> <Content Include="dashboard-ui\selectserver.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\streamingsettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\syncjob.html"> <Content Include="dashboard-ui\syncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>