Merge branch 'dev' into beta

This commit is contained in:
Luke Pulverenti 2016-04-22 12:34:36 -04:00
commit 3386e8f8f7
12 changed files with 116 additions and 57 deletions

View File

@ -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);
}
} }
} }

View File

@ -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);
} }

View File

@ -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;

View File

@ -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";
} }

View File

@ -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

View File

@ -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";
} }

View File

@ -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; }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
} }

View File

@ -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");