commit
4ea1cd5d12
|
@ -15,6 +15,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommonIO;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace MediaBrowser.Api
|
||||
{
|
||||
|
@ -187,7 +188,8 @@ namespace MediaBrowser.Api
|
|||
CancellationTokenSource = cancellationTokenSource,
|
||||
Id = transcodingJobId,
|
||||
PlaySessionId = playSessionId,
|
||||
LiveStreamId = liveStreamId
|
||||
LiveStreamId = liveStreamId,
|
||||
MediaSource = state.MediaSource
|
||||
};
|
||||
|
||||
_activeTranscodingJobs.Add(job);
|
||||
|
@ -281,6 +283,14 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
}
|
||||
|
||||
public TranscodingJob GetTranscodingJob(string playSessionId)
|
||||
{
|
||||
lock (_activeTranscodingJobs)
|
||||
{
|
||||
return _activeTranscodingJobs.FirstOrDefault(j => string.Equals(j.PlaySessionId, playSessionId, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [transcode begin request].
|
||||
/// </summary>
|
||||
|
@ -656,6 +666,7 @@ namespace MediaBrowser.Api
|
|||
/// Gets or sets the path.
|
||||
/// </summary>
|
||||
/// <value>The path.</value>
|
||||
public MediaSourceInfo MediaSource { get; set; }
|
||||
public string Path { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the type.
|
||||
|
|
|
@ -1847,18 +1847,30 @@ namespace MediaBrowser.Api.Playback
|
|||
var archivable = item as IArchivable;
|
||||
state.IsInputArchive = archivable != null && archivable.IsArchive;
|
||||
|
||||
MediaSourceInfo mediaSource;
|
||||
MediaSourceInfo mediaSource = null;
|
||||
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
||||
{
|
||||
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
|
||||
//TranscodingJob currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
|
||||
// ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
|
||||
// : null;
|
||||
|
||||
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
||||
? mediaSources.First()
|
||||
: mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
|
||||
//if (currentJob != null)
|
||||
//{
|
||||
// mediaSource = currentJob.MediaSource;
|
||||
//}
|
||||
|
||||
if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
||||
if (mediaSource == null)
|
||||
{
|
||||
mediaSource = mediaSources.First();
|
||||
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
|
||||
|
||||
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
||||
? mediaSources.First()
|
||||
: mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
|
||||
|
||||
if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mediaSource = mediaSources.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
throw;
|
||||
}
|
||||
|
||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : 3;
|
||||
var waitForSegments = state.SegmentLength >= 10 ? 2 : (state.SegmentLength > 3 || !isLive ? 3 : 4);
|
||||
await WaitForMinimumSegmentCount(playlist, waitForSegments, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -128,10 +128,9 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var audioBitrate = state.OutputAudioBitrate ?? 0;
|
||||
var videoBitrate = state.OutputVideoBitrate ?? 0;
|
||||
|
||||
var appendBaselineStream = false;
|
||||
var baselineStreamBitrate = 64000;
|
||||
|
||||
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate);
|
||||
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, baselineStreamBitrate);
|
||||
|
||||
job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
|
||||
|
||||
|
@ -161,7 +160,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
}
|
||||
}
|
||||
|
||||
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
|
||||
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, int baselineStreamBitrate)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
|
@ -175,14 +174,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8");
|
||||
builder.AppendLine(playlistUrl);
|
||||
|
||||
// Low bitrate stream
|
||||
if (includeBaselineStream)
|
||||
{
|
||||
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + baselineStreamBitrate.ToString(UsCulture));
|
||||
playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "-low/stream.m3u8");
|
||||
builder.AppendLine(playlistUrl);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
|
|
|
@ -68,8 +68,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
[Api(Description = "Gets an Http live streaming segment file. Internal use only.")]
|
||||
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
||||
{
|
||||
// TODO: Deprecate with new iOS app
|
||||
|
||||
public string PlaylistId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -113,7 +111,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
|
||||
file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file);
|
||||
|
||||
var normalizedPlaylistId = request.PlaylistId.Replace("-low", string.Empty);
|
||||
var normalizedPlaylistId = request.PlaylistId;
|
||||
|
||||
var playlistPath = Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*")
|
||||
.FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
|
|
@ -88,6 +88,10 @@ namespace MediaBrowser.Api.Playback
|
|||
return 10;
|
||||
}
|
||||
|
||||
if (!RunTimeTicks.HasValue)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace MediaBrowser.Api.Subtitles
|
|||
{
|
||||
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
|
||||
|
||||
var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, false).ConfigureAwait(false);
|
||||
var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
|
|
|
@ -60,11 +60,8 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <summary>
|
||||
/// Gets the static media source.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
||||
/// <returns>MediaSourceInfo.</returns>
|
||||
Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
|
||||
Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Opens the media source.
|
||||
|
|
|
@ -827,6 +827,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
public string DeviceId { get; set; }
|
||||
|
||||
public string MediaSourceId { get; set; }
|
||||
public string LiveStreamId { get; set; }
|
||||
|
||||
public BaseItem Item { get; set; }
|
||||
public MediaSourceInfo MediaSource { get; set; }
|
||||
|
@ -910,6 +911,10 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
{
|
||||
request.StartPositionTicks = long.Parse(val, CultureInfo.InvariantCulture);
|
||||
}
|
||||
else if (i == 22)
|
||||
{
|
||||
request.LiveStreamId = val;
|
||||
}
|
||||
}
|
||||
|
||||
request.Item = string.IsNullOrWhiteSpace(request.ItemId)
|
||||
|
@ -920,7 +925,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
|
||||
request.MediaSource = hasMediaSources == null
|
||||
? null
|
||||
: (await mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, false).ConfigureAwait(false));
|
||||
: (await mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, request.LiveStreamId, false, CancellationToken.None).ConfigureAwait(false));
|
||||
|
||||
return request;
|
||||
}
|
||||
|
|
|
@ -221,8 +221,28 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
|
||||
public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(liveStreamId))
|
||||
{
|
||||
return await GetLiveStream(liveStreamId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
//await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//try
|
||||
//{
|
||||
// var stream = _openStreams.Values.FirstOrDefault(i => string.Equals(i.MediaSource.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
// if (stream != null)
|
||||
// {
|
||||
// return stream.MediaSource;
|
||||
// }
|
||||
//}
|
||||
//finally
|
||||
//{
|
||||
// _liveStreamSemaphore.Release();
|
||||
//}
|
||||
|
||||
var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video },
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
|
|
|
@ -763,7 +763,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
throw new ApplicationException("Tuner not found.");
|
||||
}
|
||||
|
||||
private async Task<Tuple<MediaSourceInfo, ITunerHost, SemaphoreSlim>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
|
||||
private async Task<Tuple<MediaSourceInfo, ITunerHost, SemaphoreSlim>> GetChannelStreamInternal(string channelId, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("Streaming Channel " + channelId);
|
||||
|
||||
|
@ -771,7 +771,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
try
|
||||
{
|
||||
var result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||
var result = await hostInstance.GetChannelStream(channelId, null, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new Tuple<MediaSourceInfo, ITunerHost, SemaphoreSlim>(result.Item1, hostInstance, result.Item2);
|
||||
}
|
||||
|
@ -994,7 +994,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
try
|
||||
{
|
||||
var result = await GetChannelStreamInternal(timer.ChannelId, null, CancellationToken.None).ConfigureAwait(false);
|
||||
var result = await GetChannelStreamInternal(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
|
||||
isResourceOpen = true;
|
||||
semaphore = result.Item3;
|
||||
var mediaStreamInfo = result.Item1;
|
||||
|
|
|
@ -223,8 +223,7 @@ 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);
|
||||
|
||||
if (EnableMediaProbing)
|
||||
{
|
||||
|
|
|
@ -319,18 +319,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
videoBitrate = 1000000;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(videoCodec))
|
||||
var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false);
|
||||
var channel = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase));
|
||||
if (channel != null)
|
||||
{
|
||||
var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false);
|
||||
var channel = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase));
|
||||
if (channel != null)
|
||||
if (string.IsNullOrWhiteSpace(videoCodec))
|
||||
{
|
||||
videoCodec = channel.VideoCodec;
|
||||
audioCodec = channel.AudioCodec;
|
||||
|
||||
videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000;
|
||||
audioBitrate = (channel.IsHD ?? true) ? 448000 : 192000;
|
||||
}
|
||||
audioCodec = channel.AudioCodec;
|
||||
|
||||
if (!videoBitrate.HasValue)
|
||||
{
|
||||
videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000;
|
||||
}
|
||||
audioBitrate = (channel.IsHD ?? true) ? 448000 : 192000;
|
||||
}
|
||||
|
||||
// normalize
|
||||
|
@ -380,7 +383,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
BitRate = audioBitrate
|
||||
}
|
||||
},
|
||||
RequiresOpening = false,
|
||||
RequiresOpening = true,
|
||||
RequiresClosing = false,
|
||||
BufferMs = 0,
|
||||
Container = "ts",
|
||||
|
|
|
@ -307,9 +307,9 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
}
|
||||
}
|
||||
|
||||
private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
|
||||
private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, string liveStreamId)
|
||||
{
|
||||
return _mediaSourceManager.GetMediaSource(item, mediaSourceId, false);
|
||||
return _mediaSourceManager.GetMediaSource(item, mediaSourceId, liveStreamId, false, CancellationToken.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -337,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
var hasMediaSources = libraryItem as IHasMediaSources;
|
||||
if (hasMediaSources != null)
|
||||
{
|
||||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId).ConfigureAwait(false);
|
||||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
|
||||
|
||||
if (mediaSource != null)
|
||||
{
|
||||
|
@ -792,7 +792,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
var hasMediaSources = libraryItem as IHasMediaSources;
|
||||
if (hasMediaSources != null)
|
||||
{
|
||||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId).ConfigureAwait(false);
|
||||
mediaSource = await GetMediaSource(hasMediaSources, info.MediaSourceId, info.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource);
|
||||
|
|
Loading…
Reference in New Issue
Block a user