Merge pull request #2528 from MediaBrowser/dev
update hls to support mpeg2video
This commit is contained in:
commit
8b20e507c5
|
@ -208,7 +208,7 @@ namespace Emby.Dlna.Didl
|
||||||
var targetHeight = streamInfo.TargetHeight;
|
var targetHeight = streamInfo.TargetHeight;
|
||||||
|
|
||||||
var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
|
var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
|
||||||
streamInfo.VideoCodec,
|
streamInfo.TargetVideoCodec,
|
||||||
streamInfo.TargetAudioCodec,
|
streamInfo.TargetAudioCodec,
|
||||||
targetWidth,
|
targetWidth,
|
||||||
targetHeight,
|
targetHeight,
|
||||||
|
@ -352,7 +352,7 @@ namespace Emby.Dlna.Didl
|
||||||
|
|
||||||
var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container,
|
var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container,
|
||||||
streamInfo.TargetAudioCodec,
|
streamInfo.TargetAudioCodec,
|
||||||
streamInfo.VideoCodec,
|
streamInfo.TargetVideoCodec,
|
||||||
streamInfo.TargetAudioBitrate,
|
streamInfo.TargetAudioBitrate,
|
||||||
targetWidth,
|
targetWidth,
|
||||||
targetHeight,
|
targetHeight,
|
||||||
|
|
|
@ -542,7 +542,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
var list = new ContentFeatureBuilder(profile)
|
var list = new ContentFeatureBuilder(profile)
|
||||||
.BuildVideoHeader(streamInfo.Container,
|
.BuildVideoHeader(streamInfo.Container,
|
||||||
streamInfo.VideoCodec,
|
streamInfo.TargetVideoCodec,
|
||||||
streamInfo.TargetAudioCodec,
|
streamInfo.TargetAudioCodec,
|
||||||
streamInfo.TargetWidth,
|
streamInfo.TargetWidth,
|
||||||
streamInfo.TargetHeight,
|
streamInfo.TargetHeight,
|
||||||
|
|
|
@ -2545,14 +2545,24 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
||||||
|
|
||||||
private const int TunerDiscoveryDurationMs = 3000;
|
private const int TunerDiscoveryDurationMs = 3000;
|
||||||
|
|
||||||
public async Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken)
|
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var list = new List<TunerHostInfo>();
|
var list = new List<TunerHostInfo>();
|
||||||
|
|
||||||
|
var configuredDeviceIds = GetConfiguration().TunerHosts
|
||||||
|
.Where(i => !string.IsNullOrWhiteSpace(i.DeviceId))
|
||||||
|
.Select(i => i.DeviceId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var host in _liveTvManager.TunerHosts)
|
foreach (var host in _liveTvManager.TunerHosts)
|
||||||
{
|
{
|
||||||
var discoveredDevices = await DiscoverDevices(host, TunerDiscoveryDurationMs, cancellationToken).ConfigureAwait(false);
|
var discoveredDevices = await DiscoverDevices(host, TunerDiscoveryDurationMs, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (newDevicesOnly)
|
||||||
|
{
|
||||||
|
discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparer.OrdinalIgnoreCase))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
list.AddRange(discoveredDevices);
|
list.AddRange(discoveredDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,9 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken)
|
public Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return EmbyTV.EmbyTV.Current.DiscoverTuners(cancellationToken);
|
return EmbyTV.EmbyTV.Current.DiscoverTuners(newDevicesOnly, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
void service_DataSourceChanged(object sender, EventArgs e)
|
void service_DataSourceChanged(object sender, EventArgs e)
|
||||||
|
|
|
@ -684,7 +684,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class DiscoverTuners : IReturn<List<TunerHostInfo>>
|
public class DiscoverTuners : IReturn<List<TunerHostInfo>>
|
||||||
{
|
{
|
||||||
|
public bool NewDevicesOnly { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LiveTvService : BaseApiService
|
public class LiveTvService : BaseApiService
|
||||||
|
@ -739,7 +739,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
public async Task<object> Get(DiscoverTuners request)
|
public async Task<object> Get(DiscoverTuners request)
|
||||||
{
|
{
|
||||||
var result = await _liveTvManager.DiscoverTuners(CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.DiscoverTuners(request.NewDevicesOnly, CancellationToken.None).ConfigureAwait(false);
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -697,6 +697,20 @@ namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
request.SubtitleCodec = val;
|
request.SubtitleCodec = val;
|
||||||
}
|
}
|
||||||
|
else if (i == 31)
|
||||||
|
{
|
||||||
|
if (videoRequest != null)
|
||||||
|
{
|
||||||
|
videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i == 32)
|
||||||
|
{
|
||||||
|
if (videoRequest != null)
|
||||||
|
{
|
||||||
|
videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,16 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the segment file extension.
|
/// Gets the segment file extension.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
protected string GetSegmentFileExtension(StreamRequest request)
|
||||||
/// <returns>System.String.</returns>
|
{
|
||||||
protected abstract string GetSegmentFileExtension(StreamState state);
|
var segmentContainer = request.SegmentContainer;
|
||||||
|
if (!string.IsNullOrWhiteSpace(segmentContainer))
|
||||||
|
{
|
||||||
|
return "." + segmentContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ".ts";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the transcoding job.
|
/// Gets the type of the transcoding job.
|
||||||
|
@ -261,11 +268,17 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var useGenericSegmenter = false;
|
var useGenericSegmenter = false;
|
||||||
if (useGenericSegmenter)
|
if (useGenericSegmenter)
|
||||||
{
|
{
|
||||||
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
||||||
|
|
||||||
var timeDeltaParam = String.Empty;
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
var segmentFormat = GetSegmentFileExtension(state.Request).TrimStart('.');
|
||||||
|
if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
segmentFormat = "mpegts";
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
EncodingHelper.GetInputArgument(state, encodingOptions),
|
EncodingHelper.GetInputArgument(state, encodingOptions),
|
||||||
threads,
|
threads,
|
||||||
|
@ -276,7 +289,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
startNumberParam,
|
startNumberParam,
|
||||||
outputPath,
|
outputPath,
|
||||||
outputTsArg,
|
outputTsArg,
|
||||||
timeDeltaParam
|
timeDeltaParam,
|
||||||
|
segmentFormat
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +300,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero {6} -hls_time {7} -individual_header_trailer 0 -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
|
var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero {6} -hls_time {7} -individual_header_trailer 0 -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
|
||||||
itsOffset,
|
itsOffset,
|
||||||
inputModifier,
|
inputModifier,
|
||||||
EncodingHelper.GetInputArgument(state, encodingOptions),
|
EncodingHelper.GetInputArgument(state, encodingOptions),
|
||||||
threads,
|
threads,
|
||||||
EncodingHelper.GetMapArgs(state),
|
EncodingHelper.GetMapArgs(state),
|
||||||
GetVideoArguments(state),
|
GetVideoArguments(state),
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Videos/{Id}/hls1/{PlaylistId}/{SegmentId}.ts", "GET")]
|
[Route("/Videos/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
|
||||||
public class GetHlsVideoSegment : VideoStreamRequest
|
public class GetHlsVideoSegment : VideoStreamRequest
|
||||||
{
|
{
|
||||||
public string PlaylistId { get; set; }
|
public string PlaylistId { get; set; }
|
||||||
|
@ -77,8 +77,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
public string SegmentId { get; set; }
|
public string SegmentId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.aac", "GET")]
|
[Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
|
||||||
[Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.ts", "GET")]
|
|
||||||
public class GetHlsAudioSegment : StreamRequest
|
public class GetHlsAudioSegment : StreamRequest
|
||||||
{
|
{
|
||||||
public string PlaylistId { get; set; }
|
public string PlaylistId { get; set; }
|
||||||
|
@ -158,7 +157,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex);
|
var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex);
|
||||||
|
|
||||||
var segmentExtension = GetSegmentFileExtension(state);
|
var segmentExtension = GetSegmentFileExtension(state.Request);
|
||||||
|
|
||||||
TranscodingJob job = null;
|
TranscodingJob job = null;
|
||||||
|
|
||||||
|
@ -420,7 +419,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var filename = Path.GetFileNameWithoutExtension(playlist);
|
var filename = Path.GetFileNameWithoutExtension(playlist);
|
||||||
|
|
||||||
return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state));
|
return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state.Request));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<object> GetSegmentResult(StreamState state, string playlistPath,
|
private async Task<object> GetSegmentResult(StreamState state, string playlistPath,
|
||||||
|
@ -740,7 +739,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
name,
|
name,
|
||||||
index.ToString(UsCulture),
|
index.ToString(UsCulture),
|
||||||
GetSegmentFileExtension(isOutputVideo),
|
GetSegmentFileExtension(request),
|
||||||
queryString));
|
queryString));
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
@ -848,7 +847,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||||
|
|
||||||
args += " " + EncodingHelper.GetVideoQualityParam(state, EncodingHelper.GetH264Encoder(state, encodingOptions), encodingOptions, GetDefaultH264Preset()) + keyFrameArg;
|
args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg;
|
||||||
|
|
||||||
//args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
|
//args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
|
||||||
|
|
||||||
|
@ -897,7 +896,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
|
|
||||||
if (useGenericSegmenter)
|
if (useGenericSegmenter)
|
||||||
{
|
{
|
||||||
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
|
||||||
|
|
||||||
var timeDeltaParam = String.Empty;
|
var timeDeltaParam = String.Empty;
|
||||||
|
|
||||||
|
@ -907,7 +906,13 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
timeDeltaParam = string.Format("-segment_time_delta -{0}", startTime);
|
timeDeltaParam = string.Format("-segment_time_delta -{0}", startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
var segmentFormat = GetSegmentFileExtension(state.Request).TrimStart('.');
|
||||||
|
if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
segmentFormat = "mpegts";
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
EncodingHelper.GetInputArgument(state, encodingOptions),
|
EncodingHelper.GetInputArgument(state, encodingOptions),
|
||||||
threads,
|
threads,
|
||||||
|
@ -918,7 +923,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
startNumberParam,
|
startNumberParam,
|
||||||
outputPath,
|
outputPath,
|
||||||
outputTsArg,
|
outputTsArg,
|
||||||
timeDeltaParam
|
timeDeltaParam,
|
||||||
|
segmentFormat
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,20 +941,5 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
outputPath
|
outputPath
|
||||||
).Trim();
|
).Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the segment file extension.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="state">The state.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string GetSegmentFileExtension(StreamState state)
|
|
||||||
{
|
|
||||||
return GetSegmentFileExtension(state.IsOutputVideo);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string GetSegmentFileExtension(bool isOutputVideo)
|
|
||||||
{
|
|
||||||
return isOutputVideo ? ".ts" : ".ts";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -63,7 +63,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class GetHlsVideoSegment
|
/// Class GetHlsVideoSegment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.ts", "GET")]
|
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
|
||||||
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
|
||||||
{
|
{
|
||||||
public string PlaylistId { get; set; }
|
public string PlaylistId { get; set; }
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
||||||
|
|
||||||
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
|
||||||
args += " " + EncodingHelper.GetVideoQualityParam(state, EncodingHelper.GetH264Encoder(state, encodingOptions), encodingOptions, GetDefaultH264Preset()) + keyFrameArg;
|
args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg;
|
||||||
|
|
||||||
// Add resolution params, if specified
|
// Add resolution params, if specified
|
||||||
if (!hasGraphicalSubs)
|
if (!hasGraphicalSubs)
|
||||||
|
@ -118,16 +118,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the segment file extension.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="state">The state.</param>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string GetSegmentFileExtension(StreamState state)
|
|
||||||
{
|
|
||||||
return ".ts";
|
|
||||||
}
|
|
||||||
|
|
||||||
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
|
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
public string PlaySessionId { get; set; }
|
public string PlaySessionId { get; set; }
|
||||||
public string LiveStreamId { get; set; }
|
public string LiveStreamId { get; set; }
|
||||||
public string Tag { get; set; }
|
public string Tag { get; set; }
|
||||||
|
public string SegmentContainer { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VideoStreamRequest : StreamRequest
|
public class VideoStreamRequest : StreamRequest
|
||||||
|
|
|
@ -382,7 +382,7 @@ namespace MediaBrowser.Controller.LiveTv
|
||||||
List<IListingsProvider> ListingProviders { get; }
|
List<IListingsProvider> ListingProviders { get; }
|
||||||
|
|
||||||
List<NameIdPair> GetTunerHostTypes();
|
List<NameIdPair> GetTunerHostTypes();
|
||||||
Task<List<TunerHostInfo>> DiscoverTuners(CancellationToken cancellationToken);
|
Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken);
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
|
||||||
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
|
||||||
|
|
|
@ -733,12 +733,18 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
|
|
||||||
if (videoStream.IsInterlaced)
|
if (videoStream.IsInterlaced)
|
||||||
{
|
{
|
||||||
return false;
|
if (request.DeInterlace)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoStream.IsAnamorphic ?? false)
|
if (videoStream.IsAnamorphic ?? false)
|
||||||
{
|
{
|
||||||
return false;
|
if (request.RequireNonAnamorphic)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't stream copy if we're burning in subtitles
|
// Can't stream copy if we're burning in subtitles
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
AudioBitRate = info.AudioBitrate;
|
AudioBitRate = info.AudioBitrate;
|
||||||
AudioSampleRate = info.TargetAudioSampleRate;
|
AudioSampleRate = info.TargetAudioSampleRate;
|
||||||
DeviceProfile = deviceProfile;
|
DeviceProfile = deviceProfile;
|
||||||
VideoCodec = info.VideoCodec;
|
VideoCodec = info.TargetVideoCodec;
|
||||||
VideoBitRate = info.VideoBitrate;
|
VideoBitRate = info.VideoBitrate;
|
||||||
AudioStreamIndex = info.AudioStreamIndex;
|
AudioStreamIndex = info.AudioStreamIndex;
|
||||||
MaxRefFrames = info.MaxRefFrames;
|
MaxRefFrames = info.MaxRefFrames;
|
||||||
|
@ -185,6 +185,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|
||||||
[ApiMember(Name = "MaxVideoBitDepth", Description = "Optional.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "MaxVideoBitDepth", Description = "Optional.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
public int? MaxVideoBitDepth { get; set; }
|
public int? MaxVideoBitDepth { get; set; }
|
||||||
public bool RequireAvc { get; set; }
|
public bool RequireAvc { get; set; }
|
||||||
|
public bool DeInterlace { get; set; }
|
||||||
|
public bool RequireNonAnamorphic { get; set; }
|
||||||
public int? TranscodingMaxAudioChannels { get; set; }
|
public int? TranscodingMaxAudioChannels { get; set; }
|
||||||
public int? CpuCoreLimit { get; set; }
|
public int? CpuCoreLimit { get; set; }
|
||||||
public string OutputContainer { get; set; }
|
public string OutputContainer { get; set; }
|
||||||
|
|
|
@ -734,16 +734,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var charsetFromLanguage = string.IsNullOrWhiteSpace(language)
|
|
||||||
? null
|
|
||||||
: GetSubtitleFileCharacterSetFromLanguage(language);
|
|
||||||
|
|
||||||
// This assumption should only be made for external subtitles
|
|
||||||
if (!string.IsNullOrWhiteSpace(charsetFromLanguage) && !string.Equals(charsetFromLanguage, "windows-1252", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return charsetFromLanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
var charset = await DetectCharset(path, language, protocol, cancellationToken).ConfigureAwait(false);
|
var charset = await DetectCharset(path, language, protocol, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(charset))
|
if (!string.IsNullOrWhiteSpace(charset))
|
||||||
|
@ -756,7 +746,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
return charset;
|
return charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return charsetFromLanguage;
|
if (!string.IsNullOrWhiteSpace(language))
|
||||||
|
{
|
||||||
|
return GetSubtitleFileCharacterSetFromLanguage(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetSubtitleFileCharacterSetFromLanguage(string language)
|
public string GetSubtitleFileCharacterSetFromLanguage(string language)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
NumVideoStreams = 17,
|
NumVideoStreams = 17,
|
||||||
IsSecondaryAudio = 18,
|
IsSecondaryAudio = 18,
|
||||||
VideoCodecTag = 19,
|
VideoCodecTag = 19,
|
||||||
IsAvc = 20
|
IsAvc = 20,
|
||||||
|
IsInterlaced = 21
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -231,6 +231,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(',');
|
playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
playlistItem.SubProtocol = transcodingProfile.Protocol;
|
playlistItem.SubProtocol = transcodingProfile.Protocol;
|
||||||
|
|
||||||
List<CodecProfile> audioCodecProfiles = new List<CodecProfile>();
|
List<CodecProfile> audioCodecProfiles = new List<CodecProfile>();
|
||||||
|
@ -479,7 +480,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
|
|
||||||
playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(',');
|
playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(',');
|
||||||
|
|
||||||
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
|
playlistItem.VideoCodecs = transcodingProfile.VideoCodec.Split(',');
|
||||||
playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps;
|
playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps;
|
||||||
playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest;
|
playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest;
|
||||||
|
|
||||||
|
@ -1137,6 +1138,37 @@ namespace MediaBrowser.Model.Dlna
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ProfileConditionValue.IsAnamorphic:
|
case ProfileConditionValue.IsAnamorphic:
|
||||||
|
{
|
||||||
|
bool isAnamorphic;
|
||||||
|
if (bool.TryParse(value, out isAnamorphic))
|
||||||
|
{
|
||||||
|
if (isAnamorphic && condition.Condition == ProfileConditionType.Equals)
|
||||||
|
{
|
||||||
|
item.RequireNonAnamorphic = true;
|
||||||
|
}
|
||||||
|
else if (!isAnamorphic && condition.Condition == ProfileConditionType.NotEquals)
|
||||||
|
{
|
||||||
|
item.RequireNonAnamorphic = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ProfileConditionValue.IsInterlaced:
|
||||||
|
{
|
||||||
|
bool isInterlaced;
|
||||||
|
if (bool.TryParse(value, out isInterlaced))
|
||||||
|
{
|
||||||
|
if (isInterlaced && condition.Condition == ProfileConditionType.Equals)
|
||||||
|
{
|
||||||
|
item.DeInterlace = true;
|
||||||
|
}
|
||||||
|
else if (!isInterlaced && condition.Condition == ProfileConditionType.NotEquals)
|
||||||
|
{
|
||||||
|
item.DeInterlace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ProfileConditionValue.AudioProfile:
|
case ProfileConditionValue.AudioProfile:
|
||||||
case ProfileConditionValue.Has64BitOffsets:
|
case ProfileConditionValue.Has64BitOffsets:
|
||||||
case ProfileConditionValue.PacketLength:
|
case ProfileConditionValue.PacketLength:
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
public StreamInfo()
|
public StreamInfo()
|
||||||
{
|
{
|
||||||
AudioCodecs = new string[] { };
|
AudioCodecs = new string[] { };
|
||||||
|
VideoCodecs = new string[] { };
|
||||||
SubtitleCodecs = new string[] { };
|
SubtitleCodecs = new string[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +35,15 @@ namespace MediaBrowser.Model.Dlna
|
||||||
|
|
||||||
public long StartPositionTicks { get; set; }
|
public long StartPositionTicks { get; set; }
|
||||||
|
|
||||||
public string VideoCodec { get; set; }
|
|
||||||
public string VideoProfile { get; set; }
|
public string VideoProfile { get; set; }
|
||||||
|
|
||||||
public bool RequireAvc { get; set; }
|
public bool RequireAvc { get; set; }
|
||||||
|
public bool DeInterlace { get; set; }
|
||||||
|
public bool RequireNonAnamorphic { get; set; }
|
||||||
public bool CopyTimestamps { get; set; }
|
public bool CopyTimestamps { get; set; }
|
||||||
public bool EnableSubtitlesInManifest { get; set; }
|
public bool EnableSubtitlesInManifest { get; set; }
|
||||||
public string[] AudioCodecs { get; set; }
|
public string[] AudioCodecs { get; set; }
|
||||||
|
public string[] VideoCodecs { get; set; }
|
||||||
|
|
||||||
public int? AudioStreamIndex { get; set; }
|
public int? AudioStreamIndex { get; set; }
|
||||||
|
|
||||||
|
@ -204,11 +207,15 @@ namespace MediaBrowser.Model.Dlna
|
||||||
string.Empty :
|
string.Empty :
|
||||||
string.Join(",", item.AudioCodecs);
|
string.Join(",", item.AudioCodecs);
|
||||||
|
|
||||||
|
string videoCodecs = item.VideoCodecs.Length == 0 ?
|
||||||
|
string.Empty :
|
||||||
|
string.Join(",", item.VideoCodecs);
|
||||||
|
|
||||||
list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty));
|
list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty));
|
||||||
list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty));
|
list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty));
|
||||||
list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty));
|
list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty));
|
||||||
list.Add(new NameValuePair("Static", item.IsDirectStream.ToString().ToLower()));
|
list.Add(new NameValuePair("Static", item.IsDirectStream.ToString().ToLower()));
|
||||||
list.Add(new NameValuePair("VideoCodec", item.VideoCodec ?? string.Empty));
|
list.Add(new NameValuePair("VideoCodec", videoCodecs));
|
||||||
list.Add(new NameValuePair("AudioCodec", audioCodecs));
|
list.Add(new NameValuePair("AudioCodec", audioCodecs));
|
||||||
list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty));
|
list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty));
|
||||||
list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty));
|
list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty));
|
||||||
|
@ -232,7 +239,9 @@ namespace MediaBrowser.Model.Dlna
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !forceStartPosition)
|
var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls");
|
||||||
|
|
||||||
|
if (isHls && !forceStartPosition)
|
||||||
{
|
{
|
||||||
list.Add(new NameValuePair("StartTimeTicks", string.Empty));
|
list.Add(new NameValuePair("StartTimeTicks", string.Empty));
|
||||||
}
|
}
|
||||||
|
@ -276,6 +285,14 @@ namespace MediaBrowser.Model.Dlna
|
||||||
|
|
||||||
list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty));
|
list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty));
|
||||||
|
|
||||||
|
list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString().ToLower()));
|
||||||
|
list.Add(new NameValuePair("DeInterlace", item.DeInterlace.ToString().ToLower()));
|
||||||
|
|
||||||
|
if (!isDlna && isHls)
|
||||||
|
{
|
||||||
|
list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,9 +626,34 @@ namespace MediaBrowser.Model.Dlna
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string TargetVideoCodec
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
MediaStream stream = TargetVideoStream;
|
||||||
|
|
||||||
|
string inputCodec = stream == null ? null : stream.Codec;
|
||||||
|
|
||||||
|
if (IsDirectStream)
|
||||||
|
{
|
||||||
|
return inputCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string codec in VideoCodecs)
|
||||||
|
{
|
||||||
|
if (StringHelper.EqualsIgnoreCase(codec, inputCodec))
|
||||||
|
{
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoCodecs.Length == 0 ? null : VideoCodecs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Predicts the audio channels that will be in the output stream
|
/// Predicts the audio channels that will be in the output stream
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? TargetSize
|
public long? TargetSize
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -45,14 +45,21 @@ namespace MediaBrowser.Providers.Music
|
||||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
|
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var releaseId = searchInfo.GetReleaseId();
|
var releaseId = searchInfo.GetReleaseId();
|
||||||
|
var releaseGroupId = searchInfo.GetReleaseGroupId();
|
||||||
|
|
||||||
string url = null;
|
string url = null;
|
||||||
var isNameSearch = false;
|
var isNameSearch = false;
|
||||||
|
bool forceMusicBrainzProper = false;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(releaseId))
|
if (!string.IsNullOrEmpty(releaseId))
|
||||||
{
|
{
|
||||||
url = string.Format("/ws/2/release/?query=reid:{0}", releaseId);
|
url = string.Format("/ws/2/release/?query=reid:{0}", releaseId);
|
||||||
}
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(releaseGroupId))
|
||||||
|
{
|
||||||
|
url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
||||||
|
forceMusicBrainzProper = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var artistMusicBrainzId = searchInfo.GetMusicBrainzArtistId();
|
var artistMusicBrainzId = searchInfo.GetMusicBrainzArtistId();
|
||||||
|
@ -75,7 +82,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(url))
|
if (!string.IsNullOrWhiteSpace(url))
|
||||||
{
|
{
|
||||||
using (var stream = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false))
|
using (var stream = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
return GetResultsFromResponse(stream);
|
return GetResultsFromResponse(stream);
|
||||||
}
|
}
|
||||||
|
@ -131,7 +138,14 @@ namespace MediaBrowser.Providers.Music
|
||||||
Item = new MusicAlbum()
|
Item = new MusicAlbum()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(releaseId))
|
// If we have a release group Id but not a release Id...
|
||||||
|
if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId))
|
||||||
|
{
|
||||||
|
releaseId = await GetReleaseIdFromReleaseGroupId(releaseGroupId, cancellationToken).ConfigureAwait(false);
|
||||||
|
result.HasMetadata = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(releaseId))
|
||||||
{
|
{
|
||||||
var artistMusicBrainzId = id.GetMusicBrainzArtistId();
|
var artistMusicBrainzId = id.GetMusicBrainzArtistId();
|
||||||
|
|
||||||
|
@ -139,13 +153,13 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
if (releaseResult != null)
|
if (releaseResult != null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(releaseResult.ReleaseId))
|
if (!string.IsNullOrWhiteSpace(releaseResult.ReleaseId))
|
||||||
{
|
{
|
||||||
releaseId = releaseResult.ReleaseId;
|
releaseId = releaseResult.ReleaseId;
|
||||||
result.HasMetadata = true;
|
result.HasMetadata = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId))
|
if (!string.IsNullOrWhiteSpace(releaseResult.ReleaseGroupId))
|
||||||
{
|
{
|
||||||
releaseGroupId = releaseResult.ReleaseGroupId;
|
releaseGroupId = releaseResult.ReleaseGroupId;
|
||||||
result.HasMetadata = true;
|
result.HasMetadata = true;
|
||||||
|
@ -157,13 +171,13 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a release Id but not a release group Id...
|
// If we have a release Id but not a release group Id...
|
||||||
if (!string.IsNullOrEmpty(releaseId) && string.IsNullOrEmpty(releaseGroupId))
|
if (!string.IsNullOrWhiteSpace(releaseId) && string.IsNullOrWhiteSpace(releaseGroupId))
|
||||||
{
|
{
|
||||||
releaseGroupId = await GetReleaseGroupId(releaseId, cancellationToken).ConfigureAwait(false);
|
releaseGroupId = await GetReleaseGroupFromReleaseId(releaseId, cancellationToken).ConfigureAwait(false);
|
||||||
result.HasMetadata = true;
|
result.HasMetadata = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(releaseId) || !string.IsNullOrEmpty(releaseGroupId))
|
if (!string.IsNullOrWhiteSpace(releaseId) || !string.IsNullOrWhiteSpace(releaseGroupId))
|
||||||
{
|
{
|
||||||
result.HasMetadata = true;
|
result.HasMetadata = true;
|
||||||
}
|
}
|
||||||
|
@ -411,13 +425,42 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetReleaseIdFromReleaseGroupId(string releaseGroupId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
||||||
|
|
||||||
|
using (var stream = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
var settings = _xmlSettings.Create(false);
|
||||||
|
|
||||||
|
settings.CheckCharacters = false;
|
||||||
|
settings.IgnoreProcessingInstructions = true;
|
||||||
|
settings.IgnoreComments = true;
|
||||||
|
|
||||||
|
using (var reader = XmlReader.Create(oReader, settings))
|
||||||
|
{
|
||||||
|
var result = ReleaseResult.Parse(reader).FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result.ReleaseId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the release group id internal.
|
/// Gets the release group id internal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="releaseEntryId">The release entry id.</param>
|
/// <param name="releaseEntryId">The release entry id.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task{System.String}.</returns>
|
/// <returns>Task{System.String}.</returns>
|
||||||
private async Task<string> GetReleaseGroupId(string releaseEntryId, CancellationToken cancellationToken)
|
private async Task<string> GetReleaseGroupFromReleaseId(string releaseEntryId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
||||||
|
|
||||||
|
@ -514,11 +557,11 @@ namespace MediaBrowser.Providers.Music
|
||||||
private List<MbzUrl> _mbzUrls = null;
|
private List<MbzUrl> _mbzUrls = null;
|
||||||
private MbzUrl _chosenUrl;
|
private MbzUrl _chosenUrl;
|
||||||
|
|
||||||
private async Task<MbzUrl> GetMbzUrl()
|
private async Task<MbzUrl> GetMbzUrl(bool forceMusicBrainzProper = false)
|
||||||
{
|
{
|
||||||
if (_chosenUrl == null || _mbzUrls == null || (DateTime.UtcNow.Ticks - _lastMbzUrlQueryTicks) > TimeSpan.FromHours(12).Ticks)
|
if (_chosenUrl == null || _mbzUrls == null || (DateTime.UtcNow.Ticks - _lastMbzUrlQueryTicks) > TimeSpan.FromHours(12).Ticks)
|
||||||
{
|
{
|
||||||
var urls = await RefreshMzbUrls().ConfigureAwait(false);
|
var urls = await RefreshMzbUrls(forceMusicBrainzProper).ConfigureAwait(false);
|
||||||
|
|
||||||
if (urls.Count > 1)
|
if (urls.Count > 1)
|
||||||
{
|
{
|
||||||
|
@ -533,30 +576,12 @@ namespace MediaBrowser.Providers.Music
|
||||||
return _chosenUrl;
|
return _chosenUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<MbzUrl>> RefreshMzbUrls()
|
private async Task<List<MbzUrl>> RefreshMzbUrls(bool forceMusicBrainzProper = false)
|
||||||
{
|
{
|
||||||
List<MbzUrl> list;
|
List<MbzUrl> list;
|
||||||
|
|
||||||
try
|
if (forceMusicBrainzProper)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
|
||||||
{
|
|
||||||
Url = "https://mb3admin.com/admin/service/standards/musicBrainzUrls",
|
|
||||||
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
|
|
||||||
|
|
||||||
list = results;
|
|
||||||
}
|
|
||||||
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error getting music brainz info", ex);
|
|
||||||
|
|
||||||
list = new List<MbzUrl>
|
list = new List<MbzUrl>
|
||||||
{
|
{
|
||||||
new MbzUrl
|
new MbzUrl
|
||||||
|
@ -566,22 +591,55 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var options = new HttpRequestOptions
|
||||||
|
{
|
||||||
|
Url = "https://mb3admin.com/admin/service/standards/musicBrainzUrls",
|
||||||
|
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
|
||||||
|
|
||||||
|
list = results;
|
||||||
|
}
|
||||||
|
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error getting music brainz info", ex);
|
||||||
|
|
||||||
|
list = new List<MbzUrl>
|
||||||
|
{
|
||||||
|
new MbzUrl
|
||||||
|
{
|
||||||
|
url = MusicBrainzBaseUrl,
|
||||||
|
throttleMs = 1000
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_mbzUrls = list.ToList();
|
_mbzUrls = list.ToList();
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return GetMusicBrainzResponse(url, isSearch, false, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the music brainz response.
|
/// Gets the music brainz response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">The URL.</param>
|
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
|
||||||
/// <param name="isSearch">if set to <c>true</c> [is search].</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task{XmlDocument}.</returns>
|
|
||||||
internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
var urlInfo = await GetMbzUrl().ConfigureAwait(false);
|
var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false);
|
||||||
var throttleMs = urlInfo.throttleMs;
|
var throttleMs = urlInfo.throttleMs;
|
||||||
|
|
||||||
if (throttleMs > 0)
|
if (throttleMs > 0)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("3.2.7.5")]
|
[assembly: AssemblyVersion("3.2.8.1")]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user