capture more transcoding info

This commit is contained in:
Luke Pulverenti 2017-06-24 14:33:19 -04:00
parent 8dcfda89d1
commit a107ff0369
14 changed files with 338 additions and 45 deletions

View File

@ -265,7 +265,8 @@ namespace MediaBrowser.Api
Height = state.OutputHeight, Height = state.OutputHeight,
AudioChannels = state.OutputAudioChannels, AudioChannels = state.OutputAudioChannels,
IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase), IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase),
IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase),
TranscodeReasons = state.TranscodeReasons
}); });
} }
} }

View File

@ -583,6 +583,10 @@ namespace MediaBrowser.Api.Playback
videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
} }
} }
else if (i == 33)
{
request.TranscodeReasons = val;
}
} }
} }

View File

@ -541,6 +541,11 @@ namespace MediaBrowser.Api.Playback.Hls
{ {
queryString += "&SegmentContainer=" + state.Request.SegmentContainer; queryString += "&SegmentContainer=" + state.Request.SegmentContainer;
} }
// from universal audio service
if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) && queryString.IndexOf("TranscodeReasons=", StringComparison.OrdinalIgnoreCase) == -1)
{
queryString += "&TranscodeReasons=" + state.Request.TranscodeReasons;
}
// Main stream // Main stream
var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8"; var playlistUrl = isLiveStream ? "live.m3u8" : "main.m3u8";

View File

@ -513,6 +513,8 @@ namespace MediaBrowser.Api.Playback
var profiles = info.GetSubtitleProfiles(false, "-", accessToken); var profiles = info.GetSubtitleProfiles(false, "-", accessToken);
mediaSource.DefaultSubtitleStreamIndex = info.SubtitleStreamIndex; mediaSource.DefaultSubtitleStreamIndex = info.SubtitleStreamIndex;
mediaSource.TranscodeReasons = info.TranscodeReasons;
foreach (var profile in profiles) foreach (var profile in profiles)
{ {
foreach (var stream in mediaSource.MediaStreams) foreach (var stream in mediaSource.MediaStreams)

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Api.Playback.Hls; using MediaBrowser.Api.Playback.Hls;
using MediaBrowser.Api.Playback.Progressive; using MediaBrowser.Api.Playback.Progressive;
@ -265,7 +266,8 @@ namespace MediaBrowser.Api.Playback
Static = isStatic, Static = isStatic,
SegmentContainer = request.TranscodingContainer, SegmentContainer = request.TranscodingContainer,
AudioSampleRate = request.MaxAudioSampleRate, AudioSampleRate = request.MaxAudioSampleRate,
BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames BreakOnNonKeyFrames = transcodingProfile.BreakOnNonKeyFrames,
TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray())
}; };
if (isHeadRequest) if (isHeadRequest)
@ -307,7 +309,8 @@ namespace MediaBrowser.Api.Playback
PlaySessionId = playbackInfoResult.PlaySessionId, PlaySessionId = playbackInfoResult.PlaySessionId,
StartTimeTicks = request.StartTimeTicks, StartTimeTicks = request.StartTimeTicks,
Static = isStatic, Static = isStatic,
AudioSampleRate = request.MaxAudioSampleRate AudioSampleRate = request.MaxAudioSampleRate,
TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray())
}; };
if (isHeadRequest) if (isHeadRequest)

View File

@ -487,7 +487,7 @@ namespace MediaBrowser.Controller.Entities
var folder = this; var folder = this;
innerProgress.RegisterAction(p => innerProgress.RegisterAction(p =>
{ {
double newPct = .70 * p + 10; double newPct = .80 * p + 10;
progress.Report(newPct); progress.Report(newPct);
ProviderManager.OnRefreshProgress(folder, newPct); ProviderManager.OnRefreshProgress(folder, newPct);
}); });
@ -498,11 +498,11 @@ namespace MediaBrowser.Controller.Entities
if (refreshChildMetadata) if (refreshChildMetadata)
{ {
progress.Report(80); progress.Report(90);
if (recursive) if (recursive)
{ {
ProviderManager.OnRefreshProgress(this, 80); ProviderManager.OnRefreshProgress(this, 90);
} }
var container = this as IMetadataContainer; var container = this as IMetadataContainer;
@ -512,7 +512,7 @@ namespace MediaBrowser.Controller.Entities
var folder = this; var folder = this;
innerProgress.RegisterAction(p => innerProgress.RegisterAction(p =>
{ {
double newPct = .20 * p + 80; double newPct = .10 * p + 90;
progress.Report(newPct); progress.Report(newPct);
if (recursive) if (recursive)
{ {

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
@ -9,6 +10,7 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Session;
namespace MediaBrowser.Controller.MediaEncoding namespace MediaBrowser.Controller.MediaEncoding
{ {
@ -40,6 +42,24 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ReadInputAtNativeFramerate { get; set; } public bool ReadInputAtNativeFramerate { get; set; }
private List<TranscodeReason> _transcodeReasons = null;
public List<TranscodeReason> TranscodeReasons
{
get
{
if (_transcodeReasons == null)
{
_transcodeReasons = (BaseRequest.TranscodeReasons ?? string.Empty)
.Split(',')
.Where(i => !string.IsNullOrWhiteSpace(i))
.Select(v => (TranscodeReason)Enum.Parse(typeof(TranscodeReason), v, true))
.ToList();
}
return _transcodeReasons;
}
}
public bool IgnoreInputDts public bool IgnoreInputDts
{ {
get get
@ -251,7 +271,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
return AudioStream.SampleRate; return AudioStream.SampleRate;
} }
} }
else if (BaseRequest.AudioSampleRate.HasValue) else if (BaseRequest.AudioSampleRate.HasValue)
{ {

View File

@ -204,6 +204,8 @@ namespace MediaBrowser.Controller.MediaEncoding
public string SubtitleCodec { get; set; } public string SubtitleCodec { get; set; }
public string TranscodeReasons { get; set; }
/// <summary> /// <summary>
/// Gets or sets the index of the audio stream. /// Gets or sets the index of the audio stream.
/// </summary> /// </summary>

View File

@ -55,7 +55,6 @@ namespace MediaBrowser.Model.Configuration
HidePlayedInLatest = true; HidePlayedInLatest = true;
PlayDefaultAudioTrack = true; PlayDefaultAudioTrack = true;
DisplayMissingEpisodes = true;
LatestItemsExcludes = new string[] { }; LatestItemsExcludes = new string[] { };
OrderedViews = new string[] { }; OrderedViews = new string[] { };

View File

@ -1,5 +1,4 @@
using System.Xml.Serialization; using System.Xml.Serialization;
using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Model.Dlna namespace MediaBrowser.Model.Dlna
{ {

View File

@ -105,8 +105,99 @@ namespace MediaBrowser.Model.Dlna
return null; return null;
} }
private TranscodeReason? GetTranscodeReasonForFailedCondition(ProfileCondition condition)
{
switch (condition.Property)
{
case ProfileConditionValue.AudioBitrate:
if (condition.Condition == ProfileConditionType.LessThanEqual)
{
return TranscodeReason.AudioBitrateNotSupported;
}
return TranscodeReason.AudioBitrateNotSupported;
case ProfileConditionValue.AudioChannels:
if (condition.Condition == ProfileConditionType.LessThanEqual)
{
return TranscodeReason.AudioChannelsNotSupported;
}
return TranscodeReason.AudioChannelsNotSupported;
case ProfileConditionValue.AudioProfile:
return TranscodeReason.AudioProfileNotSupported;
case ProfileConditionValue.AudioSampleRate:
return TranscodeReason.AudioSampleRateNotSupported;
case ProfileConditionValue.Has64BitOffsets:
// TODO
return null;
case ProfileConditionValue.Height:
return TranscodeReason.VideoResolutionNotSupported;
case ProfileConditionValue.IsAnamorphic:
return TranscodeReason.AnamorphicVideoNotSupported;
case ProfileConditionValue.IsAvc:
// TODO
return null;
case ProfileConditionValue.IsInterlaced:
return TranscodeReason.InterlacedVideoNotSupported;
case ProfileConditionValue.IsSecondaryAudio:
return TranscodeReason.SecondaryAudioNotSupported;
case ProfileConditionValue.NumAudioStreams:
// TODO
return null;
case ProfileConditionValue.NumVideoStreams:
// TODO
return null;
case ProfileConditionValue.PacketLength:
// TODO
return null;
case ProfileConditionValue.RefFrames:
return TranscodeReason.RefFramesNotSupported;
case ProfileConditionValue.VideoBitDepth:
return TranscodeReason.VideoBitDepthNotSupported;
case ProfileConditionValue.VideoBitrate:
return TranscodeReason.VideoBitrateNotSupported;
case ProfileConditionValue.VideoCodecTag:
return TranscodeReason.VideoCodecNotSupported;
case ProfileConditionValue.VideoFramerate:
return TranscodeReason.VideoFramerateNotSupported;
case ProfileConditionValue.VideoLevel:
return TranscodeReason.VideoLevelNotSupported;
case ProfileConditionValue.VideoProfile:
return TranscodeReason.VideoProfileNotSupported;
case ProfileConditionValue.VideoTimestamp:
// TODO
return null;
case ProfileConditionValue.Width:
return TranscodeReason.VideoResolutionNotSupported;
default:
return null;
}
}
private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options) private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
{ {
List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
StreamInfo playlistItem = new StreamInfo StreamInfo playlistItem = new StreamInfo
{ {
ItemId = options.ItemId, ItemId = options.ItemId,
@ -133,7 +224,10 @@ namespace MediaBrowser.Model.Dlna
MediaStream audioStream = item.GetDefaultAudioStream(null); MediaStream audioStream = item.GetDefaultAudioStream(null);
List<PlayMethod> directPlayMethods = GetAudioDirectPlayMethods(item, audioStream, options); var directPlayInfo = GetAudioDirectPlayMethods(item, audioStream, options);
List<PlayMethod> directPlayMethods = directPlayInfo.Item1;
transcodeReasons.AddRange(directPlayInfo.Item2);
ConditionProcessor conditionProcessor = new ConditionProcessor(); ConditionProcessor conditionProcessor = new ConditionProcessor();
@ -180,6 +274,11 @@ namespace MediaBrowser.Model.Dlna
if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate)) if (!conditionProcessor.IsAudioConditionSatisfied(c, inputAudioChannels, inputAudioBitrate, inputAudioSampleRate))
{ {
LogConditionFailure(options.Profile, "AudioCodecProfile", c, item); LogConditionFailure(options.Profile, "AudioCodecProfile", c, item);
var transcodeReason = GetTranscodeReasonForFailedCondition(c);
if (transcodeReason.HasValue)
{
transcodeReasons.Add(transcodeReason.Value);
}
all = false; all = false;
break; break;
} }
@ -292,9 +391,9 @@ namespace MediaBrowser.Model.Dlna
var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate); var longBitrate = Math.Min(transcodingBitrate, playlistItem.AudioBitrate ?? transcodingBitrate);
playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate); playlistItem.AudioBitrate = longBitrate > int.MaxValue ? int.MaxValue : Convert.ToInt32(longBitrate);
} }
playlistItem.TranscodeReasons = transcodeReasons;
return playlistItem; return playlistItem;
} }
@ -308,8 +407,10 @@ namespace MediaBrowser.Model.Dlna
return options.GetMaxBitrate(isAudio); return options.GetMaxBitrate(isAudio);
} }
private List<PlayMethod> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) private Tuple<List<PlayMethod>, List<TranscodeReason>> GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options)
{ {
List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
DirectPlayProfile directPlayProfile = null; DirectPlayProfile directPlayProfile = null;
foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles) foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles)
{ {
@ -325,27 +426,134 @@ namespace MediaBrowser.Model.Dlna
if (directPlayProfile != null) if (directPlayProfile != null)
{ {
// While options takes the network and other factors into account. Only applies to direct stream // While options takes the network and other factors into account. Only applies to direct stream
if (item.SupportsDirectStream && IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream) && options.EnableDirectStream) if (item.SupportsDirectStream)
{ {
playMethods.Add(PlayMethod.DirectStream); if (IsAudioEligibleForDirectPlay(item, options.GetMaxBitrate(true), PlayMethod.DirectStream))
{
if (options.EnableDirectStream)
{
playMethods.Add(PlayMethod.DirectStream);
}
}
else
{
transcodeReasons.Add(TranscodeReason.ContainerBitrateExceedsLimit);
}
} }
// The profile describes what the device supports // The profile describes what the device supports
// If device requirements are satisfied then allow both direct stream and direct play // If device requirements are satisfied then allow both direct stream and direct play
if (item.SupportsDirectPlay && if (item.SupportsDirectPlay)
IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay) && options.EnableDirectPlay)
{ {
playMethods.Add(PlayMethod.DirectPlay); if (IsAudioEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true), PlayMethod.DirectPlay))
{
if (options.EnableDirectPlay)
{
playMethods.Add(PlayMethod.DirectPlay);
}
}
else
{
transcodeReasons.Add(TranscodeReason.ContainerBitrateExceedsLimit);
}
} }
} }
else else
{ {
transcodeReasons.InsertRange(0, GetTranscodeReasonsFromDirectPlayProfile(item, null, audioStream, options.Profile.DirectPlayProfiles));
_logger.Info("Profile: {0}, No direct play profiles found for Path: {1}", _logger.Info("Profile: {0}, No direct play profiles found for Path: {1}",
options.Profile.Name ?? "Unknown Profile", options.Profile.Name ?? "Unknown Profile",
item.Path ?? "Unknown path"); item.Path ?? "Unknown path");
} }
return playMethods; if (playMethods.Count > 0)
{
transcodeReasons.Clear();
}
else
{
transcodeReasons = transcodeReasons.Distinct().ToList();
}
return new Tuple<List<PlayMethod>, List<TranscodeReason>>(playMethods, transcodeReasons);
}
private List<TranscodeReason> GetTranscodeReasonsFromDirectPlayProfile(MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable<DirectPlayProfile> directPlayProfiles)
{
var list = new List<TranscodeReason>();
var containerSupported = false;
var audioSupported = false;
var videoSupported = false;
foreach (var profile in directPlayProfiles)
{
if (profile.Container.Length > 0)
{
// Check container type
string mediaContainer = item.Container ?? string.Empty;
foreach (string i in profile.GetContainers())
{
if (StringHelper.EqualsIgnoreCase(i, mediaContainer))
{
containerSupported = true;
if (videoStream != null)
{
// Check video codec
List<string> videoCodecs = profile.GetVideoCodecs();
if (videoCodecs.Count > 0)
{
string videoCodec = videoStream.Codec;
if (!string.IsNullOrEmpty(videoCodec) && ListHelper.ContainsIgnoreCase(videoCodecs, videoCodec))
{
videoSupported = true;
}
}
else
{
videoSupported = true;
}
}
if (audioStream != null)
{
// Check audio codec
List<string> audioCodecs = profile.GetAudioCodecs();
if (audioCodecs.Count > 0)
{
string audioCodec = audioStream.Codec;
if (!string.IsNullOrEmpty(audioCodec) && ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec))
{
audioSupported = true;
}
}
else
{
audioSupported = true;
}
}
}
}
}
}
if (!containerSupported)
{
list.Add(TranscodeReason.ContainerNotSupported);
}
if (videoStream != null && !videoSupported)
{
list.Add(TranscodeReason.VideoCodecNotSupported);
}
if (audioStream != null && !audioSupported)
{
list.Add(TranscodeReason.VideoCodecNotSupported);
}
return list;
} }
private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles) private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles)
@ -393,6 +601,8 @@ namespace MediaBrowser.Model.Dlna
private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
{ {
List<TranscodeReason> transcodeReasons = new List<TranscodeReason>();
StreamInfo playlistItem = new StreamInfo StreamInfo playlistItem = new StreamInfo
{ {
ItemId = options.ItemId, ItemId = options.ItemId,
@ -428,7 +638,8 @@ namespace MediaBrowser.Model.Dlna
if (isEligibleForDirectPlay || isEligibleForDirectStream) if (isEligibleForDirectPlay || isEligibleForDirectStream)
{ {
// See if it can be direct played // See if it can be direct played
PlayMethod? directPlay = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream); var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectPlay, isEligibleForDirectStream);
var directPlay = directPlayInfo.Item1;
if (directPlay != null) if (directPlay != null)
{ {
@ -445,6 +656,8 @@ namespace MediaBrowser.Model.Dlna
return playlistItem; return playlistItem;
} }
transcodeReasons.AddRange(directPlayInfo.Item2);
} }
// Can't direct play, find the transcoding profile // Can't direct play, find the transcoding profile
@ -618,6 +831,8 @@ namespace MediaBrowser.Model.Dlna
} }
} }
playlistItem.TranscodeReasons = transcodeReasons;
return playlistItem; return playlistItem;
} }
@ -677,7 +892,7 @@ namespace MediaBrowser.Model.Dlna
return Math.Min(defaultBitrate, encoderAudioBitrateLimit); return Math.Min(defaultBitrate, encoderAudioBitrateLimit);
} }
private PlayMethod? GetVideoDirectPlayProfile(VideoOptions options, private Tuple<PlayMethod?, List<TranscodeReason>> GetVideoDirectPlayProfile(VideoOptions options,
MediaSourceInfo mediaSource, MediaSourceInfo mediaSource,
MediaStream videoStream, MediaStream videoStream,
MediaStream audioStream, MediaStream audioStream,
@ -688,11 +903,11 @@ namespace MediaBrowser.Model.Dlna
if (options.ForceDirectPlay) if (options.ForceDirectPlay)
{ {
return PlayMethod.DirectPlay; return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectPlay, new List<TranscodeReason>());
} }
if (options.ForceDirectStream) if (options.ForceDirectStream)
{ {
return PlayMethod.DirectStream; return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectStream, new List<TranscodeReason>());
} }
if (videoStream == null) if (videoStream == null)
@ -701,7 +916,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile", profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path"); mediaSource.Path ?? "Unknown path");
return null; return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownVideoStreamInfo });
} }
// See if it can be direct played // See if it can be direct played
@ -721,7 +936,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile", profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path"); mediaSource.Path ?? "Unknown path");
return null; return new Tuple<PlayMethod?, List<TranscodeReason>>(null, GetTranscodeReasonsFromDirectPlayProfile(mediaSource, videoStream, audioStream, profile.DirectPlayProfiles));
} }
string container = mediaSource.Container; string container = mediaSource.Container;
@ -784,7 +999,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile", profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path"); mediaSource.Path ?? "Unknown path");
return null; return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownVideoStreamInfo });
} }
conditions = new List<ProfileCondition>(); conditions = new List<ProfileCondition>();
@ -819,7 +1034,12 @@ namespace MediaBrowser.Model.Dlna
{ {
LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource);
return null; var transcodeReason = GetTranscodeReasonForFailedCondition(i);
var transcodeReasons = transcodeReason.HasValue
? new List<TranscodeReason> { transcodeReason.Value }
: new List<TranscodeReason> { };
return new Tuple<PlayMethod?, List<TranscodeReason>>(null, transcodeReasons);
} }
} }
@ -833,7 +1053,7 @@ namespace MediaBrowser.Model.Dlna
profile.Name ?? "Unknown Profile", profile.Name ?? "Unknown Profile",
mediaSource.Path ?? "Unknown path"); mediaSource.Path ?? "Unknown path");
return null; return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.UnknownAudioStreamInfo });
} }
conditions = new List<ProfileCondition>(); conditions = new List<ProfileCondition>();
@ -870,17 +1090,22 @@ namespace MediaBrowser.Model.Dlna
{ {
LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource); LogConditionFailure(profile, "VideoAudioCodecProfile", i, mediaSource);
return null; var transcodeReason = GetTranscodeReasonForFailedCondition(i);
var transcodeReasons = transcodeReason.HasValue
? new List<TranscodeReason> { transcodeReason.Value }
: new List<TranscodeReason> { };
return new Tuple<PlayMethod?, List<TranscodeReason>>(null, transcodeReasons);
} }
} }
} }
if (isEligibleForDirectStream && mediaSource.SupportsDirectStream) if (isEligibleForDirectStream && mediaSource.SupportsDirectStream)
{ {
return PlayMethod.DirectStream; return new Tuple<PlayMethod?, List<TranscodeReason>>(PlayMethod.DirectStream, new List<TranscodeReason>());
} }
return null; return new Tuple<PlayMethod?, List<TranscodeReason>>(null, new List<TranscodeReason> { TranscodeReason.ContainerBitrateExceedsLimit });
} }
private void LogConditionFailure(DeviceProfile profile, string type, ProfileCondition condition, MediaSourceInfo mediaSource) private void LogConditionFailure(DeviceProfile profile, string type, ProfileCondition condition, MediaSourceInfo mediaSource)
@ -1047,12 +1272,12 @@ namespace MediaBrowser.Model.Dlna
// Don't restrict by bitrate if coming from an external domain // Don't restrict by bitrate if coming from an external domain
if (item.IsRemote) if (item.IsRemote)
{ {
return true; return true;
} }
if (!maxBitrate.HasValue) if (!maxBitrate.HasValue)
{ {
_logger.Info("Cannot "+ playMethod + " due to unknown supported bitrate"); _logger.Info("Cannot " + playMethod + " due to unknown supported bitrate");
return false; return false;
} }

View File

@ -21,6 +21,7 @@ namespace MediaBrowser.Model.Dlna
AudioCodecs = new string[] { }; AudioCodecs = new string[] { };
VideoCodecs = new string[] { }; VideoCodecs = new string[] { };
SubtitleCodecs = new string[] { }; SubtitleCodecs = new string[] { };
TranscodeReasons = new List<TranscodeReason>();
} }
public string ItemId { get; set; } public string ItemId { get; set; }
@ -89,6 +90,7 @@ namespace MediaBrowser.Model.Dlna
public string PlaySessionId { get; set; } public string PlaySessionId { get; set; }
public List<MediaSourceInfo> AllMediaSources { get; set; } public List<MediaSourceInfo> AllMediaSources { get; set; }
public List<TranscodeReason> TranscodeReasons { get; set; }
public string MediaSourceId public string MediaSourceId
{ {
@ -231,22 +233,11 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty));
list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty));
var forceStartPosition = false;
long startPositionTicks = item.StartPositionTicks; long startPositionTicks = item.StartPositionTicks;
//if (item.MediaSource.DateLiveStreamOpened.HasValue && startPositionTicks == 0)
//{
// var elapsed = DateTime.UtcNow - item.MediaSource.DateLiveStreamOpened.Value;
// elapsed -= TimeSpan.FromSeconds(20);
// if (elapsed.TotalSeconds >= 0)
// {
// startPositionTicks = elapsed.Ticks + startPositionTicks;
// forceStartPosition = true;
// }
//}
var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls"); var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls");
if (isHls && !forceStartPosition) if (isHls)
{ {
list.Add(new NameValuePair("StartTimeTicks", string.Empty)); list.Add(new NameValuePair("StartTimeTicks", string.Empty));
} }
@ -310,6 +301,11 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString())); list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString()));
} }
if (isDlna || !item.IsDirectStream)
{
list.Add(new NameValuePair("TranscodeReasons", string.Join(",", item.TranscodeReasons.Distinct().Select(i => i.ToString()).ToArray())));
}
return list; return list;
} }

View File

@ -4,6 +4,7 @@ using MediaBrowser.Model.MediaInfo;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
namespace MediaBrowser.Model.Dto namespace MediaBrowser.Model.Dto
{ {
@ -110,6 +111,9 @@ namespace MediaBrowser.Model.Dto
} }
} }
[IgnoreDataMember]
public List<TranscodeReason> TranscodeReasons { get; set; }
public int? DefaultAudioStreamIndex { get; set; } public int? DefaultAudioStreamIndex { get; set; }
public int? DefaultSubtitleStreamIndex { get; set; } public int? DefaultSubtitleStreamIndex { get; set; }

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace MediaBrowser.Model.Session namespace MediaBrowser.Model.Session
{ {
public class TranscodingInfo public class TranscodingInfo
@ -15,5 +17,36 @@ namespace MediaBrowser.Model.Session
public int? Width { get; set; } public int? Width { get; set; }
public int? Height { get; set; } public int? Height { get; set; }
public int? AudioChannels { get; set; } public int? AudioChannels { get; set; }
public List<TranscodeReason> TranscodeReasons { get; set; }
public TranscodingInfo()
{
TranscodeReasons = new List<TranscodeReason>();
}
}
public enum TranscodeReason
{
ContainerNotSupported = 0,
VideoCodecNotSupported = 1,
AudioCodecNotSupported = 2,
ContainerBitrateExceedsLimit = 3,
AudioBitrateNotSupported = 4,
AudioChannelsNotSupported = 5,
VideoResolutionNotSupported = 6,
UnknownVideoStreamInfo = 7,
UnknownAudioStreamInfo = 8,
AudioProfileNotSupported = 9,
AudioSampleRateNotSupported = 10,
AnamorphicVideoNotSupported = 11,
InterlacedVideoNotSupported = 12,
SecondaryAudioNotSupported = 13,
RefFramesNotSupported = 14,
VideoBitDepthNotSupported = 15,
VideoBitrateNotSupported = 16,
VideoFramerateNotSupported = 17,
VideoLevelNotSupported = 18,
VideoProfileNotSupported = 19
} }
} }