use server to build initial stream url's
This commit is contained in:
parent
46c9210749
commit
348b8c4414
|
@ -1,8 +1,11 @@
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Session;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -13,7 +16,7 @@ using System.Threading.Tasks;
|
|||
namespace MediaBrowser.Api.Playback
|
||||
{
|
||||
[Route("/Items/{Id}/MediaInfo", "GET", Summary = "Gets live playback media info for an item")]
|
||||
public class GetLiveMediaInfo : IReturn<LiveMediaInfoResult>
|
||||
public class GetLiveMediaInfo : IReturn<PlaybackInfoResponse>
|
||||
{
|
||||
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
public string Id { get; set; }
|
||||
|
@ -23,7 +26,17 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
|
||||
[Route("/Items/{Id}/PlaybackInfo", "GET", Summary = "Gets live playback media info for an item")]
|
||||
public class GetPlaybackInfo : IReturn<LiveMediaInfoResult>
|
||||
public class GetPlaybackInfo : IReturn<PlaybackInfoResponse>
|
||||
{
|
||||
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}/PlaybackInfo", "POST", Summary = "Gets live playback media info for an item")]
|
||||
public class GetPostedPlaybackInfo : PlaybackInfoRequest, IReturn<PlaybackInfoResponse>
|
||||
{
|
||||
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
public string Id { get; set; }
|
||||
|
@ -36,26 +49,55 @@ namespace MediaBrowser.Api.Playback
|
|||
public class MediaInfoService : BaseApiService
|
||||
{
|
||||
private readonly IMediaSourceManager _mediaSourceManager;
|
||||
private readonly IDeviceManager _deviceManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public MediaInfoService(IMediaSourceManager mediaSourceManager)
|
||||
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager)
|
||||
{
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
_deviceManager = deviceManager;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
public Task<object> Get(GetPlaybackInfo request)
|
||||
public async Task<object> Get(GetPlaybackInfo request)
|
||||
{
|
||||
return GetPlaybackInfo(request.Id, request.UserId);
|
||||
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
public Task<object> Get(GetLiveMediaInfo request)
|
||||
public async Task<object> Get(GetLiveMediaInfo request)
|
||||
{
|
||||
return GetPlaybackInfo(request.Id, request.UserId);
|
||||
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
|
||||
return ToOptimizedResult(result);
|
||||
}
|
||||
|
||||
private async Task<object> GetPlaybackInfo(string id, string userId)
|
||||
public async Task<object> Post(GetPostedPlaybackInfo request)
|
||||
{
|
||||
var info = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
|
||||
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||
|
||||
var profile = request.DeviceProfile;
|
||||
//if (profile == null)
|
||||
//{
|
||||
// var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
|
||||
// if (caps != null)
|
||||
// {
|
||||
// profile = caps.DeviceProfile;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
SetDeviceSpecificData(request.Id, info, profile, authInfo, null);
|
||||
}
|
||||
|
||||
return ToOptimizedResult(info);
|
||||
}
|
||||
|
||||
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId)
|
||||
{
|
||||
IEnumerable<MediaSourceInfo> mediaSources;
|
||||
var result = new LiveMediaInfoResult();
|
||||
var result = new PlaybackInfoResponse();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -68,9 +110,89 @@ namespace MediaBrowser.Api.Playback
|
|||
}
|
||||
|
||||
result.MediaSources = mediaSources.ToList();
|
||||
result.StreamId = Guid.NewGuid().ToString("N");
|
||||
|
||||
return ToOptimizedResult(result);
|
||||
if (result.MediaSources.Count == 0)
|
||||
{
|
||||
if (!result.ErrorCode.HasValue)
|
||||
{
|
||||
result.ErrorCode = PlaybackErrorCode.NoCompatibleStream;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.StreamId = Guid.NewGuid().ToString("N");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SetDeviceSpecificData(string itemId, PlaybackInfoResponse result, DeviceProfile profile, AuthorizationInfo auth, int? maxBitrate)
|
||||
{
|
||||
var streamBuilder = new StreamBuilder();
|
||||
|
||||
var item = _libraryManager.GetItemById(itemId);
|
||||
|
||||
foreach (var mediaSource in result.MediaSources)
|
||||
{
|
||||
var options = new VideoOptions
|
||||
{
|
||||
MediaSources = new List<MediaSourceInfo> { mediaSource },
|
||||
Context = EncodingContext.Streaming,
|
||||
DeviceId = auth.DeviceId,
|
||||
ItemId = item.Id.ToString("N"),
|
||||
Profile = profile,
|
||||
MaxBitrate = maxBitrate
|
||||
};
|
||||
|
||||
if (mediaSource.SupportsDirectPlay)
|
||||
{
|
||||
var supportsDirectStream = mediaSource.SupportsDirectStream;
|
||||
|
||||
// Dummy this up to fool StreamBuilder
|
||||
mediaSource.SupportsDirectStream = true;
|
||||
|
||||
// The MediaSource supports direct stream, now test to see if the client supports it
|
||||
var streamInfo = item is Video ?
|
||||
streamBuilder.BuildVideoItem(options) :
|
||||
streamBuilder.BuildAudioItem(options);
|
||||
|
||||
if (streamInfo == null || !streamInfo.IsDirectStream)
|
||||
{
|
||||
mediaSource.SupportsDirectPlay = false;
|
||||
}
|
||||
|
||||
// Set this back to what it was
|
||||
mediaSource.SupportsDirectStream = supportsDirectStream;
|
||||
}
|
||||
|
||||
if (mediaSource.SupportsDirectStream)
|
||||
{
|
||||
// The MediaSource supports direct stream, now test to see if the client supports it
|
||||
var streamInfo = item is Video ?
|
||||
streamBuilder.BuildVideoItem(options) :
|
||||
streamBuilder.BuildAudioItem(options);
|
||||
|
||||
if (streamInfo == null || !streamInfo.IsDirectStream)
|
||||
{
|
||||
mediaSource.SupportsDirectStream = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaSource.SupportsTranscoding)
|
||||
{
|
||||
// The MediaSource supports direct stream, now test to see if the client supports it
|
||||
var streamInfo = item is Video ?
|
||||
streamBuilder.BuildVideoItem(options) :
|
||||
streamBuilder.BuildAudioItem(options);
|
||||
|
||||
if (streamInfo != null && streamInfo.PlayMethod == PlayMethod.Transcode)
|
||||
{
|
||||
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).Substring(1);
|
||||
mediaSource.TranscodingContainer = streamInfo.Container;
|
||||
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ namespace MediaBrowser.Controller.Channels
|
|||
RunTimeTicks = RunTimeTicks,
|
||||
Name = id,
|
||||
Id = id,
|
||||
ReadAtNativeFramerate = ReadAtNativeFramerate
|
||||
ReadAtNativeFramerate = ReadAtNativeFramerate,
|
||||
SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http
|
||||
};
|
||||
|
||||
var bitrate = (AudioBitrate ?? 0) + (VideoBitrate ?? 0);
|
||||
|
|
|
@ -501,7 +501,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
|
||||
Timestamp = i.Timestamp,
|
||||
Type = type,
|
||||
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList()
|
||||
PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(),
|
||||
SupportsDirectStream = i.VideoType == VideoType.VideoFile
|
||||
};
|
||||
|
||||
if (i.IsShortcut)
|
||||
|
|
|
@ -800,12 +800,15 @@
|
|||
<Compile Include="..\MediaBrowser.Model\MediaInfo\IBlurayExaminer.cs">
|
||||
<Link>MediaInfo\IBlurayExaminer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\LiveMediaInfoResult.cs">
|
||||
<Link>MediaInfo\LiveMediaInfoResult.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\MediaProtocol.cs">
|
||||
<Link>MediaInfo\MediaProtocol.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\PlaybackInfoRequest.cs">
|
||||
<Link>MediaInfo\PlaybackInfoRequest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\PlaybackInfoResponse.cs">
|
||||
<Link>MediaInfo\PlaybackInfoResponse.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\SubtitleFormat.cs">
|
||||
<Link>MediaInfo\SubtitleFormat.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -756,12 +756,15 @@
|
|||
<Compile Include="..\MediaBrowser.Model\MediaInfo\IBlurayExaminer.cs">
|
||||
<Link>MediaInfo\IBlurayExaminer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\LiveMediaInfoResult.cs">
|
||||
<Link>MediaInfo\LiveMediaInfoResult.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\MediaProtocol.cs">
|
||||
<Link>MediaInfo\MediaProtocol.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\PlaybackInfoRequest.cs">
|
||||
<Link>MediaInfo\PlaybackInfoRequest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\PlaybackInfoResponse.cs">
|
||||
<Link>MediaInfo\PlaybackInfoResponse.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MediaBrowser.Model\MediaInfo\SubtitleFormat.cs">
|
||||
<Link>MediaInfo\SubtitleFormat.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -251,7 +251,7 @@ namespace MediaBrowser.Model.ApiClient
|
|||
/// <param name="itemId">The item identifier.</param>
|
||||
/// <param name="userId">The user identifier.</param>
|
||||
/// <returns>Task<LiveMediaInfoResult>.</returns>
|
||||
Task<LiveMediaInfoResult> GetPlaybackInfo(string itemId, string userId);
|
||||
Task<PlaybackInfoResponse> GetPlaybackInfo(string itemId, string userId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the users async.
|
||||
|
|
|
@ -118,9 +118,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
return stream;
|
||||
}
|
||||
|
||||
PlaybackException error = new PlaybackException();
|
||||
error.ErrorCode = PlaybackErrorCode.NoCompatibleStream;
|
||||
throw error;
|
||||
return null;
|
||||
}
|
||||
|
||||
private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
|
||||
|
@ -221,7 +219,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
|
||||
playlistItem.Container = transcodingProfile.Container;
|
||||
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
|
||||
playlistItem.Protocol = transcodingProfile.Protocol;
|
||||
playlistItem.SubProtocol = transcodingProfile.Protocol;
|
||||
|
||||
List<CodecProfile> audioCodecProfiles = new List<CodecProfile>();
|
||||
foreach (CodecProfile i in options.Profile.CodecProfiles)
|
||||
|
@ -374,7 +372,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
|
||||
playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',')[0];
|
||||
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
|
||||
playlistItem.Protocol = transcodingProfile.Protocol;
|
||||
playlistItem.SubProtocol = transcodingProfile.Protocol;
|
||||
playlistItem.AudioStreamIndex = audioStreamIndex;
|
||||
|
||||
List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>();
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
|
||||
public string Container { get; set; }
|
||||
|
||||
public string Protocol { get; set; }
|
||||
public string SubProtocol { get; set; }
|
||||
|
||||
public long StartPositionTicks { get; set; }
|
||||
|
||||
|
@ -69,7 +69,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; }
|
||||
public string SubtitleFormat { get; set; }
|
||||
|
||||
public LiveMediaInfoResult PlaybackInfo { get; set; }
|
||||
public PlaybackInfoResponse PlaybackInfo { get; set; }
|
||||
|
||||
public string MediaSourceId
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
|
||||
}
|
||||
|
||||
if (StringHelper.EqualsIgnoreCase(Protocol, "hls"))
|
||||
if (StringHelper.EqualsIgnoreCase(SubProtocol, "hls"))
|
||||
{
|
||||
return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, dlnaCommand);
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ namespace MediaBrowser.Model.Dlna
|
|||
List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
|
||||
|
||||
// HLS will preserve timestamps so we can just grab the full subtitle stream
|
||||
long startPositionTicks = StringHelper.EqualsIgnoreCase(Protocol, "hls")
|
||||
long startPositionTicks = StringHelper.EqualsIgnoreCase(SubProtocol, "hls")
|
||||
? 0
|
||||
: StartPositionTicks;
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace MediaBrowser.Model.Dto
|
|||
public bool ReadAtNativeFramerate { get; set; }
|
||||
public bool SupportsTranscoding { get; set; }
|
||||
public bool SupportsDirectStream { get; set; }
|
||||
public bool SupportsDirectPlay { get; set; }
|
||||
|
||||
public VideoType? VideoType { get; set; }
|
||||
|
||||
|
@ -39,7 +40,11 @@ namespace MediaBrowser.Model.Dto
|
|||
public int? Bitrate { get; set; }
|
||||
|
||||
public TransportStreamTimestamp? Timestamp { get; set; }
|
||||
public Dictionary<string, string> RequiredHttpHeaders { get; set; }
|
||||
public Dictionary<string, string> RequiredHttpHeaders { get; set; }
|
||||
|
||||
public string TranscodingUrl { get; set; }
|
||||
public string TranscodingSubProtocol { get; set; }
|
||||
public string TranscodingContainer { get; set; }
|
||||
|
||||
public MediaSourceInfo()
|
||||
{
|
||||
|
@ -49,6 +54,7 @@ namespace MediaBrowser.Model.Dto
|
|||
PlayableStreamFileNames = new List<string>();
|
||||
SupportsTranscoding = true;
|
||||
SupportsDirectStream = true;
|
||||
SupportsDirectPlay = true;
|
||||
}
|
||||
|
||||
public int? DefaultAudioStreamIndex { get; set; }
|
||||
|
|
|
@ -140,7 +140,8 @@
|
|||
<Compile Include="Dto\MetadataEditorInfo.cs" />
|
||||
<Compile Include="Dto\NameIdPair.cs" />
|
||||
<Compile Include="Dto\NameValuePair.cs" />
|
||||
<Compile Include="MediaInfo\LiveMediaInfoResult.cs" />
|
||||
<Compile Include="MediaInfo\PlaybackInfoRequest.cs" />
|
||||
<Compile Include="MediaInfo\PlaybackInfoResponse.cs" />
|
||||
<Compile Include="Dto\MediaSourceType.cs" />
|
||||
<Compile Include="Configuration\DynamicDayOfWeek.cs" />
|
||||
<Compile Include="Entities\ExtraType.cs" />
|
||||
|
|
9
MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs
Normal file
9
MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using MediaBrowser.Model.Dlna;
|
||||
|
||||
namespace MediaBrowser.Model.MediaInfo
|
||||
{
|
||||
public class PlaybackInfoRequest
|
||||
{
|
||||
public DeviceProfile DeviceProfile { get; set; }
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||
|
||||
namespace MediaBrowser.Model.MediaInfo
|
||||
{
|
||||
public class LiveMediaInfoResult
|
||||
public class PlaybackInfoResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the media sources.
|
||||
|
@ -24,7 +24,7 @@ namespace MediaBrowser.Model.MediaInfo
|
|||
/// <value>The error code.</value>
|
||||
public PlaybackErrorCode? ErrorCode { get; set; }
|
||||
|
||||
public LiveMediaInfoResult()
|
||||
public PlaybackInfoResponse()
|
||||
{
|
||||
MediaSources = new List<MediaSourceInfo>();
|
||||
}
|
Loading…
Reference in New Issue
Block a user