StreamInfo.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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 SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; }
  40. public string MediaSourceId
  41. {
  42. get
  43. {
  44. return MediaSource == null ? null : MediaSource.Id;
  45. }
  46. }
  47. public string ToUrl(string baseUrl)
  48. {
  49. return ToDlnaUrl(baseUrl);
  50. }
  51. public string ToDlnaUrl(string baseUrl)
  52. {
  53. if (string.IsNullOrEmpty(baseUrl))
  54. {
  55. throw new ArgumentNullException(baseUrl);
  56. }
  57. string dlnaCommand = BuildDlnaParam(this);
  58. string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
  59. baseUrl = baseUrl.TrimEnd('/');
  60. if (MediaType == DlnaProfileType.Audio)
  61. {
  62. return string.Format("{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
  63. }
  64. if (StringHelper.EqualsIgnoreCase(Protocol, "hls"))
  65. {
  66. return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, dlnaCommand);
  67. }
  68. return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
  69. }
  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 ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty,
  81. item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty,
  82. item.VideoBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoBitrate.Value) : string.Empty,
  83. item.AudioBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioBitrate.Value) : string.Empty,
  84. item.MaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxAudioChannels.Value) : string.Empty,
  85. item.MaxFramerate.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxFramerate.Value) : string.Empty,
  86. item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty,
  87. item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty,
  88. StringHelper.ToStringCultureInvariant(item.StartPositionTicks),
  89. item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : 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 float? 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. double totalSeconds = RunTimeTicks.Value;
  259. // Convert to ms
  260. totalSeconds /= 10000;
  261. // Convert to seconds
  262. totalSeconds /= 1000;
  263. return totalBitrate.HasValue ?
  264. Convert.ToInt64(totalBitrate.Value * totalSeconds) :
  265. (long?)null;
  266. }
  267. return null;
  268. }
  269. }
  270. public int? TargetVideoBitrate
  271. {
  272. get
  273. {
  274. MediaStream stream = TargetVideoStream;
  275. return VideoBitrate.HasValue && !IsDirectStream
  276. ? VideoBitrate
  277. : stream == null ? null : stream.BitRate;
  278. }
  279. }
  280. public TransportStreamTimestamp TargetTimestamp
  281. {
  282. get
  283. {
  284. TransportStreamTimestamp defaultValue = StringHelper.EqualsIgnoreCase(Container, "m2ts")
  285. ? TransportStreamTimestamp.Valid
  286. : TransportStreamTimestamp.None;
  287. return !IsDirectStream
  288. ? defaultValue
  289. : MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
  290. }
  291. }
  292. public int? TargetTotalBitrate
  293. {
  294. get
  295. {
  296. return (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0);
  297. }
  298. }
  299. public bool? IsTargetAnamorphic
  300. {
  301. get
  302. {
  303. if (IsDirectStream)
  304. {
  305. return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic;
  306. }
  307. return false;
  308. }
  309. }
  310. public int? TargetWidth
  311. {
  312. get
  313. {
  314. MediaStream videoStream = TargetVideoStream;
  315. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  316. {
  317. ImageSize size = new ImageSize
  318. {
  319. Width = videoStream.Width.Value,
  320. Height = videoStream.Height.Value
  321. };
  322. double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
  323. double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
  324. ImageSize newSize = DrawingUtils.Resize(size,
  325. null,
  326. null,
  327. maxWidth,
  328. maxHeight);
  329. return Convert.ToInt32(newSize.Width);
  330. }
  331. return MaxWidth;
  332. }
  333. }
  334. public int? TargetHeight
  335. {
  336. get
  337. {
  338. MediaStream videoStream = TargetVideoStream;
  339. if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
  340. {
  341. ImageSize size = new ImageSize
  342. {
  343. Width = videoStream.Width.Value,
  344. Height = videoStream.Height.Value
  345. };
  346. double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
  347. double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
  348. ImageSize newSize = DrawingUtils.Resize(size,
  349. null,
  350. null,
  351. maxWidth,
  352. maxHeight);
  353. return Convert.ToInt32(newSize.Height);
  354. }
  355. return MaxHeight;
  356. }
  357. }
  358. }
  359. public enum SubtitleDeliveryMethod
  360. {
  361. /// <summary>
  362. /// The encode
  363. /// </summary>
  364. Encode = 0,
  365. /// <summary>
  366. /// Internal format is supported natively
  367. /// </summary>
  368. Direct = 1,
  369. /// <summary>
  370. /// The embed
  371. /// </summary>
  372. Embed = 2,
  373. /// <summary>
  374. /// The external
  375. /// </summary>
  376. External = 3
  377. }
  378. }