StreamInfo.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using MediaBrowser.Model.Drawing;
  2. using MediaBrowser.Model.Dto;
  3. using MediaBrowser.Model.Entities;
  4. using MediaBrowser.Model.Extensions;
  5. using MediaBrowser.Model.MediaInfo;
  6. using System;
  7. using System.Collections.Generic;
  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 float? 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 (StringHelper.EqualsIgnoreCase(Protocol, "hls"))
  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 string BuildDlnaParam(StreamInfo item)
  70. {
  71. List<string> list = new List<string>
  72. {
  73. item.DeviceProfileId ?? string.Empty,
  74. item.DeviceId ?? string.Empty,
  75. item.MediaSourceId ?? string.Empty,
  76. (item.IsDirectStream).ToString().ToLower(),
  77. item.VideoCodec ?? string.Empty,
  78. item.AudioCodec ?? string.Empty,
  79. item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty,
  80. item.SubtitleStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty,
  81. item.VideoBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoBitrate.Value) : string.Empty,
  82. item.AudioBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioBitrate.Value) : string.Empty,
  83. item.MaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxAudioChannels.Value) : string.Empty,
  84. item.MaxFramerate.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxFramerate.Value) : string.Empty,
  85. item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty,
  86. item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty,
  87. StringHelper.ToStringCultureInvariant(item.StartPositionTicks),
  88. item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty
  89. };
  90. return string.Format("Params={0}", string.Join(";", list.ToArray()));
  91. }
  92. /// <summary>
  93. /// Returns the audio stream that will be used
  94. /// </summary>
  95. public MediaStream TargetAudioStream
  96. {
  97. get
  98. {
  99. if (MediaSource != null)
  100. {
  101. if (AudioStreamIndex.HasValue)
  102. {
  103. foreach (MediaStream i in MediaSource.MediaStreams)
  104. {
  105. if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio)
  106. return i;
  107. }
  108. return null;
  109. }
  110. return MediaSource.DefaultAudioStream;
  111. }
  112. return null;
  113. }
  114. }
  115. /// <summary>
  116. /// Returns the video stream that will be used
  117. /// </summary>
  118. public MediaStream TargetVideoStream
  119. {
  120. get
  121. {
  122. if (MediaSource != null)
  123. {
  124. return MediaSource.VideoStream;
  125. }
  126. return null;
  127. }
  128. }
  129. /// <summary>
  130. /// Predicts the audio sample rate that will be in the output stream
  131. /// </summary>
  132. public int? TargetAudioSampleRate
  133. {
  134. get
  135. {
  136. MediaStream stream = TargetAudioStream;
  137. return stream == null ? null : stream.SampleRate;
  138. }
  139. }
  140. /// <summary>
  141. /// Predicts the audio sample rate that will be in the output stream
  142. /// </summary>
  143. public int? TargetVideoBitDepth
  144. {
  145. get
  146. {
  147. MediaStream stream = TargetVideoStream;
  148. return stream == null || !IsDirectStream ? null : stream.BitDepth;
  149. }
  150. }
  151. /// <summary>
  152. /// Predicts the audio sample rate that will be in the output stream
  153. /// </summary>
  154. public float? TargetFramerate
  155. {
  156. get
  157. {
  158. MediaStream stream = TargetVideoStream;
  159. return MaxFramerate.HasValue && !IsDirectStream
  160. ? MaxFramerate
  161. : stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
  162. }
  163. }
  164. /// <summary>
  165. /// Predicts the audio sample rate that will be in the output stream
  166. /// </summary>
  167. public double? TargetVideoLevel
  168. {
  169. get
  170. {
  171. MediaStream stream = TargetVideoStream;
  172. return VideoLevel.HasValue && !IsDirectStream
  173. ? VideoLevel
  174. : stream == null ? null : stream.Level;
  175. }
  176. }
  177. /// <summary>
  178. /// Predicts the audio sample rate that will be in the output stream
  179. /// </summary>
  180. public int? TargetPacketLength
  181. {
  182. get
  183. {
  184. MediaStream stream = TargetVideoStream;
  185. return !IsDirectStream
  186. ? null
  187. : stream == null ? null : stream.PacketLength;
  188. }
  189. }
  190. /// <summary>
  191. /// Predicts the audio sample rate that will be in the output stream
  192. /// </summary>
  193. public string TargetVideoProfile
  194. {
  195. get
  196. {
  197. MediaStream stream = TargetVideoStream;
  198. return !string.IsNullOrEmpty(VideoProfile) && !IsDirectStream
  199. ? VideoProfile
  200. : stream == null ? null : stream.Profile;
  201. }
  202. }
  203. /// <summary>
  204. /// Predicts the audio bitrate that will be in the output stream
  205. /// </summary>
  206. public int? TargetAudioBitrate
  207. {
  208. get
  209. {
  210. MediaStream stream = TargetAudioStream;
  211. return AudioBitrate.HasValue && !IsDirectStream
  212. ? AudioBitrate
  213. : stream == null ? null : stream.BitRate;
  214. }
  215. }
  216. /// <summary>
  217. /// Predicts the audio channels that will be in the output stream
  218. /// </summary>
  219. public int? TargetAudioChannels
  220. {
  221. get
  222. {
  223. MediaStream stream = TargetAudioStream;
  224. int? streamChannels = stream == null ? null : stream.Channels;
  225. return MaxAudioChannels.HasValue && !IsDirectStream
  226. ? (streamChannels.HasValue ? Math.Min(MaxAudioChannels.Value, streamChannels.Value) : MaxAudioChannels.Value)
  227. : stream == null ? null : streamChannels;
  228. }
  229. }
  230. /// <summary>
  231. /// Predicts the audio codec that will be in the output stream
  232. /// </summary>
  233. public string TargetAudioCodec
  234. {
  235. get
  236. {
  237. MediaStream stream = TargetAudioStream;
  238. return IsDirectStream
  239. ? (stream == null ? null : stream.Codec)
  240. : AudioCodec;
  241. }
  242. }
  243. /// <summary>
  244. /// Predicts the audio channels that will be in the output stream
  245. /// </summary>
  246. public long? TargetSize
  247. {
  248. get
  249. {
  250. if (IsDirectStream)
  251. {
  252. return MediaSource.Size;
  253. }
  254. if (RunTimeTicks.HasValue)
  255. {
  256. int? totalBitrate = TargetTotalBitrate;
  257. return totalBitrate.HasValue ?
  258. Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
  259. (long?)null;
  260. }
  261. return null;
  262. }
  263. }
  264. public int? TargetVideoBitrate
  265. {
  266. get
  267. {
  268. MediaStream stream = TargetVideoStream;
  269. return VideoBitrate.HasValue && !IsDirectStream
  270. ? VideoBitrate
  271. : stream == null ? null : stream.BitRate;
  272. }
  273. }
  274. public TransportStreamTimestamp TargetTimestamp
  275. {
  276. get
  277. {
  278. TransportStreamTimestamp defaultValue = StringHelper.EqualsIgnoreCase(Container, "m2ts")
  279. ? TransportStreamTimestamp.Valid
  280. : TransportStreamTimestamp.None;
  281. return !IsDirectStream
  282. ? defaultValue
  283. : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
  284. }
  285. }
  286. public int? TargetTotalBitrate
  287. {
  288. get
  289. {
  290. return (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0);
  291. }
  292. }
  293. public bool? IsTargetAnamorphic
  294. {
  295. get
  296. {
  297. if (IsDirectStream)
  298. {
  299. return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic;
  300. }
  301. return false;
  302. }
  303. }
  304. public int? TargetWidth
  305. {
  306. get
  307. {
  308. MediaStream videoStream = TargetVideoStream;
  309. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  310. {
  311. ImageSize size = new ImageSize
  312. {
  313. Width = videoStream.Width.Value,
  314. Height = videoStream.Height.Value
  315. };
  316. ImageSize newSize = DrawingUtils.Resize(size,
  317. null,
  318. null,
  319. MaxWidth,
  320. MaxHeight);
  321. return Convert.ToInt32(newSize.Width);
  322. }
  323. return MaxWidth;
  324. }
  325. }
  326. public int? TargetHeight
  327. {
  328. get
  329. {
  330. MediaStream videoStream = TargetVideoStream;
  331. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  332. {
  333. ImageSize size = new ImageSize
  334. {
  335. Width = videoStream.Width.Value,
  336. Height = videoStream.Height.Value
  337. };
  338. ImageSize newSize = DrawingUtils.Resize(size,
  339. null,
  340. null,
  341. MaxWidth,
  342. MaxHeight);
  343. return Convert.ToInt32(newSize.Height);
  344. }
  345. return MaxHeight;
  346. }
  347. }
  348. }
  349. }