StreamHelper.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. using MediaBrowser.Model.Dto;
  2. using MediaBrowser.Model.Entities;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.Linq;
  7. namespace MediaBrowser.Dlna.PlayTo
  8. {
  9. class StreamHelper
  10. {
  11. /// <summary>
  12. /// Gets the dlna headers.
  13. /// </summary>
  14. /// <param name="item">The item.</param>
  15. /// <returns></returns>
  16. internal static string GetDlnaHeaders(PlaylistItem item)
  17. {
  18. var orgOp = item.Transcode ? ";DLNA.ORG_OP=00" : ";DLNA.ORG_OP=01";
  19. var orgCi = item.Transcode ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
  20. const string dlnaflags = ";DLNA.ORG_FLAGS=01500000000000000000000000000000";
  21. var contentFeatures = string.Empty;
  22. if (string.Equals(item.FileFormat, "mp3", StringComparison.OrdinalIgnoreCase))
  23. {
  24. contentFeatures = "DLNA.ORG_PN=MP3";
  25. }
  26. else if (string.Equals(item.FileFormat, "wma", StringComparison.OrdinalIgnoreCase))
  27. {
  28. contentFeatures = "DLNA.ORG_PN=WMABASE";
  29. }
  30. else if (string.Equals(item.FileFormat, "avi", StringComparison.OrdinalIgnoreCase))
  31. {
  32. contentFeatures = "DLNA.ORG_PN=AVI";
  33. }
  34. else if (string.Equals(item.FileFormat, "mkv", StringComparison.OrdinalIgnoreCase))
  35. {
  36. contentFeatures = "DLNA.ORG_PN=MATROSKA";
  37. }
  38. else if (string.Equals(item.FileFormat, "mp4", StringComparison.OrdinalIgnoreCase))
  39. {
  40. contentFeatures = "DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC";
  41. }
  42. else if (string.Equals(item.FileFormat, "mpeg", StringComparison.OrdinalIgnoreCase))
  43. {
  44. contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
  45. }
  46. else if (string.Equals(item.FileFormat, "ts", StringComparison.OrdinalIgnoreCase))
  47. {
  48. contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
  49. }
  50. else if (item.IsVideo)
  51. {
  52. //Default to AVI for video
  53. contentFeatures = "DLNA.ORG_PN=AVI";
  54. }
  55. else
  56. {
  57. //Default to MP3 for audio
  58. contentFeatures = "DLNA.ORG_PN=MP3";
  59. }
  60. return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
  61. }
  62. #region Audio
  63. /// <summary>
  64. /// Gets the audio URL.
  65. /// </summary>
  66. /// <param name="item">The item.</param>
  67. /// <param name="serverAddress">The server address.</param>
  68. /// <returns>System.String.</returns>
  69. internal static string GetAudioUrl(PlaylistItem item, string serverAddress)
  70. {
  71. if (!item.Transcode)
  72. return string.Format("{0}/audio/{1}/stream.{2}?Static=True", serverAddress, item.ItemId, item.FileFormat);
  73. return string.Format("{0}/audio/{1}/stream.mp3?AudioCodec=Mp3", serverAddress, item.ItemId);
  74. }
  75. #endregion
  76. #region Video
  77. /// <summary>
  78. /// Gets the video URL.
  79. /// </summary>
  80. /// <param name="deviceProperties">The device properties.</param>
  81. /// <param name="item">The item.</param>
  82. /// <param name="streams">The streams.</param>
  83. /// <param name="serverAddress">The server address.</param>
  84. /// <returns>The url to send to the device</returns>
  85. internal static string GetVideoUrl(DeviceProperties deviceProperties, PlaylistItem item, List<MediaStream> streams, string serverAddress)
  86. {
  87. string dlnaCommand = string.Empty;
  88. if (!item.Transcode)
  89. {
  90. dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, null, null, null, null, null, null, null, null, null, null, item.MimeType);
  91. return string.Format("{0}/Videos/{1}/stream.{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand);
  92. }
  93. var videostream = streams.Where(m => m.Type == MediaStreamType.Video).OrderBy(m => m.IsDefault).FirstOrDefault();
  94. var audiostream = streams.Where(m => m.Type == MediaStreamType.Audio).OrderBy(m => m.IsDefault).FirstOrDefault();
  95. var videoCodec = GetVideoCodec(videostream);
  96. var audioCodec = GetAudioCodec(audiostream);
  97. int? videoBitrate = null;
  98. int? audioBitrate = null;
  99. int? audioChannels = null;
  100. if (videoCodec != VideoCodecs.Copy)
  101. videoBitrate = 2000000;
  102. if (audioCodec != AudioCodecs.Copy)
  103. {
  104. audioBitrate = 128000;
  105. audioChannels = 2;
  106. }
  107. dlnaCommand = BuildDlnaUrl(deviceProperties.UUID, !item.Transcode, videoCodec, audioCodec, null, null, videoBitrate, audioChannels, audioBitrate, item.StartPositionTicks, "baseline", "3", item.MimeType);
  108. return string.Format("{0}/Videos/{1}/stream.{2}?{3}", serverAddress, item.ItemId, item.FileFormat, dlnaCommand);
  109. }
  110. /// <summary>
  111. /// Gets the video codec.
  112. /// </summary>
  113. /// <param name="videoStream">The video stream.</param>
  114. /// <returns></returns>
  115. private static VideoCodecs GetVideoCodec(MediaStream videoStream)
  116. {
  117. switch (videoStream.Codec.ToLower())
  118. {
  119. case "h264":
  120. case "mpeg4":
  121. return VideoCodecs.Copy;
  122. }
  123. return VideoCodecs.H264;
  124. }
  125. /// <summary>
  126. /// Gets the audio codec.
  127. /// </summary>
  128. /// <param name="audioStream">The audio stream.</param>
  129. /// <returns></returns>
  130. private static AudioCodecs GetAudioCodec(MediaStream audioStream)
  131. {
  132. if (audioStream != null)
  133. {
  134. switch (audioStream.Codec.ToLower())
  135. {
  136. case "aac":
  137. case "mp3":
  138. case "wma":
  139. return AudioCodecs.Copy;
  140. }
  141. }
  142. return AudioCodecs.Aac;
  143. }
  144. /// <summary>
  145. /// Builds the dlna URL.
  146. /// </summary>
  147. 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)
  148. {
  149. var usCulture = new CultureInfo("en-US");
  150. var dlnaparam = string.Format("Params={0};", deviceID);
  151. dlnaparam += isStatic ? "true;" : "false;";
  152. dlnaparam += videoCodec.HasValue ? videoCodec.Value + ";" : ";";
  153. dlnaparam += audioCodec.HasValue ? audioCodec.Value + ";" : ";";
  154. dlnaparam += audiostreamIndex.HasValue ? audiostreamIndex.Value.ToString(usCulture) + ";" : ";";
  155. dlnaparam += subtitleIndex.HasValue ? subtitleIndex.Value.ToString(usCulture) + ";" : ";";
  156. dlnaparam += videoBitrate.HasValue ? videoBitrate.Value.ToString(usCulture) + ";" : ";";
  157. dlnaparam += audioBitrate.HasValue ? audioBitrate.Value.ToString(usCulture) + ";" : ";";
  158. dlnaparam += audiochannels.HasValue ? audiochannels.Value.ToString(usCulture) + ";" : ";";
  159. dlnaparam += startPositionTicks.HasValue ? startPositionTicks.Value.ToString(usCulture) + ";" : ";";
  160. dlnaparam += profile + ";";
  161. dlnaparam += videoLevel + ";";
  162. dlnaparam += mimeType + ";";
  163. return dlnaparam;
  164. }
  165. #endregion
  166. }
  167. }