StreamInfo.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. using MediaBrowser.Model.Drawing;
  2. using MediaBrowser.Model.Dto;
  3. using MediaBrowser.Model.Entities;
  4. using MediaBrowser.Model.MediaInfo;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Globalization;
  8. namespace MediaBrowser.Model.Dlna
  9. {
  10. /// <summary>
  11. /// Class StreamInfo.
  12. /// </summary>
  13. public class StreamInfo
  14. {
  15. public string ItemId { get; set; }
  16. public bool IsDirectStream { get; set; }
  17. public DlnaProfileType MediaType { get; set; }
  18. public string Container { get; set; }
  19. public string Protocol { get; set; }
  20. public long StartPositionTicks { get; set; }
  21. public string VideoCodec { get; set; }
  22. public string VideoProfile { get; set; }
  23. public string AudioCodec { get; set; }
  24. public int? AudioStreamIndex { get; set; }
  25. public int? SubtitleStreamIndex { get; set; }
  26. public int? MaxAudioChannels { get; set; }
  27. public int? AudioBitrate { get; set; }
  28. public int? VideoBitrate { get; set; }
  29. public int? VideoLevel { get; set; }
  30. public int? MaxWidth { get; set; }
  31. public int? MaxHeight { get; set; }
  32. public int? MaxFramerate { get; set; }
  33. public string DeviceProfileId { get; set; }
  34. public string DeviceId { get; set; }
  35. public long? RunTimeTicks { get; set; }
  36. public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
  37. public bool EstimateContentLength { get; set; }
  38. public MediaSourceInfo MediaSource { get; set; }
  39. public string MediaSourceId
  40. {
  41. get
  42. {
  43. return MediaSource == null ? null : MediaSource.Id;
  44. }
  45. }
  46. public string ToUrl(string baseUrl)
  47. {
  48. return ToDlnaUrl(baseUrl);
  49. }
  50. public string ToDlnaUrl(string baseUrl)
  51. {
  52. if (string.IsNullOrEmpty(baseUrl))
  53. {
  54. throw new ArgumentNullException(baseUrl);
  55. }
  56. string dlnaCommand = BuildDlnaParam(this);
  57. string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
  58. baseUrl = baseUrl.TrimEnd('/');
  59. if (MediaType == DlnaProfileType.Audio)
  60. {
  61. return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
  62. }
  63. if (string.Equals(Protocol, "hls", StringComparison.OrdinalIgnoreCase))
  64. {
  65. return string.Format("{0}/videos/{1}/stream.m3u8?{2}", baseUrl, ItemId, dlnaCommand);
  66. }
  67. return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
  68. }
  69. private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
  70. private static string BuildDlnaParam(StreamInfo item)
  71. {
  72. List<string> list = new List<string>
  73. {
  74. item.DeviceProfileId ?? string.Empty,
  75. item.DeviceId ?? string.Empty,
  76. item.MediaSourceId ?? string.Empty,
  77. (item.IsDirectStream).ToString().ToLower(),
  78. item.VideoCodec ?? string.Empty,
  79. item.AudioCodec ?? string.Empty,
  80. item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(UsCulture) : string.Empty,
  81. item.SubtitleStreamIndex.HasValue ? item.SubtitleStreamIndex.Value.ToString(UsCulture) : string.Empty,
  82. item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(UsCulture) : string.Empty,
  83. item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(UsCulture) : string.Empty,
  84. item.MaxAudioChannels.HasValue ? item.MaxAudioChannels.Value.ToString(UsCulture) : string.Empty,
  85. item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(UsCulture) : string.Empty,
  86. item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(UsCulture) : string.Empty,
  87. item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(UsCulture) : string.Empty,
  88. item.StartPositionTicks.ToString(UsCulture),
  89. item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(UsCulture) : string.Empty
  90. };
  91. return string.Format("Params={0}", string.Join(";", list.ToArray()));
  92. }
  93. /// <summary>
  94. /// Returns the audio stream that will be used
  95. /// </summary>
  96. public MediaStream TargetAudioStream
  97. {
  98. get
  99. {
  100. if (MediaSource != null)
  101. {
  102. if (AudioStreamIndex.HasValue)
  103. {
  104. foreach (MediaStream i in MediaSource.MediaStreams)
  105. {
  106. if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio)
  107. return i;
  108. }
  109. return null;
  110. }
  111. return MediaSource.DefaultAudioStream;
  112. }
  113. return null;
  114. }
  115. }
  116. /// <summary>
  117. /// Returns the video stream that will be used
  118. /// </summary>
  119. public MediaStream TargetVideoStream
  120. {
  121. get
  122. {
  123. if (MediaSource != null)
  124. {
  125. return MediaSource.VideoStream;
  126. }
  127. return null;
  128. }
  129. }
  130. /// <summary>
  131. /// Predicts the audio sample rate that will be in the output stream
  132. /// </summary>
  133. public int? TargetAudioSampleRate
  134. {
  135. get
  136. {
  137. MediaStream stream = TargetAudioStream;
  138. return stream == null ? null : stream.SampleRate;
  139. }
  140. }
  141. /// <summary>
  142. /// Predicts the audio sample rate that will be in the output stream
  143. /// </summary>
  144. public int? TargetVideoBitDepth
  145. {
  146. get
  147. {
  148. MediaStream stream = TargetVideoStream;
  149. return stream == null || !IsDirectStream ? null : stream.BitDepth;
  150. }
  151. }
  152. /// <summary>
  153. /// Predicts the audio sample rate that will be in the output stream
  154. /// </summary>
  155. public double? TargetFramerate
  156. {
  157. get
  158. {
  159. MediaStream stream = TargetVideoStream;
  160. return MaxFramerate.HasValue && !IsDirectStream
  161. ? MaxFramerate
  162. : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
  163. }
  164. }
  165. /// <summary>
  166. /// Predicts the audio sample rate that will be in the output stream
  167. /// </summary>
  168. public double? TargetVideoLevel
  169. {
  170. get
  171. {
  172. MediaStream stream = TargetVideoStream;
  173. return VideoLevel.HasValue && !IsDirectStream
  174. ? VideoLevel
  175. : stream == null ? null : stream.Level;
  176. }
  177. }
  178. /// <summary>
  179. /// Predicts the audio sample rate that will be in the output stream
  180. /// </summary>
  181. public int? TargetPacketLength
  182. {
  183. get
  184. {
  185. MediaStream stream = TargetVideoStream;
  186. return !IsDirectStream
  187. ? null
  188. : stream == null ? null : stream.PacketLength;
  189. }
  190. }
  191. /// <summary>
  192. /// Predicts the audio sample rate that will be in the output stream
  193. /// </summary>
  194. public string TargetVideoProfile
  195. {
  196. get
  197. {
  198. MediaStream stream = TargetVideoStream;
  199. return !string.IsNullOrEmpty(VideoProfile) && !IsDirectStream
  200. ? VideoProfile
  201. : stream == null ? null : stream.Profile;
  202. }
  203. }
  204. /// <summary>
  205. /// Predicts the audio bitrate that will be in the output stream
  206. /// </summary>
  207. public int? TargetAudioBitrate
  208. {
  209. get
  210. {
  211. MediaStream stream = TargetAudioStream;
  212. return AudioBitrate.HasValue && !IsDirectStream
  213. ? AudioBitrate
  214. : stream == null ? null : stream.BitRate;
  215. }
  216. }
  217. /// <summary>
  218. /// Predicts the audio channels that will be in the output stream
  219. /// </summary>
  220. public int? TargetAudioChannels
  221. {
  222. get
  223. {
  224. MediaStream stream = TargetAudioStream;
  225. int? streamChannels = stream == null ? null : stream.Channels;
  226. return MaxAudioChannels.HasValue && !IsDirectStream
  227. ? (streamChannels.HasValue ? Math.Min(MaxAudioChannels.Value, streamChannels.Value) : MaxAudioChannels.Value)
  228. : stream == null ? null : streamChannels;
  229. }
  230. }
  231. /// <summary>
  232. /// Predicts the audio codec that will be in the output stream
  233. /// </summary>
  234. public string TargetAudioCodec
  235. {
  236. get
  237. {
  238. MediaStream stream = TargetAudioStream;
  239. return IsDirectStream
  240. ? (stream == null ? null : stream.Codec)
  241. : AudioCodec;
  242. }
  243. }
  244. /// <summary>
  245. /// Predicts the audio channels that will be in the output stream
  246. /// </summary>
  247. public long? TargetSize
  248. {
  249. get
  250. {
  251. if (IsDirectStream)
  252. {
  253. return MediaSource.Size;
  254. }
  255. if (RunTimeTicks.HasValue)
  256. {
  257. int? totalBitrate = TargetTotalBitrate;
  258. return totalBitrate.HasValue ?
  259. Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
  260. (long?)null;
  261. }
  262. return null;
  263. }
  264. }
  265. public int? TargetVideoBitrate
  266. {
  267. get
  268. {
  269. MediaStream stream = TargetVideoStream;
  270. return VideoBitrate.HasValue && !IsDirectStream
  271. ? VideoBitrate
  272. : stream == null ? null : stream.BitRate;
  273. }
  274. }
  275. public TransportStreamTimestamp TargetTimestamp
  276. {
  277. get
  278. {
  279. TransportStreamTimestamp defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase)
  280. ? TransportStreamTimestamp.Valid
  281. : TransportStreamTimestamp.None;
  282. return !IsDirectStream
  283. ? defaultValue
  284. : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
  285. }
  286. }
  287. public int? TargetTotalBitrate
  288. {
  289. get
  290. {
  291. return (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0);
  292. }
  293. }
  294. public int? TargetWidth
  295. {
  296. get
  297. {
  298. MediaStream videoStream = TargetVideoStream;
  299. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  300. {
  301. ImageSize size = new ImageSize
  302. {
  303. Width = videoStream.Width.Value,
  304. Height = videoStream.Height.Value
  305. };
  306. ImageSize newSize = DrawingUtils.Resize(size,
  307. null,
  308. null,
  309. MaxWidth,
  310. MaxHeight);
  311. return Convert.ToInt32(newSize.Width);
  312. }
  313. return MaxWidth;
  314. }
  315. }
  316. public int? TargetHeight
  317. {
  318. get
  319. {
  320. MediaStream videoStream = TargetVideoStream;
  321. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  322. {
  323. ImageSize size = new ImageSize
  324. {
  325. Width = videoStream.Width.Value,
  326. Height = videoStream.Height.Value
  327. };
  328. ImageSize newSize = DrawingUtils.Resize(size,
  329. null,
  330. null,
  331. MaxWidth,
  332. MaxHeight);
  333. return Convert.ToInt32(newSize.Height);
  334. }
  335. return MaxHeight;
  336. }
  337. }
  338. }
  339. }