|
@@ -1,6 +1,5 @@
|
|
-using MediaBrowser.Model.Dto;
|
|
|
|
|
|
+using MediaBrowser.Controller.Dlna;
|
|
using MediaBrowser.Model.Entities;
|
|
using MediaBrowser.Model.Entities;
|
|
-using System;
|
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
@@ -9,91 +8,21 @@ namespace MediaBrowser.Dlna.PlayTo
|
|
{
|
|
{
|
|
class StreamHelper
|
|
class StreamHelper
|
|
{
|
|
{
|
|
- /// <summary>
|
|
|
|
- /// Gets the dlna headers.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="item">The item.</param>
|
|
|
|
- /// <returns></returns>
|
|
|
|
- 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
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Gets the audio URL.
|
|
/// Gets the audio URL.
|
|
/// </summary>
|
|
/// </summary>
|
|
|
|
+ /// <param name="deviceProperties">The device properties.</param>
|
|
/// <param name="item">The item.</param>
|
|
/// <param name="item">The item.</param>
|
|
|
|
+ /// <param name="streams">The streams.</param>
|
|
/// <param name="serverAddress">The server address.</param>
|
|
/// <param name="serverAddress">The server address.</param>
|
|
/// <returns>System.String.</returns>
|
|
/// <returns>System.String.</returns>
|
|
- internal static string GetAudioUrl(PlaylistItem item, string serverAddress)
|
|
|
|
|
|
+ internal static string GetAudioUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> 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
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Gets the video URL.
|
|
/// Gets the video URL.
|
|
/// </summary>
|
|
/// </summary>
|
|
@@ -104,97 +33,40 @@ namespace MediaBrowser.Dlna.PlayTo
|
|
/// <returns>The url to send to the device</returns>
|
|
/// <returns>The url to send to the device</returns>
|
|
internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress)
|
|
internal static string GetVideoUrl(DeviceInfo deviceProperties, PlaylistItem item, List<MediaStream> 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 videoCodec = GetVideoCodec(videostream);
|
|
|
|
- var audioCodec = GetAudioCodec(audiostream);
|
|
|
|
- int? videoBitrate = null;
|
|
|
|
- int? audioBitrate = null;
|
|
|
|
- int? audioChannels = null;
|
|
|
|
-
|
|
|
|
- if (videoCodec != VideoCodecs.Copy)
|
|
|
|
- videoBitrate = 2000000;
|
|
|
|
|
|
+ var dlnaCommand = BuildDlnaUrl(item.MediaSourceId, deviceProperties.UUID, !item.Transcode, item.VideoCodec, item.AudioCodec, item.AudioStreamIndex, item.SubtitleStreamIndex, 1500000, 128000, item.StartPositionTicks, item.TranscodingSettings);
|
|
|
|
|
|
- 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);
|
|
return string.Format("{0}/Videos/{1}/stream{2}?{3}", serverAddress, item.ItemId, item.Container, dlnaCommand);
|
|
}
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
|
- /// Gets the video codec.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="videoStream">The video stream.</param>
|
|
|
|
- /// <returns></returns>
|
|
|
|
- private static VideoCodecs GetVideoCodec(MediaStream videoStream)
|
|
|
|
- {
|
|
|
|
- switch (videoStream.Codec.ToLower())
|
|
|
|
- {
|
|
|
|
- case "h264":
|
|
|
|
- case "mpeg4":
|
|
|
|
- return VideoCodecs.Copy;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- return VideoCodecs.H264;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// <summary>
|
|
|
|
- /// Gets the audio codec.
|
|
|
|
- /// </summary>
|
|
|
|
- /// <param name="audioStream">The audio stream.</param>
|
|
|
|
- /// <returns></returns>
|
|
|
|
- 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;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Builds the dlna URL.
|
|
/// Builds the dlna URL.
|
|
/// </summary>
|
|
/// </summary>
|
|
- 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<TranscodingSetting> settings)
|
|
{
|
|
{
|
|
- var usCulture = new CultureInfo("en-US");
|
|
|
|
|
|
+ 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 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 usCulture = new CultureInfo("en-US");
|
|
|
|
|
|
- return dlnaparam;
|
|
|
|
|
|
+ var list = new List<string>
|
|
|
|
+ {
|
|
|
|
+ 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 string.Format("Params={0}", string.Join(";", list.ToArray()));
|
|
}
|
|
}
|
|
-
|
|
|
|
- #endregion
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|