aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs17
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs36
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs74
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs28
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs29
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs10
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs10
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj1
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs7
11 files changed, 122 insertions, 98 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 1b8234973..380ece2f2 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1417,7 +1417,6 @@ namespace MediaBrowser.Api.Playback
List<MediaStream> mediaStreams = null;
state.ItemType = item.GetType().Name;
- state.ReadInputAtNativeFramerate = true;
if (item is ILiveTvRecording)
{
@@ -1479,6 +1478,7 @@ namespace MediaBrowser.Api.Playback
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
mediaStreams = new List<MediaStream>();
+ state.ReadInputAtNativeFramerate = true;
state.OutputAudioSync = "1000";
state.DeInterlace = true;
state.InputVideoSync = "-1";
@@ -1489,13 +1489,13 @@ namespace MediaBrowser.Api.Playback
}
else if (item is IChannelMediaItem)
{
- var source = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
+ var mediaSource = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- state.InputProtocol = source.Protocol;
- state.MediaPath = source.Path;
+ state.InputProtocol = mediaSource.Protocol;
+ state.MediaPath = mediaSource.Path;
state.RunTimeTicks = item.RunTimeTicks;
- state.RemoteHttpHeaders = source.RequiredHttpHeaders;
- mediaStreams = source.MediaStreams;
+ state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
+ mediaStreams = mediaSource.MediaStreams;
}
else
{
@@ -1539,6 +1539,11 @@ namespace MediaBrowser.Api.Playback
state.DeInterlace = true;
}
+ if (state.InputProtocol == MediaProtocol.Rtmp)
+ {
+ state.ReadInputAtNativeFramerate = true;
+ }
+
var videoRequest = request as VideoStreamRequest;
AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index e41a331be..57c2244c7 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -119,9 +119,8 @@ namespace MediaBrowser.Api.Playback.Hls
}
}
- int audioBitrate;
- int videoBitrate;
- GetPlaylistBitrates(state, out audioBitrate, out videoBitrate);
+ var audioBitrate = state.OutputAudioBitrate ?? 0;
+ var videoBitrate = state.OutputVideoBitrate ?? 0;
var appendBaselineStream = false;
var baselineStreamBitrate = 64000;
@@ -162,37 +161,6 @@ namespace MediaBrowser.Api.Playback.Hls
return minimumSegmentCount;
}
- /// <summary>
- /// Gets the playlist bitrates.
- /// </summary>
- /// <param name="state">The state.</param>
- /// <param name="audioBitrate">The audio bitrate.</param>
- /// <param name="videoBitrate">The video bitrate.</param>
- protected void GetPlaylistBitrates(StreamState state, out int audioBitrate, out int videoBitrate)
- {
- var audioBitrateParam = state.OutputAudioBitrate;
- var videoBitrateParam = state.OutputVideoBitrate;
-
- if (!audioBitrateParam.HasValue)
- {
- if (state.AudioStream != null)
- {
- audioBitrateParam = state.AudioStream.BitRate;
- }
- }
-
- if (!videoBitrateParam.HasValue)
- {
- if (state.VideoStream != null)
- {
- videoBitrateParam = state.VideoStream.BitRate;
- }
- }
-
- audioBitrate = audioBitrateParam ?? 0;
- videoBitrate = videoBitrateParam ?? 0;
- }
-
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
{
var builder = new StringBuilder();
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 5913e81db..b5b6849ce 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -304,45 +304,79 @@ namespace MediaBrowser.Api.Playback.Hls
{
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
- int audioBitrate;
- int videoBitrate;
- GetPlaylistBitrates(state, out audioBitrate, out videoBitrate);
+ var audioBitrate = state.OutputAudioBitrate ?? 0;
+ var videoBitrate = state.OutputVideoBitrate ?? 0;
- var appendBaselineStream = false;
- var baselineStreamBitrate = 64000;
-
- var hlsVideoRequest = state.VideoRequest as GetMasterHlsVideoStream;
- if (hlsVideoRequest != null)
- {
- appendBaselineStream = hlsVideoRequest.AppendBaselineStream;
- baselineStreamBitrate = hlsVideoRequest.BaselineStreamAudioBitRate ?? baselineStreamBitrate;
- }
-
- var playlistText = GetMasterPlaylistFileText(videoBitrate + audioBitrate);
+ var playlistText = GetMasterPlaylistFileText(state, videoBitrate + audioBitrate);
return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
- private string GetMasterPlaylistFileText(int bitrate)
+ private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
{
var builder = new StringBuilder();
builder.AppendLine("#EXTM3U");
- // Pad a little to satisfy the apple hls validator
- var paddedBitrate = Convert.ToInt32(bitrate * 1.05);
-
var queryStringIndex = Request.RawUrl.IndexOf('?');
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
// Main stream
- builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
var playlistUrl = "main.m3u8" + queryString;
- builder.AppendLine(playlistUrl);
+ AppendPlaylist(builder, playlistUrl, totalBitrate);
+
+ if (state.VideoRequest.VideoBitRate.HasValue)
+ {
+ var requestedVideoBitrate = state.VideoRequest.VideoBitRate.Value;
+
+ // By default, vary by just 200k
+ var variation = GetBitrateVariation(totalBitrate);
+
+ var newBitrate = totalBitrate - variation;
+ AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - variation).ToString(UsCulture)), newBitrate);
+
+ newBitrate = totalBitrate - (2 * variation);
+ AppendPlaylist(builder, playlistUrl.Replace(requestedVideoBitrate.ToString(UsCulture), (requestedVideoBitrate - (2 * variation)).ToString(UsCulture)), newBitrate);
+ }
return builder.ToString();
}
+ private void AppendPlaylist(StringBuilder builder, string url, int bitrate)
+ {
+ builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate.ToString(UsCulture));
+ builder.AppendLine(url);
+ }
+
+ private int GetBitrateVariation(int bitrate)
+ {
+ // By default, vary by just 200k
+ var variation = 200000;
+
+ if (bitrate >= 10000000)
+ {
+ variation = 2000000;
+ }
+ else if (bitrate >= 5000000)
+ {
+ variation = 1500000;
+ }
+ else if (bitrate >= 3000000)
+ {
+ variation = 1000000;
+ }
+ else if (bitrate >= 2000000)
+ {
+ variation = 500000;
+ }
+ else if (bitrate >= 1000000)
+ {
+ variation = 300000;
+ }
+
+ return variation;
+ }
+
public object Get(GetMainHlsVideoStream request)
{
var result = GetPlaylistAsync(request, "main").Result;
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index a5d19b5cb..f7b888f82 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using MediaBrowser.Model.Weather;
+using MediaBrowser.Model.Weather;
using System;
namespace MediaBrowser.Model.Configuration
@@ -211,7 +210,6 @@ namespace MediaBrowser.Model.Configuration
public string[] ManualLoginClients { get; set; }
public ChannelOptions ChannelOptions { get; set; }
-
public ChapterOptions ChapterOptions { get; set; }
public bool DefaultMetadataSettingsApplied { get; set; }
@@ -274,8 +272,6 @@ namespace MediaBrowser.Model.Configuration
SubtitleOptions = new SubtitleOptions();
- ChannelOptions = new ChannelOptions();
-
LiveTvOptions = new LiveTvOptions();
TvFileOrganizationOptions = new TvFileOrganizationOptions();
}
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index b2ca97f55..9188a2281 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -24,40 +23,17 @@ namespace MediaBrowser.Providers.MediaInfo
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new ConcurrentDictionary<string, SemaphoreSlim>();
- private readonly IIsoManager _isoManager;
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
- public AudioImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem)
+ public AudioImageProvider(IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem)
{
- _isoManager = isoManager;
_mediaEncoder = mediaEncoder;
_config = config;
_fileSystem = fileSystem;
}
- /// <summary>
- /// The null mount task result
- /// </summary>
- protected readonly Task<IIsoMount> NullMountTaskResult = Task.FromResult<IIsoMount>(null);
-
- /// <summary>
- /// Mounts the iso if needed.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IIsoMount}.</returns>
- protected Task<IIsoMount> MountIsoIfNeeded(Video item, CancellationToken cancellationToken)
- {
- if (item.VideoType == VideoType.Iso)
- {
- return _isoManager.Mount(item.Path, cancellationToken);
- }
-
- return NullMountTaskResult;
- }
-
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType> { ImageType.Primary };
@@ -156,7 +132,7 @@ namespace MediaBrowser.Providers.MediaInfo
public bool Supports(IHasImages item)
{
- return item.LocationType == LocationType.FileSystem && item is Audio;
+ return item is Audio;
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index 0f2ed1642..a856d5dba 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Providers.MediaInfo
audio.FormatName = mediaInfo.Format;
audio.TotalBitrate = mediaInfo.TotalBitrate;
- audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.Video);
+ audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage);
if (data.streams != null)
{
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
new file mode 100644
index 000000000..9dfb0404e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Channels
+{
+ public static class ChannelConfigurationExtension
+ {
+ public static ChannelOptions GetChannelsConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<ChannelOptions>("channels");
+ }
+ }
+
+ public class ChannelConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "channels",
+ ConfigurationType = typeof (ChannelOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
index ce5c41f89..d219ab027 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
@@ -146,9 +146,11 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var numComplete = 0;
+ var options = _config.GetChannelsConfiguration();
+
foreach (var item in result.Items)
{
- if (_config.Configuration.ChannelOptions.DownloadingChannels.Contains(item.ChannelId))
+ if (options.DownloadingChannels.Contains(item.ChannelId))
{
try
{
@@ -282,12 +284,14 @@ namespace MediaBrowser.Server.Implementations.Channels
private void CleanChannelContent(CancellationToken cancellationToken)
{
- if (!_config.Configuration.ChannelOptions.MaxDownloadAge.HasValue)
+ var options = _config.GetChannelsConfiguration();
+
+ if (!options.MaxDownloadAge.HasValue)
{
return;
}
- var minDateModified = DateTime.UtcNow.AddDays(0 - _config.Configuration.ChannelOptions.MaxDownloadAge.Value);
+ var minDateModified = DateTime.UtcNow.AddDays(0 - options.MaxDownloadAge.Value);
var path = _manager.ChannelDownloadPath;
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 188a26c60..c6dd80758 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -77,9 +77,11 @@ namespace MediaBrowser.Server.Implementations.Channels
{
get
{
- if (!string.IsNullOrWhiteSpace(_config.Configuration.ChannelOptions.DownloadPath))
+ var options = _config.GetChannelsConfiguration();
+
+ if (!string.IsNullOrWhiteSpace(options.DownloadPath))
{
- return _config.Configuration.ChannelOptions.DownloadPath;
+ return options.DownloadPath;
}
return Path.Combine(_config.ApplicationPaths.ProgramDataPath, "channels");
@@ -374,7 +376,9 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var list = channelMediaSources.ToList();
- var width = _config.Configuration.ChannelOptions.PreferredStreamingWidth;
+ var options = _config.GetChannelsConfiguration();
+
+ var width = options.PreferredStreamingWidth;
if (width.HasValue)
{
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 7410f6377..340107851 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -101,6 +101,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Channels\ChannelConfigurations.cs" />
<Compile Include="Channels\ChannelDownloadScheduledTask.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" />
<Compile Include="Channels\ChannelItemImageProvider.cs" />
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 96aa9c9d5..87f18e4cb 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -310,6 +310,13 @@ namespace MediaBrowser.ServerApplication
saveConfig = true;
}
+ if (ServerConfigurationManager.Configuration.ChannelOptions != null)
+ {
+ ServerConfigurationManager.SaveConfiguration("channels", ServerConfigurationManager.Configuration.ChannelOptions);
+ ServerConfigurationManager.Configuration.ChannelOptions = null;
+ saveConfig = true;
+ }
+
if (saveConfig)
{
ServerConfigurationManager.SaveConfiguration();