From f3e992b82be4b23e33e6130d1495f2b5203d0576 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 23 Mar 2014 01:10:33 -0400 Subject: [PATCH] support more profile features --- MediaBrowser.Api/Movies/MoviesService.cs | 5 +- .../Playback/BaseStreamingService.cs | 42 ++-- MediaBrowser.Api/Playback/StreamRequest.cs | 5 +- MediaBrowser.Api/Playback/StreamState.cs | 10 - .../Dlna/TranscodingProfile.cs | 5 +- MediaBrowser.Dlna/DlnaManager.cs | 26 ++- MediaBrowser.Dlna/PlayTo/DlnaController.cs | 97 +++++++-- MediaBrowser.Dlna/PlayTo/PlaylistItem.cs | 20 +- .../PlayTo/PlaylistItemFactory.cs | 64 +----- MediaBrowser.Dlna/PlayTo/StreamHelper.cs | 186 +++--------------- 10 files changed, 188 insertions(+), 272 deletions(-) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index f9b7608696..204a7aab45 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -117,10 +117,9 @@ namespace MediaBrowser.Api.Movies public object Get(GetMovieRecommendations request) { - var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null; + var user = _userManager.GetUserById(request.UserId.Value); - var folder = user.RootFolder; - var movies = folder.RecursiveChildren.OfType().ToList(); + var movies = user.RootFolder.GetRecursiveChildren(user).OfType().ToList(); var result = GetRecommendationCategories(user, movies, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList()); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 1001980ec1..9ec28700dc 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -745,6 +745,16 @@ namespace MediaBrowser.Api.Playback } } + if (request.MaxAudioChannels.HasValue) + { + if (audioStream != null && audioStream.Channels.HasValue) + { + return Math.Min(request.MaxAudioChannels.Value, audioStream.Channels.Value); + } + + return request.MaxAudioChannels.Value; + } + return request.AudioChannels; } @@ -1205,73 +1215,73 @@ namespace MediaBrowser.Api.Playback } else if (i == 1) { - request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + request.MediaSourceId = val; } else if (i == 2) + { + request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + else if (i == 3) { if (videoRequest != null) { videoRequest.VideoCodec = (VideoCodecs)Enum.Parse(typeof(VideoCodecs), val, true); } } - else if (i == 3) + else if (i == 4) { request.AudioCodec = (AudioCodecs)Enum.Parse(typeof(AudioCodecs), val, true); } - else if (i == 4) + else if (i == 5) { if (videoRequest != null) { videoRequest.AudioStreamIndex = int.Parse(val, UsCulture); } } - else if (i == 5) + else if (i == 6) { if (videoRequest != null) { videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture); } } - else if (i == 6) + else if (i == 7) { if (videoRequest != null) { videoRequest.VideoBitRate = int.Parse(val, UsCulture); } } - else if (i == 7) + else if (i == 8) { request.AudioBitRate = int.Parse(val, UsCulture); } - else if (i == 8) - { - request.AudioChannels = int.Parse(val, UsCulture); - } else if (i == 9) + { + request.MaxAudioChannels = int.Parse(val, UsCulture); + } + else if (i == 10) { if (videoRequest != null) { request.StartTimeTicks = long.Parse(val, UsCulture); } } - else if (i == 10) + else if (i == 11) { if (videoRequest != null) { videoRequest.Profile = val; } } - else if (i == 11) + else if (i == 12) { if (videoRequest != null) { videoRequest.Level = val; } } - else if (i == 12) - { - request.ForcedMimeType = val; - } } } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index df52e5e3ee..2251ce52d3 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -49,6 +49,9 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "AudioChannels", Description = "Optional. Specify a specific number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? AudioChannels { get; set; } + [ApiMember(Name = "MaxAudioChannels", Description = "Optional. Specify a maximum number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? MaxAudioChannels { get; set; } + /// /// Gets or sets the audio sample rate. /// @@ -69,8 +72,6 @@ namespace MediaBrowser.Api.Playback public bool ThrowDebugError { get; set; } public string Params { get; set; } - - public string ForcedMimeType { get; set; } } public class VideoStreamRequest : StreamRequest diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 88daf9f623..ecc5c93ef2 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -79,16 +79,6 @@ namespace MediaBrowser.Api.Playback public string GetMimeType(string outputPath) { - if (!string.IsNullOrWhiteSpace(Request.ForcedMimeType)) - { - if (VideoRequest == null) - { - return "audio/" + Request.ForcedMimeType; - } - - return "video/" + Request.ForcedMimeType; - } - return MimeTypes.GetMimeType(outputPath); } } diff --git a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs index 1073f74aaf..32ffb91cf6 100644 --- a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs @@ -31,8 +31,9 @@ namespace MediaBrowser.Controller.Dlna public enum TranscodingSettingType { - Profile = 0, - MaxAudioChannels = 1 + VideoLevel = 0, + VideoProfile = 1, + MaxAudioChannels = 2 } public enum TranscodeSeekInfo diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index 24e9d83a03..ec2a09c52e 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -274,11 +274,9 @@ namespace MediaBrowser.Dlna Settings = new List { - new TranscodingSetting - { - Name = TranscodingSettingType.MaxAudioChannels, - Value = "6" - } + new TranscodingSetting { Name = TranscodingSettingType.MaxAudioChannels, Value = "6" }, + new TranscodingSetting{ Name = TranscodingSettingType.VideoLevel, Value = "3"}, + new TranscodingSetting{ Name = TranscodingSettingType.VideoProfile, Value = "baseline"} } }, new TranscodingProfile @@ -791,7 +789,13 @@ namespace MediaBrowser.Dlna Container = "ts", Type = DlnaProfileType.Video, VideoCodec = "h264", - AudioCodec = "aac" + AudioCodec = "aac", + + Settings = new List + { + new TranscodingSetting{ Name = TranscodingSettingType.VideoLevel, Value = "3"}, + new TranscodingSetting{ Name = TranscodingSettingType.VideoProfile, Value = "baseline"} + } }, new TranscodingProfile { @@ -1010,12 +1014,20 @@ namespace MediaBrowser.Dlna new TranscodingProfile { Container = "mp3", + AudioCodec = "mp3", Type = DlnaProfileType.Audio }, new TranscodingProfile { Container = "ts", - Type = DlnaProfileType.Video + Type = DlnaProfileType.Video, + AudioCodec = "aac", + VideoCodec = "h264", + Settings = new List + { + new TranscodingSetting{ Name = TranscodingSettingType.VideoLevel, Value = "3"}, + new TranscodingSetting{ Name = TranscodingSettingType.VideoProfile, Value = "baseline"} + } } }, diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs index e94663802f..4f9c92da52 100644 --- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs +++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs @@ -270,7 +270,7 @@ namespace MediaBrowser.Dlna.PlayTo playlistItem.StartPositionTicks = newItem.StartPositionTicks; playlistItem.StreamUrl = newItem.StreamUrl; playlistItem.Didl = newItem.Didl; - return _device.SetAvTransport(playlistItem.StreamUrl, playlistItem.DlnaHeaders, playlistItem.Didl); + return _device.SetAvTransport(playlistItem.StreamUrl, GetDlnaHeaders(playlistItem), playlistItem.Didl); } return _device.Seek(TimeSpan.FromTicks(command.SeekPositionTicks ?? 0)); @@ -391,16 +391,20 @@ namespace MediaBrowser.Dlna.PlayTo private PlaylistItem CreatePlaylistItem(BaseItem item, long startPostionTicks, string serverAddress) { - var streams = _itemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = item.Id }).ToList(); + var streams = _itemRepository.GetMediaStreams(new MediaStreamQuery + { + ItemId = item.Id + + }).ToList(); var deviceInfo = _device.Properties; - var playlistItem = GetPlaylistItem(item, _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification())); + var playlistItem = GetPlaylistItem(item, streams, _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification())); playlistItem.StartPositionTicks = startPostionTicks; if (playlistItem.MediaType == DlnaProfileType.Audio) { - playlistItem.StreamUrl = StreamHelper.GetAudioUrl(playlistItem, serverAddress); + playlistItem.StreamUrl = StreamHelper.GetAudioUrl(deviceInfo, playlistItem, streams, serverAddress); } else { @@ -410,32 +414,92 @@ namespace MediaBrowser.Dlna.PlayTo var didl = DidlBuilder.Build(item, _session.UserId.ToString(), serverAddress, playlistItem.StreamUrl, streams); playlistItem.Didl = didl; - var header = StreamHelper.GetDlnaHeaders(playlistItem); - playlistItem.DlnaHeaders = header; return playlistItem; } - private PlaylistItem GetPlaylistItem(BaseItem item, DeviceProfile profile) + private string GetDlnaHeaders(PlaylistItem item) + { + var orgOp = item.Transcode ? ";DLNA.ORG_OP=00" : ";DLNA.ORG_OP=01"; + + var orgCi = item.Transcode ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1"; + + const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000"; + + string contentFeatures; + + var container = item.Container.TrimStart('.'); + + if (string.Equals(container, "mp3", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=MP3"; + } + else if (string.Equals(container, "wma", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=WMABASE"; + } + else if (string.Equals(container, "wmw", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=WMVMED_BASE"; + } + else if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=WMVMED_BASE"; + } + else if (string.Equals(container, "avi", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=AVI"; + } + else if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=MATROSKA"; + } + else if (string.Equals(container, "mp4", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC"; + } + else if (string.Equals(container, "mpeg", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; + } + else if (string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) + { + contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; + } + else if (item.MediaType == DlnaProfileType.Video) + { + // Default to AVI for video + contentFeatures = "DLNA.ORG_PN=AVI"; + } + else + { + // Default to MP3 for audio + contentFeatures = "DLNA.ORG_PN=MP3"; + } + + return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); + } + + private PlaylistItem GetPlaylistItem(BaseItem item, List mediaStreams, DeviceProfile profile) { var video = item as Video; if (video != null) { - return new PlaylistItemFactory(_itemRepository).Create(video, profile); + return new PlaylistItemFactory().Create(video, mediaStreams, profile); } var audio = item as Audio; if (audio != null) { - return new PlaylistItemFactory(_itemRepository).Create(audio, profile); + return new PlaylistItemFactory().Create(audio, mediaStreams, profile); } var photo = item as Photo; if (photo != null) { - return new PlaylistItemFactory(_itemRepository).Create(photo, profile); + return new PlaylistItemFactory().Create(photo, profile); } throw new ArgumentException("Unrecognized item type."); @@ -482,11 +546,18 @@ namespace MediaBrowser.Dlna.PlayTo await _device.SetStop(); return true; } + nextTrack.PlayState = 1; - _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, nextTrack.DlnaHeaders); - await _device.SetAvTransport(nextTrack.StreamUrl, nextTrack.DlnaHeaders, nextTrack.Didl); + + var dlnaheaders = GetDlnaHeaders(nextTrack); + + _logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", _device.Properties.Name, nextTrack.StreamUrl, dlnaheaders); + + await _device.SetAvTransport(nextTrack.StreamUrl, dlnaheaders, nextTrack.Didl); + if (nextTrack.StartPositionTicks > 0 && !nextTrack.Transcode) await _device.Seek(TimeSpan.FromTicks(nextTrack.StartPositionTicks)); + return true; } @@ -508,7 +579,7 @@ namespace MediaBrowser.Dlna.PlayTo return Task.FromResult(false); prevTrack.PlayState = 1; - return _device.SetAvTransport(prevTrack.StreamUrl, prevTrack.DlnaHeaders, prevTrack.Didl); + return _device.SetAvTransport(prevTrack.StreamUrl, GetDlnaHeaders(prevTrack), prevTrack.Didl); } #endregion diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs index 1304f61b11..77b9085f75 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs @@ -1,4 +1,5 @@ using MediaBrowser.Controller.Dlna; +using System.Collections.Generic; namespace MediaBrowser.Dlna.PlayTo { @@ -14,16 +15,27 @@ namespace MediaBrowser.Dlna.PlayTo public string Container { get; set; } - public string MimeType { get; set; } - public int PlayState { get; set; } public string StreamUrl { get; set; } - public string DlnaHeaders { get; set; } - public string Didl { get; set; } public long StartPositionTicks { get; set; } + + public string VideoCodec { get; set; } + + public string AudioCodec { get; set; } + + public List TranscodingSettings { get; set; } + + public int? AudioStreamIndex { get; set; } + + public int? SubtitleStreamIndex { get; set; } + + public PlaylistItem() + { + TranscodingSettings = new List(); + } } } \ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs index 5da845d068..8655e58da0 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs @@ -1,9 +1,9 @@ using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; @@ -12,15 +12,9 @@ namespace MediaBrowser.Dlna.PlayTo { public class PlaylistItemFactory { - private readonly IItemRepository _itemRepo; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public PlaylistItemFactory(IItemRepository itemRepo) - { - _itemRepo = itemRepo; - } - - public PlaylistItem Create(Audio item, DeviceProfile profile) + public PlaylistItem Create(Audio item, List mediaStreams, DeviceProfile profile) { var playlistItem = new PlaylistItem { @@ -28,12 +22,6 @@ namespace MediaBrowser.Dlna.PlayTo MediaType = DlnaProfileType.Audio }; - var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery - { - ItemId = item.Id, - Type = MediaStreamType.Audio - }); - var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); if (profile.CodecProfiles.Where(i => i.Type == CodecType.AudioCodec) @@ -57,11 +45,9 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; - + playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); } - - AttachMediaProfile(playlistItem, profile); return playlistItem; } @@ -91,16 +77,14 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; - + playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); } - - AttachMediaProfile(playlistItem, profile); return playlistItem; } - public PlaylistItem Create(Video item, DeviceProfile profile) + public PlaylistItem Create(Video item, List mediaStreams, DeviceProfile profile) { var playlistItem = new PlaylistItem { @@ -108,12 +92,6 @@ namespace MediaBrowser.Dlna.PlayTo MediaType = DlnaProfileType.Video }; - var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery - { - ItemId = item.Id - - }).ToList(); - var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio); var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); @@ -138,43 +116,13 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; + playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); } - AttachMediaProfile(playlistItem, profile); - return playlistItem; } - private void AttachMediaProfile(PlaylistItem item, DeviceProfile profile) - { - var mediaProfile = GetMediaProfile(item, profile); - - if (mediaProfile != null) - { - item.MimeType = (mediaProfile.MimeType ?? string.Empty).Split('/').LastOrDefault(); - - // TODO: Org_pn? - } - } - - private MediaProfile GetMediaProfile(PlaylistItem item, DeviceProfile profile) - { - return profile.MediaProfiles.FirstOrDefault(i => - { - if (i.Type == item.MediaType) - { - if (string.Equals(item.Container.TrimStart('.'), i.Container.TrimStart('.'), StringComparison.OrdinalIgnoreCase)) - { - // TODO: Enforce codecs - return true; - } - } - - return false; - }); - } - private bool IsSupported(DirectPlayProfile profile, Photo item) { var mediaPath = item.Path; diff --git a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs index cb2b72a038..2a8e2d6170 100644 --- a/MediaBrowser.Dlna/PlayTo/StreamHelper.cs +++ b/MediaBrowser.Dlna/PlayTo/StreamHelper.cs @@ -1,6 +1,5 @@ -using MediaBrowser.Model.Dto; +using MediaBrowser.Controller.Dlna; using MediaBrowser.Model.Entities; -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -9,91 +8,21 @@ namespace MediaBrowser.Dlna.PlayTo { class StreamHelper { - /// - /// Gets the dlna headers. - /// - /// The item. - /// - internal static string GetDlnaHeaders(PlaylistItem item) - { - var orgOp = item.Transcode ? ";DLNA.ORG_OP=00" : ";DLNA.ORG_OP=01"; - - var orgCi = item.Transcode ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1"; - - const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000"; - - var contentFeatures = string.Empty; - - if (string.Equals(item.Container, "mp3", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MP3"; - } - else if (string.Equals(item.Container, "wma", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=WMABASE"; - } - else if (string.Equals(item.Container, "wmw", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=WMVMED_BASE"; - } - else if (string.Equals(item.Container, "asf", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=WMVMED_BASE"; - } - else if (string.Equals(item.Container, "avi", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=AVI"; - } - else if (string.Equals(item.Container, "mkv", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MATROSKA"; - } - else if (string.Equals(item.Container, "mp4", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC"; - } - else if (string.Equals(item.Container, "mpeg", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; - } - else if (string.Equals(item.Container, "ts", StringComparison.OrdinalIgnoreCase)) - { - contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL"; - } - else if (item.MediaType == Controller.Dlna.DlnaProfileType.Video) - { - //Default to AVI for video - contentFeatures = "DLNA.ORG_PN=AVI"; - } - else - { - //Default to MP3 for audio - contentFeatures = "DLNA.ORG_PN=MP3"; - } - - return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); - } - - #region Audio - /// /// Gets the audio URL. /// + /// The device properties. /// The item. + /// The streams. /// The server address. /// System.String. - internal static string GetAudioUrl(PlaylistItem item, string serverAddress) + internal static string GetAudioUrl(DeviceInfo deviceProperties, PlaylistItem item, List streams, string serverAddress) { - if (!item.Transcode) - return string.Format("{0}/audio/{1}/stream{2}?Static=True", serverAddress, item.ItemId, item.Container); + var dlnaCommand = BuildDlnaUrl(item.MediaSourceId, deviceProperties.UUID, !item.Transcode, null, item.AudioCodec, item.AudioStreamIndex, item.SubtitleStreamIndex, null, 128000, item.StartPositionTicks, item.TranscodingSettings); - return string.Format("{0}/audio/{1}/stream.mp3?AudioCodec=Mp3", serverAddress, item.ItemId); + return string.Format("{0}/audio/{1}/stream{2}?{3}", serverAddress, item.ItemId, "." + item.Container.TrimStart('.'), dlnaCommand); } - #endregion - - #region Video - /// /// Gets the video URL. /// @@ -104,97 +33,40 @@ namespace MediaBrowser.Dlna.PlayTo /// The url to send to the device internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List streams, string serverAddress) { - string dlnaCommand = string.Empty; - if (!item.Transcode) - { - dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, null, null, null, null, null, null, null, null, null, null, item.MimeType); - return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.Container, dlnaCommand); - } - var videostream = streams.Where(m => m.Type == MediaStreamType.Video).OrderBy(m => m.IsDefault).FirstOrDefault(); - var audiostream = streams.Where(m => m.Type == MediaStreamType.Audio).OrderBy(m => m.IsDefault).FirstOrDefault(); + var dlnaCommand = BuildDlnaUrl(item.MediaSourceId, deviceProperties.UUID, !item.Transcode, item.VideoCodec, item.AudioCodec, item.AudioStreamIndex, item.SubtitleStreamIndex, 1500000, 128000, item.StartPositionTicks, item.TranscodingSettings); - var videoCodec = GetVideoCodec(videostream); - var audioCodec = GetAudioCodec(audiostream); - int? videoBitrate = null; - int? audioBitrate = null; - int? audioChannels = null; - - if (videoCodec != VideoCodecs.Copy) - videoBitrate = 2000000; - - if (audioCodec != AudioCodecs.Copy) - { - audioBitrate = 128000; - audioChannels = 2; - } - - dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, videoCodec, audioCodec, null, null, videoBitrate, audioChannels, audioBitrate, item.StartPositionTicks, "baseline", "3", item.MimeType); return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.Container, dlnaCommand); } - /// - /// Gets the video codec. - /// - /// The video stream. - /// - private static VideoCodecs GetVideoCodec(MediaStream videoStream) - { - switch (videoStream.Codec.ToLower()) - { - case "h264": - case "mpeg4": - return VideoCodecs.Copy; - - } - return VideoCodecs.H264; - } - - /// - /// Gets the audio codec. - /// - /// The audio stream. - /// - private static AudioCodecs GetAudioCodec(MediaStream audioStream) - { - if (audioStream != null) - { - switch (audioStream.Codec.ToLower()) - { - case "aac": - case "mp3": - case "wma": - return AudioCodecs.Copy; - - } - } - return AudioCodecs.Aac; - } - /// /// Builds the dlna URL. /// - private static string BuildDlnaUrl(string deviceID, bool isStatic, VideoCodecs? videoCodec, AudioCodecs? audioCodec, int? subtitleIndex, int? audiostreamIndex, int? videoBitrate, int? audiochannels, int? audioBitrate, long? startPositionTicks, string profile, string videoLevel, string mimeType) + private static string BuildDlnaUrl(string mediaSourceId, string deviceID, bool isStatic, string videoCodec, string audioCodec, int? audiostreamIndex, int? subtitleIndex, int? videoBitrate, int? audioBitrate, long? startPositionTicks, List settings) { + var profile = settings.Where(i => i.Name == TranscodingSettingType.VideoProfile).Select(i => i.Value).FirstOrDefault(); + var videoLevel = settings.Where(i => i.Name == TranscodingSettingType.VideoLevel).Select(i => i.Value).FirstOrDefault(); + var maxAudioChannels = settings.Where(i => i.Name == TranscodingSettingType.MaxAudioChannels).Select(i => i.Value).FirstOrDefault(); + var usCulture = new CultureInfo("en-US"); - var dlnaparam = string.Format("Params={0};", deviceID); - dlnaparam += isStatic ? "true;" : "false;"; - dlnaparam += videoCodec.HasValue ? videoCodec.Value + ";" : ";"; - dlnaparam += audioCodec.HasValue ? audioCodec.Value + ";" : ";"; - dlnaparam += audiostreamIndex.HasValue ? audiostreamIndex.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += subtitleIndex.HasValue ? subtitleIndex.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += videoBitrate.HasValue ? videoBitrate.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += audioBitrate.HasValue ? audioBitrate.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += audiochannels.HasValue ? audiochannels.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += startPositionTicks.HasValue ? startPositionTicks.Value.ToString(usCulture) + ";" : ";"; - dlnaparam += profile + ";"; - dlnaparam += videoLevel + ";"; - dlnaparam += mimeType + ";"; + var list = new List + { + deviceID ?? string.Empty, + mediaSourceId ?? string.Empty, + isStatic.ToString().ToLower(), + videoCodec ?? string.Empty, + audioCodec ?? string.Empty, + audiostreamIndex.HasValue ? audiostreamIndex.Value.ToString(usCulture) : string.Empty, + subtitleIndex.HasValue ? subtitleIndex.Value.ToString(usCulture) : string.Empty, + videoBitrate.HasValue ? videoBitrate.Value.ToString(usCulture) : string.Empty, + audioBitrate.HasValue ? audioBitrate.Value.ToString(usCulture) : string.Empty, + maxAudioChannels ?? string.Empty, + startPositionTicks.HasValue ? startPositionTicks.Value.ToString(usCulture) : string.Empty, + profile ?? string.Empty, + videoLevel ?? string.Empty + }; - return dlnaparam; + return string.Format("Params={0}", string.Join(";", list.ToArray())); } - - #endregion - } } \ No newline at end of file