commit
51f6cd999f
|
@ -337,9 +337,9 @@ namespace MediaBrowser.Api.Playback
|
||||||
/// Gets the video bitrate to specify on the command line
|
/// Gets the video bitrate to specify on the command line
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <param name="videoCodec">The video codec.</param>
|
/// <param name="videoEncoder">The video codec.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetVideoQualityParam(StreamState state, string videoCodec)
|
protected string GetVideoQualityParam(StreamState state, string videoEncoder)
|
||||||
{
|
{
|
||||||
var param = string.Empty;
|
var param = string.Empty;
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||||
|
|
||||||
if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(encodingOptions.H264Preset))
|
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";
|
param += "-preset fast";
|
||||||
|
|
||||||
|
@ -377,20 +377,20 @@ namespace MediaBrowser.Api.Playback
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (h264_qsv)
|
// 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";
|
param += "-preset 7 -look_ahead 0";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (h264_nvenc)
|
// h264 (h264_nvenc)
|
||||||
else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param += "-preset default";
|
param += "-preset default";
|
||||||
}
|
}
|
||||||
|
|
||||||
// webm
|
// 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
|
// Values 0-3, 0 being highest quality but slower
|
||||||
var profileScore = 0;
|
var profileScore = 0;
|
||||||
|
@ -417,23 +417,23 @@ namespace MediaBrowser.Api.Playback
|
||||||
qmax);
|
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";
|
param += "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
// asf/wmv
|
// asf/wmv
|
||||||
else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param += "-qmin 2";
|
param += "-qmin 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param += "-mbd 2";
|
param += "-mbd 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
param += GetVideoBitrateParam(state, videoCodec);
|
param += GetVideoBitrateParam(state, videoEncoder);
|
||||||
|
|
||||||
var framerate = GetFramerateParam(state);
|
var framerate = GetFramerateParam(state);
|
||||||
if (framerate.HasValue)
|
if (framerate.HasValue)
|
||||||
|
@ -448,8 +448,8 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
|
if (!string.IsNullOrEmpty(state.VideoRequest.Profile))
|
||||||
{
|
{
|
||||||
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// not supported by h264_omx
|
// not supported by h264_omx
|
||||||
param += " -profile:v " + state.VideoRequest.Profile;
|
param += " -profile:v " + state.VideoRequest.Profile;
|
||||||
|
@ -458,11 +458,13 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(state.VideoRequest.Level))
|
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
|
// 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) ||
|
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (state.VideoRequest.Level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case "30":
|
case "30":
|
||||||
param += " -level 3";
|
param += " -level 3";
|
||||||
|
@ -492,20 +494,20 @@ namespace MediaBrowser.Api.Playback
|
||||||
param += " -level 5.2";
|
param += " -level 5.2";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
param += " -level " + state.VideoRequest.Level;
|
param += " -level " + level;
|
||||||
break;
|
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) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-pix_fmt yuv420p " + param;
|
param = "-pix_fmt yuv420p " + param;
|
||||||
}
|
}
|
||||||
|
@ -513,6 +515,25 @@ namespace MediaBrowser.Api.Playback
|
||||||
return param;
|
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)
|
protected string GetAudioFilterParam(StreamState state, bool isHls)
|
||||||
{
|
{
|
||||||
var volParam = string.Empty;
|
var volParam = string.Empty;
|
||||||
|
@ -1176,17 +1197,21 @@ namespace MediaBrowser.Api.Playback
|
||||||
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
|
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);
|
await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
if (state.ReadInputAtNativeFramerate)
|
if (state.ReadInputAtNativeFramerate && !transcodingJob.HasExited)
|
||||||
{
|
{
|
||||||
await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
|
await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartThrottler(state, transcodingJob);
|
if (!transcodingJob.HasExited)
|
||||||
|
{
|
||||||
|
StartThrottler(state, transcodingJob);
|
||||||
|
}
|
||||||
|
|
||||||
ReportUsage(state);
|
ReportUsage(state);
|
||||||
|
|
||||||
return transcodingJob;
|
return transcodingJob;
|
||||||
|
|
|
@ -31,6 +31,8 @@ namespace MediaBrowser.Controller.Channels
|
||||||
/// <returns>ChannelFeatures.</returns>
|
/// <returns>ChannelFeatures.</returns>
|
||||||
ChannelFeatures GetChannelFeatures(string id);
|
ChannelFeatures GetChannelFeatures(string id);
|
||||||
|
|
||||||
|
bool SupportsSync(string channelId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all channel features.
|
/// Gets all channel features.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1057,10 +1057,20 @@ namespace MediaBrowser.Controller.Entities
|
||||||
/// <returns>IList{BaseItem}.</returns>
|
/// <returns>IList{BaseItem}.</returns>
|
||||||
public IList<BaseItem> GetRecursiveChildren()
|
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)
|
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>();
|
var result = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
|
|
|
@ -483,7 +483,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
if (OnDeviceUnavailable != null)
|
if (OnDeviceUnavailable != null)
|
||||||
{
|
{
|
||||||
|
_logger.Debug("Disposing device due to loss of connection");
|
||||||
OnDeviceUnavailable();
|
OnDeviceUnavailable();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_successiveStopCount >= maxSuccessiveStopReturns)
|
if (_successiveStopCount >= maxSuccessiveStopReturns)
|
||||||
|
|
|
@ -595,23 +595,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
/// Gets the video bitrate to specify on the command line
|
/// Gets the video bitrate to specify on the command line
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <param name="videoCodec">The video codec.</param>
|
/// <param name="videoEncoder">The video codec.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetVideoQualityParam(EncodingJob state, string videoCodec)
|
protected string GetVideoQualityParam(EncodingJob state, string videoEncoder)
|
||||||
{
|
{
|
||||||
var param = string.Empty;
|
var param = string.Empty;
|
||||||
|
|
||||||
var isVc1 = state.VideoStream != null &&
|
var isVc1 = state.VideoStream != null &&
|
||||||
string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
|
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 = "-preset superfast";
|
||||||
|
|
||||||
param += " -crf 23";
|
param += " -crf 23";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoCodec, "libx265", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "libx265", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-preset fast";
|
param = "-preset fast";
|
||||||
|
|
||||||
|
@ -619,20 +619,20 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (h264_qsv)
|
// 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";
|
param = "-preset 7 -look_ahead 0";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// h264 (h264_nvenc)
|
// h264 (h264_nvenc)
|
||||||
else if (string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-preset llhq";
|
param = "-preset llhq";
|
||||||
}
|
}
|
||||||
|
|
||||||
// webm
|
// 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
|
// Values 0-3, 0 being highest quality but slower
|
||||||
var profileScore = 0;
|
var profileScore = 0;
|
||||||
|
@ -659,23 +659,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
qmax);
|
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";
|
param = "-mbd rd -flags +mv4+aic -trellis 2 -cmp 2 -subcmp 2 -bf 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
// asf/wmv
|
// asf/wmv
|
||||||
else if (string.Equals(videoCodec, "wmv2", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "wmv2", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-qmin 2";
|
param = "-qmin 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(videoEncoder, "msmpeg4", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-mbd 2";
|
param = "-mbd 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
param += GetVideoBitrateParam(state, videoCodec);
|
param += GetVideoBitrateParam(state, videoEncoder);
|
||||||
|
|
||||||
var framerate = GetFramerateParam(state);
|
var framerate = GetFramerateParam(state);
|
||||||
if (framerate.HasValue)
|
if (framerate.HasValue)
|
||||||
|
@ -690,8 +690,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(state.Options.Profile))
|
if (!string.IsNullOrEmpty(state.Options.Profile))
|
||||||
{
|
{
|
||||||
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// not supported by h264_omx
|
// not supported by h264_omx
|
||||||
param += " -profile:v " + state.Options.Profile;
|
param += " -profile:v " + state.Options.Profile;
|
||||||
|
@ -702,9 +702,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(levelString))
|
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
|
// 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) ||
|
if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (levelString)
|
switch (levelString)
|
||||||
{
|
{
|
||||||
|
@ -740,16 +742,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase))
|
else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param += " -level " + levelString;
|
param += " -level " + levelString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(videoCodec, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
!string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!string.Equals(videoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
!string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
param = "-pix_fmt yuv420p " + param;
|
param = "-pix_fmt yuv420p " + param;
|
||||||
}
|
}
|
||||||
|
@ -757,6 +759,25 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
return param;
|
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)
|
protected string GetVideoBitrateParam(EncodingJob state, string videoCodec)
|
||||||
{
|
{
|
||||||
var bitrate = state.OutputVideoBitrate;
|
var bitrate = state.OutputVideoBitrate;
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace MediaBrowser.Model.LiveTv
|
||||||
public string SeriesRecordingPath { get; set; }
|
public string SeriesRecordingPath { get; set; }
|
||||||
public bool EnableAutoOrganize { get; set; }
|
public bool EnableAutoOrganize { get; set; }
|
||||||
public bool EnableRecordingEncoding { get; set; }
|
public bool EnableRecordingEncoding { get; set; }
|
||||||
|
public string RecordingEncodingFormat { get; set; }
|
||||||
public bool EnableRecordingSubfolders { get; set; }
|
public bool EnableRecordingSubfolders { get; set; }
|
||||||
public bool EnableOriginalAudioWithEncodedRecordings { get; set; }
|
public bool EnableOriginalAudioWithEncodedRecordings { get; set; }
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ namespace MediaBrowser.Model.LiveTv
|
||||||
TunerHosts = new List<TunerHostInfo>();
|
TunerHosts = new List<TunerHostInfo>();
|
||||||
ListingProviders = new List<ListingsProviderInfo>();
|
ListingProviders = new List<ListingsProviderInfo>();
|
||||||
MediaLocationsCreated = new string[] { };
|
MediaLocationsCreated = new string[] { };
|
||||||
|
RecordingEncodingFormat = "mp4";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,19 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
return GetChannelFeaturesDto(channel, channelProvider, channelProvider.GetChannelFeatures());
|
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,
|
public ChannelFeatures GetChannelFeaturesDto(Channel channel,
|
||||||
IChannel provider,
|
IChannel provider,
|
||||||
InternalChannelFeatures features)
|
InternalChannelFeatures features)
|
||||||
|
@ -1450,6 +1463,24 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
return result;
|
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)
|
private IEnumerable<BaseItem> ApplyFilters(IEnumerable<BaseItem> items, IEnumerable<ItemFilter> filters, User user)
|
||||||
{
|
{
|
||||||
foreach (var filter in filters.OrderByDescending(f => (int)f))
|
foreach (var filter in filters.OrderByDescending(f => (int)f))
|
||||||
|
|
|
@ -401,7 +401,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
var locationType = item.LocationType;
|
var locationType = item.LocationType;
|
||||||
|
|
||||||
var children = item.IsFolder
|
var children = item.IsFolder
|
||||||
? ((Folder)item).GetRecursiveChildren().ToList()
|
? ((Folder)item).GetRecursiveChildren(false).ToList()
|
||||||
: new List<BaseItem>();
|
: new List<BaseItem>();
|
||||||
|
|
||||||
foreach (var metadataPath in GetMetadataPaths(item, children))
|
foreach (var metadataPath in GetMetadataPaths(item, children))
|
||||||
|
|
|
@ -46,9 +46,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
||||||
_httpClient = httpClient;
|
_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)
|
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)
|
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)
|
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 mediaStreams = mediaSource.MediaStreams ?? new List<MediaStream>();
|
||||||
var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty;
|
var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty;
|
||||||
|
|
||||||
if (copyAudio.Contains(inputAudioCodec, StringComparer.OrdinalIgnoreCase))
|
// do not copy aac because many players have difficulty with aac_latm
|
||||||
{
|
|
||||||
return "-codec:a:0 copy";
|
|
||||||
}
|
|
||||||
if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase))
|
if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return "-codec:a:0 copy";
|
return "-codec:a:0 copy";
|
||||||
|
|
|
@ -785,9 +785,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
|
||||||
get { return "Schedules Direct"; }
|
get { return "Schedules Direct"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string TypeName = "SchedulesDirect";
|
||||||
public string Type
|
public string Type
|
||||||
{
|
{
|
||||||
get { return "SchedulesDirect"; }
|
get { return TypeName; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
|
private async Task<bool> HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken)
|
||||||
|
|
|
@ -35,6 +35,7 @@ using MediaBrowser.Common.Security;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Server.Implementations.LiveTv.Listings;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.LiveTv
|
namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
{
|
{
|
||||||
|
@ -1436,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
{
|
{
|
||||||
if (query.IsMovie.Value)
|
if (query.IsMovie.Value)
|
||||||
{
|
{
|
||||||
includeItemTypes.Add(typeof (Movie).Name);
|
includeItemTypes.Add(typeof(Movie).Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2802,6 +2803,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
||||||
feature = "embytvseriesrecordings";
|
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);
|
return _security.GetRegistrationStatus(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -541,6 +541,11 @@ namespace MediaBrowser.Server.Implementations.Sync
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.SourceType == SourceType.Channel)
|
||||||
|
{
|
||||||
|
return BaseItem.ChannelManager.SupportsSync(item.ChannelId);
|
||||||
|
}
|
||||||
|
|
||||||
return item.LocationType == LocationType.FileSystem || item is Season;
|
return item.LocationType == LocationType.FileSystem || item is Season;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,10 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
|
|
||||||
private void PerformPreInitMigrations()
|
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)
|
foreach (var task in migrations)
|
||||||
{
|
{
|
||||||
|
@ -383,8 +386,7 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
var migrations = new List<IVersionMigration>
|
var migrations = new List<IVersionMigration>
|
||||||
{
|
{
|
||||||
new MovieDbEpisodeProviderMigration(ServerConfigurationManager),
|
new MovieDbEpisodeProviderMigration(ServerConfigurationManager),
|
||||||
new DbMigration(ServerConfigurationManager, TaskManager),
|
new DbMigration(ServerConfigurationManager, TaskManager)
|
||||||
new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var task in migrations)
|
foreach (var task in migrations)
|
||||||
|
|
|
@ -331,7 +331,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
Application.Run();
|
Application.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SplashForm _splash;
|
internal static SplashForm _splash;
|
||||||
private static Thread _splashThread;
|
private static Thread _splashThread;
|
||||||
private static void ShowSplashScreen(Version appVersion, Progress<double> progress, ILogger logger)
|
private static void ShowSplashScreen(Version appVersion, Progress<double> progress, ILogger logger)
|
||||||
{
|
{
|
||||||
|
|
|
@ -212,7 +212,12 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
|
|
||||||
private bool Confirm()
|
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)
|
public bool PortsRequireAuthorization(string applicationPath)
|
||||||
|
@ -242,7 +247,7 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
|
|
||||||
if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1)
|
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();
|
return Confirm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user