Merge branch 'dev' into beta
This commit is contained in:
commit
3386e8f8f7
|
@ -289,17 +289,5 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
return isLiveStream;
|
return isLiveStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CanStreamCopyAudio(StreamState state, List<string> supportedAudioCodecs)
|
|
||||||
{
|
|
||||||
var isLiveStream = IsLiveStream(state);
|
|
||||||
|
|
||||||
if (!isLiveStream)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CanStreamCopyAudio(state, supportedAudioCodecs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -500,18 +500,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsLiveStream(StreamState state)
|
|
||||||
{
|
|
||||||
var isLiveStream = (state.RunTimeTicks ?? 0) == 0;
|
|
||||||
|
|
||||||
if (state.VideoRequest.ForceLiveStream)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isLiveStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
|
private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
@ -830,11 +818,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header -sc_threshold 0";
|
args += " -flags -global_header";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -859,7 +846,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
args += GetGraphicalSubtitleParam(state, codec);
|
args += GetGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header -sc_threshold 0";
|
args += " -flags -global_header";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
{
|
||||||
|
args += " -copyts";
|
||||||
}
|
}
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
|
@ -867,7 +859,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
private bool EnableCopyTs(StreamState state)
|
private bool EnableCopyTs(StreamState state)
|
||||||
{
|
{
|
||||||
return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
//return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
||||||
|
@ -889,24 +882,28 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
||||||
|
|
||||||
//var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
var enableGenericSegmenter = false;
|
||||||
|
|
||||||
//return string.Format("{0} {11} {1}{10} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
if (enableGenericSegmenter)
|
||||||
// inputModifier,
|
{
|
||||||
// GetInputArgument(state),
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
||||||
// threads,
|
|
||||||
// mapArgs,
|
|
||||||
// GetVideoArguments(state),
|
|
||||||
// GetAudioArguments(state),
|
|
||||||
// state.SegmentLength.ToString(UsCulture),
|
|
||||||
// startNumberParam,
|
|
||||||
// outputPath,
|
|
||||||
// outputTsArg,
|
|
||||||
// slowSeekParam,
|
|
||||||
// toTimeParam
|
|
||||||
// ).Trim();
|
|
||||||
|
|
||||||
return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
|
return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
||||||
|
inputModifier,
|
||||||
|
GetInputArgument(state),
|
||||||
|
threads,
|
||||||
|
mapArgs,
|
||||||
|
GetVideoArguments(state),
|
||||||
|
GetAudioArguments(state),
|
||||||
|
state.SegmentLength.ToString(UsCulture),
|
||||||
|
startNumberParam,
|
||||||
|
outputPath,
|
||||||
|
outputTsArg,
|
||||||
|
toTimeParam
|
||||||
|
).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
GetInputArgument(state),
|
GetInputArgument(state),
|
||||||
threads,
|
threads,
|
||||||
|
@ -946,10 +943,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
var isLiveStream = IsLiveStream(state);
|
var isLiveStream = IsLiveStream(state);
|
||||||
|
|
||||||
if (!isLiveStream)
|
//if (!isLiveStream && Request.QueryString["AllowCustomSegmenting"] != "true")
|
||||||
{
|
//{
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
|
|
||||||
return base.CanStreamCopyVideo(state);
|
return base.CanStreamCopyVideo(state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
// if h264_mp4toannexb is ever added, do not use it for live tv
|
// if h264_mp4toannexb is ever added, do not use it for live tv
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
|
|
|
@ -141,7 +141,6 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,19 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public List<string> PlayableStreamFileNames { get; set; }
|
public List<string> PlayableStreamFileNames { get; set; }
|
||||||
|
|
||||||
public int SegmentLength = 3;
|
public int SegmentLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int HlsListSize
|
public int HlsListSize
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -75,7 +75,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
{
|
{
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
|
|
||||||
[XmlAttribute("protocol")]
|
[XmlAttribute("protocol")]
|
||||||
public string Protocol { get; set; }
|
public string Protocol { get; set; }
|
||||||
|
|
||||||
[XmlAttribute("estimateContentLength")]
|
[XmlAttribute("estimateContentLength")]
|
||||||
public bool EstimateContentLength { get; set; }
|
public bool EstimateContentLength { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
||||||
|
|
||||||
if (otherDuplicatePaths.Count > 0)
|
if (otherDuplicatePaths.Count > 0)
|
||||||
{
|
{
|
||||||
var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, otherDuplicatePaths);
|
var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths));
|
||||||
_logger.Info(msg);
|
_logger.Info(msg);
|
||||||
result.Status = FileSortingStatus.SkippedExisting;
|
result.Status = FileSortingStatus.SkippedExisting;
|
||||||
result.StatusMessage = msg;
|
result.StatusMessage = msg;
|
||||||
|
|
|
@ -179,6 +179,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
|
|
||||||
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)
|
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (WebSocketConnecting != null)
|
if (WebSocketConnecting != null)
|
||||||
{
|
{
|
||||||
WebSocketConnecting(this, args);
|
WebSocketConnecting(this, args);
|
||||||
|
@ -187,6 +192,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
|
|
||||||
private void OnWebSocketConnected(WebSocketConnectEventArgs args)
|
private void OnWebSocketConnected(WebSocketConnectEventArgs args)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (WebSocketConnected != null)
|
if (WebSocketConnected != null)
|
||||||
{
|
{
|
||||||
WebSocketConnected(this, args);
|
WebSocketConnected(this, args);
|
||||||
|
@ -331,6 +341,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
|
|
||||||
var httpRes = httpReq.Response;
|
var httpRes = httpReq.Response;
|
||||||
|
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
httpRes.StatusCode = 503;
|
||||||
|
httpRes.Close();
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
var operationName = httpReq.OperationName;
|
var operationName = httpReq.OperationName;
|
||||||
var localPath = url.LocalPath;
|
var localPath = url.LocalPath;
|
||||||
|
|
||||||
|
|
|
@ -224,7 +224,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||||
|
|
||||||
var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
|
var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
//await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false);
|
if (EnableMediaProbing)
|
||||||
|
{
|
||||||
|
await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
return new Tuple<MediaSourceInfo, SemaphoreSlim>(stream, resourcePool);
|
return new Tuple<MediaSourceInfo, SemaphoreSlim>(stream, resourcePool);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -239,6 +243,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||||
throw new LiveTvConflictException();
|
throw new LiveTvConflictException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual bool EnableMediaProbing
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
protected async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
protected async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -268,6 +277,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
||||||
return _semaphoreLocks.GetOrAdd(url, key => new SemaphoreSlim(1, 1));
|
return _semaphoreLocks.GetOrAdd(url, key => new SemaphoreSlim(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await AddMediaInfoInternal(mediaSource, isAudio, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Leave the resource locked. it will be released upstream
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Release the resource if there's some kind of failure.
|
||||||
|
resourcePool.Release();
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
|
private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var originalRuntime = mediaSource.RunTimeTicks;
|
var originalRuntime = mediaSource.RunTimeTicks;
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
||||||
/// <value>The web socket listeners.</value>
|
/// <value>The web socket listeners.</value>
|
||||||
private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
|
private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
|
||||||
|
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ServerManager" /> class.
|
/// Initializes a new instance of the <see cref="ServerManager" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -143,6 +145,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
||||||
/// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param>
|
/// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param>
|
||||||
void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e)
|
void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger)
|
var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger)
|
||||||
{
|
{
|
||||||
OnReceive = ProcessWebSocketMessageReceived,
|
OnReceive = ProcessWebSocketMessageReceived,
|
||||||
|
@ -164,6 +171,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
||||||
/// <param name="result">The result.</param>
|
/// <param name="result">The result.</param>
|
||||||
private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
|
private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//_logger.Debug("Websocket message received: {0}", result.MessageType);
|
//_logger.Debug("Websocket message received: {0}", result.MessageType);
|
||||||
|
|
||||||
var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
|
var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
|
||||||
|
@ -244,6 +256,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
||||||
throw new ArgumentNullException("dataFunction");
|
throw new ArgumentNullException("dataFunction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(GetType().Name);
|
||||||
|
}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList();
|
var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList();
|
||||||
|
@ -301,6 +318,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,9 +555,10 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
private static void ShutdownWindowsApplication()
|
private static void ShutdownWindowsApplication()
|
||||||
{
|
{
|
||||||
_logger.Info("Calling Application.Exit");
|
//_logger.Info("Calling Application.Exit");
|
||||||
Application.Exit();
|
//Application.Exit();
|
||||||
|
|
||||||
|
_logger.Info("Calling Environment.Exit");
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
|
|
||||||
_logger.Info("Calling ApplicationTaskCompletionSource.SetResult");
|
_logger.Info("Calling ApplicationTaskCompletionSource.SetResult");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user