Merge pull request #2145 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-09-08 02:44:27 -04:00 committed by GitHub
commit 51f6cd999f
15 changed files with 191 additions and 63 deletions

View File

@ -337,9 +337,9 @@ namespace MediaBrowser.Api.Playback
/// Gets the video bitrate to specify on the command line
/// </summary>
/// <param name="state">The state.</param>
/// <param name="videoCodec">The video codec.</param>
/// <param name="videoEncoder">The video codec.</param>
/// <returns>System.String.</returns>
protected string GetVideoQualityParam(StreamState state, string videoCodec)
protected string GetVideoQualityParam(StreamState state, string videoEncoder)
{
var param = string.Empty;
@ -348,7 +348,7 @@ namespace MediaBrowser.Api.Playback
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
{
if (!string.IsNullOrWhiteSpace(encodingOptions.H264Preset))
{
@ -369,7 +369,7 @@ namespace MediaBrowser.Api.Playback
}
}
else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
{
param += "-preset fast";
@ -377,20 +377,20 @@ namespace MediaBrowser.Api.Playback
}
// h264 (h264_qsv)
else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
param += "-preset 7 -look_ahead 0";
}
// h264 (h264_nvenc)
else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
{
param += "-preset default";
}
// webm
else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase))
{
// Values 0-3, 0 being highest quality but slower
var profileScore = 0;
@ -417,23 +417,23 @@ namespace MediaBrowser.Api.Playback
qmax);
}
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase))
{
param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
}
// asf/wmv
else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase))
{
param += "-qmin 2";
}
else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
param += "-mbd 2";
}
param += GetVideoBitrateParam(state, videoCodec);
param += GetVideoBitrateParam(state, videoEncoder);
var framerate = GetFramerateParam(state);
if (framerate.HasValue)
@ -448,8 +448,8 @@ namespace MediaBrowser.Api.Playback
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
{
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
// not supported by h264_omx
param += " -profile:v " + state.VideoRequest.Profile;
@ -458,11 +458,13 @@ namespace MediaBrowser.Api.Playback
if (!string.IsNullOrEmpty(state.VideoRequest.Level))
{
var level = NormalizeTranscodingLevel(state.OutputVideoCodec, state.VideoRequest.Level);
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
{
switch (state.VideoRequest.Level)
switch (level)
{
case "30":
param += " -level 3";
@ -492,20 +494,20 @@ namespace MediaBrowser.Api.Playback
param += " -level 5.2";
break;
default:
param += " -level " + state.VideoRequest.Level;
param += " -level " + level;
break;
}
}
else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase))
{
param += " -level " + state.VideoRequest.Level;
param += " -level " + level;
}
}
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
param = "-pix_fmt yuv420p " + param;
}
@ -513,6 +515,25 @@ namespace MediaBrowser.Api.Playback
return param;
}
private string NormalizeTranscodingLevel(string videoCodec, string level)
{
double requestLevel;
// Clients may direct play higher than level 41, but there's no reason to transcode higher
if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel))
{
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
if (requestLevel > 41)
{
return "41";
}
}
}
return level;
}
protected string GetAudioFilterParam(StreamState state, bool isHls)
{
var volParam = string.Empty;
@ -1176,17 +1197,21 @@ namespace MediaBrowser.Api.Playback
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
}
if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive)
if (state.IsInputVideo && transcodingJob.Type == TranscodingJobType.Progressive && !transcodingJob.HasExited)
{
await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false);
if (state.ReadInputAtNativeFramerate)
if (state.ReadInputAtNativeFramerate && !transcodingJob.HasExited)
{
await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
}
}
if (!transcodingJob.HasExited)
{
StartThrottler(state, transcodingJob);
}
ReportUsage(state);
return transcodingJob;

View File

@ -31,6 +31,8 @@ namespace MediaBrowser.Controller.Channels
/// <returns>ChannelFeatures.</returns>
ChannelFeatures GetChannelFeatures(string id);
bool SupportsSync(string channelId);
/// <summary>
/// Gets all channel features.
/// </summary>

View File

@ -1057,10 +1057,20 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IList{BaseItem}.</returns>
public IList<BaseItem> GetRecursiveChildren()
{
return GetRecursiveChildren(i => true);
return GetRecursiveChildren(true);
}
public IList<BaseItem> GetRecursiveChildren(bool includeLinkedChildren)
{
return GetRecursiveChildren(i => true, includeLinkedChildren);
}
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
{
return GetRecursiveChildren(filter, true);
}
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter, bool includeLinkedChildren)
{
var result = new Dictionary<Guid, BaseItem>();

View File

@ -483,7 +483,9 @@ namespace MediaBrowser.Dlna.PlayTo
{
if (OnDeviceUnavailable != null)
{
_logger.Debug("Disposing device due to loss of connection");
OnDeviceUnavailable();
return;
}
}
if (_successiveStopCount >= maxSuccessiveStopReturns)

View File

@ -595,23 +595,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// Gets the video bitrate to specify on the command line
/// </summary>
/// <param name="state">The state.</param>
/// <param name="videoCodec">The video codec.</param>
/// <param name="videoEncoder">The video codec.</param>
/// <returns>System.String.</returns>
protected string GetVideoQualityParam(EncodingJob state, string videoCodec)
protected string GetVideoQualityParam(EncodingJob state, string videoEncoder)
{
var param = string.Empty;
var isVc1 = state.VideoStream != null &&
string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
{
param = "-preset superfast";
param += " -crf 23";
}
else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
{
param = "-preset fast";
@ -619,20 +619,20 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
// h264 (h264_qsv)
else if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
param = "-preset 7 -look_ahead 0";
}
// h264 (h264_nvenc)
else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
{
param = "-preset llhq";
}
// webm
else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "libvpx", StringComparison.OrdinalIgnoreCase))
{
// Values 0-3, 0 being highest quality but slower
var profileScore = 0;
@ -659,23 +659,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
qmax);
}
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "mpeg4", StringComparison.OrdinalIgnoreCase))
{
param = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
}
// asf/wmv
else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase))
{
param = "-qmin 2";
}
else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase))
{
param = "-mbd 2";
}
param += GetVideoBitrateParam(state, videoCodec);
param += GetVideoBitrateParam(state, videoEncoder);
var framerate = GetFramerateParam(state);
if (framerate.HasValue)
@ -690,8 +690,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!string.IsNullOrEmpty(state.Options.Profile))
{
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
// not supported by h264_omx
param += " -profile:v " + state.Options.Profile;
@ -702,9 +702,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!string.IsNullOrEmpty(levelString))
{
levelString = NormalizeTranscodingLevel(state.OutputVideoCodec, levelString);
// h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format
if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
{
switch (levelString)
{
@ -740,16 +742,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
break;
}
}
else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase))
{
param += " -level " + levelString;
}
}
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
param = "-pix_fmt yuv420p " + param;
}
@ -757,6 +759,25 @@ namespace MediaBrowser.MediaEncoding.Encoder
return param;
}
private string NormalizeTranscodingLevel(string videoCodec, string level)
{
double requestLevel;
// Clients may direct play higher than level 41, but there's no reason to transcode higher
if (double.TryParse(level, NumberStyles.Any, UsCulture, out requestLevel))
{
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
if (requestLevel > 41)
{
return "41";
}
}
}
return level;
}
protected string GetVideoBitrateParam(EncodingJob state, string videoCodec)
{
var bitrate = state.OutputVideoBitrate;

View File

@ -13,6 +13,7 @@ namespace MediaBrowser.Model.LiveTv
public string SeriesRecordingPath { get; set; }
public bool EnableAutoOrganize { get; set; }
public bool EnableRecordingEncoding { get; set; }
public string RecordingEncodingFormat { get; set; }
public bool EnableRecordingSubfolders { get; set; }
public bool EnableOriginalAudioWithEncodedRecordings { get; set; }
@ -31,6 +32,7 @@ namespace MediaBrowser.Model.LiveTv
TunerHosts = new List<TunerHostInfo>();
ListingProviders = new List<ListingsProviderInfo>();
MediaLocationsCreated = new string[] { };
RecordingEncodingFormat = "mp4";
}
}

View File

@ -530,6 +530,19 @@ namespace MediaBrowser.Server.Implementations.Channels
return GetChannelFeaturesDto(channel, channelProvider, channelProvider.GetChannelFeatures());
}
public bool SupportsSync(string channelId)
{
if (string.IsNullOrWhiteSpace(channelId))
{
throw new ArgumentNullException("channelId");
}
//var channel = GetChannel(channelId);
var channelProvider = GetChannelProvider(channelId);
return channelProvider.GetChannelFeatures().SupportsContentDownloading;
}
public ChannelFeatures GetChannelFeaturesDto(Channel channel,
IChannel provider,
InternalChannelFeatures features)
@ -1450,6 +1463,24 @@ namespace MediaBrowser.Server.Implementations.Channels
return result;
}
internal IChannel GetChannelProvider(string internalChannelId)
{
if (internalChannelId == null)
{
throw new ArgumentNullException("internalChannelId");
}
var result = GetAllChannels()
.FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), internalChannelId, StringComparison.OrdinalIgnoreCase));
if (result == null)
{
throw new ResourceNotFoundException("No channel provider found for channel id " + internalChannelId);
}
return result;
}
private IEnumerable<BaseItem> ApplyFilters(IEnumerable<BaseItem> items, IEnumerable<ItemFilter> filters, User user)
{
foreach (var filter in filters.OrderByDescending(f => (int)f))

View File

@ -401,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.Library
var locationType = item.LocationType;
var children = item.IsFolder
? ((Folder)item).GetRecursiveChildren().ToList()
? ((Folder)item).GetRecursiveChildren(false).ToList()
: new List<BaseItem>();
foreach (var metadataPath in GetMetadataPaths(item, children))

View File

@ -46,9 +46,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_httpClient = httpClient;
}
private string OutputFormat
{
get
{
var format = _liveTvOptions.RecordingEncodingFormat;
if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase))
{
return "mkv";
}
return "mp4";
}
}
public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile)
{
return Path.ChangeExtension(targetFile, ".mp4");
return Path.ChangeExtension(targetFile, "." + OutputFormat);
}
public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
@ -233,15 +248,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private string GetAudioArgs(MediaSourceInfo mediaSource)
{
// do not copy aac because many players have difficulty with aac_latm
var copyAudio = new[] { "mp3" };
var mediaStreams = mediaSource.MediaStreams ?? new List<MediaStream>();
var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty;
if (copyAudio.Contains(inputAudioCodec, StringComparer.OrdinalIgnoreCase))
{
return "-codec:a:0 copy";
}
// do not copy aac because many players have difficulty with aac_latm
if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase))
{
return "-codec:a:0 copy";

View File

@ -785,9 +785,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
get { return "Schedules Direct"; }
}
public static string TypeName = "SchedulesDirect";
public string Type
{
get { return "SchedulesDirect"; }
get { return TypeName; }
}
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)

View File

@ -35,6 +35,7 @@ using MediaBrowser.Common.Security;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Events;
using MediaBrowser.Server.Implementations.LiveTv.Listings;
namespace MediaBrowser.Server.Implementations.LiveTv
{
@ -2802,6 +2803,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
feature = "embytvseriesrecordings";
}
var config = GetConfiguration();
if (config.TunerHosts.Count(i => i.IsEnabled) > 0 &&
config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
{
return Task.FromResult(new MBRegistrationRecord
{
IsRegistered = true,
IsValid = true
});
}
return _security.GetRegistrationStatus(feature);
}

View File

@ -541,6 +541,11 @@ namespace MediaBrowser.Server.Implementations.Sync
return true;
}
if (item.SourceType == SourceType.Channel)
{
return BaseItem.ChannelManager.SupportsSync(item.ChannelId);
}
return item.LocationType == LocationType.FileSystem || item is Season;
}

View File

@ -363,7 +363,10 @@ namespace MediaBrowser.Server.Startup.Common
private void PerformPreInitMigrations()
{
var migrations = new List<IVersionMigration>();
var migrations = new List<IVersionMigration>
{
new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename)
};
foreach (var task in migrations)
{
@ -383,8 +386,7 @@ namespace MediaBrowser.Server.Startup.Common
var migrations = new List<IVersionMigration>
{
new MovieDbEpisodeProviderMigration(ServerConfigurationManager),
new DbMigration(ServerConfigurationManager, TaskManager),
new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename)
new DbMigration(ServerConfigurationManager, TaskManager)
};
foreach (var task in migrations)

View File

@ -331,7 +331,7 @@ namespace MediaBrowser.ServerApplication
Application.Run();
}
private static SplashForm _splash;
internal static SplashForm _splash;
private static Thread _splashThread;
private static void ShowSplashScreen(Version appVersion, Progress<double> progress, ILogger logger)
{

View File

@ -212,7 +212,12 @@ namespace MediaBrowser.ServerApplication.Native
private bool Confirm()
{
return MessageBox.Show("Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK;
if (MainStartup._splash == null)
{
return false;
}
return MessageBox.Show(MainStartup._splash, "Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK;
}
public bool PortsRequireAuthorization(string applicationPath)
@ -242,7 +247,7 @@ namespace MediaBrowser.ServerApplication.Native
if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1)
{
_logger.Info("Found windows firewall rule: " + data);
_logger.Info("Found potential windows firewall rule blocking Emby Server: " + data);
return Confirm();
}