ContentFeatureBuilder.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #nullable disable
  2. #pragma warning disable CS1591
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using MediaBrowser.Model.MediaInfo;
  7. namespace MediaBrowser.Model.Dlna
  8. {
  9. public class ContentFeatureBuilder
  10. {
  11. private readonly DeviceProfile _profile;
  12. public ContentFeatureBuilder(DeviceProfile profile)
  13. {
  14. _profile = profile;
  15. }
  16. public string BuildImageHeader(
  17. string container,
  18. int? width,
  19. int? height,
  20. bool isDirectStream,
  21. string orgPn = null)
  22. {
  23. string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();
  24. // 0 = native, 1 = transcoded
  25. var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
  26. var flagValue = DlnaFlags.BackgroundTransferMode |
  27. DlnaFlags.InteractiveTransferMode |
  28. DlnaFlags.DlnaV15;
  29. string dlnaflags = string.Format(
  30. CultureInfo.InvariantCulture,
  31. ";DLNA.ORG_FLAGS={0}",
  32. DlnaMaps.FlagsToString(flagValue));
  33. ResponseProfile mediaProfile = _profile.GetImageMediaProfile(
  34. container,
  35. width,
  36. height);
  37. if (string.IsNullOrEmpty(orgPn))
  38. {
  39. orgPn = mediaProfile?.OrgPn;
  40. }
  41. if (string.IsNullOrEmpty(orgPn))
  42. {
  43. orgPn = GetImageOrgPnValue(container, width, height);
  44. }
  45. string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
  46. return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
  47. }
  48. public string BuildAudioHeader(
  49. string container,
  50. string audioCodec,
  51. int? audioBitrate,
  52. int? audioSampleRate,
  53. int? audioChannels,
  54. int? audioBitDepth,
  55. bool isDirectStream,
  56. long? runtimeTicks,
  57. TranscodeSeekInfo transcodeSeekInfo)
  58. {
  59. // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
  60. string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);
  61. // 0 = native, 1 = transcoded
  62. string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
  63. var flagValue = DlnaFlags.StreamingTransferMode |
  64. DlnaFlags.BackgroundTransferMode |
  65. DlnaFlags.InteractiveTransferMode |
  66. DlnaFlags.DlnaV15;
  67. // if (isDirectStream)
  68. //{
  69. // flagValue = flagValue | DlnaFlags.ByteBasedSeek;
  70. //}
  71. // else if (runtimeTicks.HasValue)
  72. //{
  73. // flagValue = flagValue | DlnaFlags.TimeBasedSeek;
  74. //}
  75. string dlnaflags = string.Format(
  76. CultureInfo.InvariantCulture,
  77. ";DLNA.ORG_FLAGS={0}",
  78. DlnaMaps.FlagsToString(flagValue));
  79. ResponseProfile mediaProfile = _profile.GetAudioMediaProfile(
  80. container,
  81. audioCodec,
  82. audioChannels,
  83. audioBitrate,
  84. audioSampleRate,
  85. audioBitDepth);
  86. string orgPn = mediaProfile?.OrgPn;
  87. if (string.IsNullOrEmpty(orgPn))
  88. {
  89. orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels);
  90. }
  91. string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
  92. return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
  93. }
  94. public List<string> BuildVideoHeader(
  95. string container,
  96. string videoCodec,
  97. string audioCodec,
  98. int? width,
  99. int? height,
  100. int? bitDepth,
  101. int? videoBitrate,
  102. TransportStreamTimestamp timestamp,
  103. bool isDirectStream,
  104. long? runtimeTicks,
  105. string videoProfile,
  106. double? videoLevel,
  107. float? videoFramerate,
  108. int? packetLength,
  109. TranscodeSeekInfo transcodeSeekInfo,
  110. bool? isAnamorphic,
  111. bool? isInterlaced,
  112. int? refFrames,
  113. int? numVideoStreams,
  114. int? numAudioStreams,
  115. string videoCodecTag,
  116. bool? isAvc)
  117. {
  118. // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
  119. string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks > 0, isDirectStream, transcodeSeekInfo);
  120. // 0 = native, 1 = transcoded
  121. string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
  122. var flagValue = DlnaFlags.StreamingTransferMode |
  123. DlnaFlags.BackgroundTransferMode |
  124. DlnaFlags.InteractiveTransferMode |
  125. DlnaFlags.DlnaV15;
  126. // if (isDirectStream)
  127. //{
  128. // flagValue = flagValue | DlnaFlags.ByteBasedSeek;
  129. //}
  130. // else if (runtimeTicks.HasValue)
  131. //{
  132. // flagValue = flagValue | DlnaFlags.TimeBasedSeek;
  133. //}
  134. string dlnaflags = string.Format(CultureInfo.InvariantCulture, ";DLNA.ORG_FLAGS={0}",
  135. DlnaMaps.FlagsToString(flagValue));
  136. ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(
  137. container,
  138. audioCodec,
  139. videoCodec,
  140. width,
  141. height,
  142. bitDepth,
  143. videoBitrate,
  144. videoProfile,
  145. videoLevel,
  146. videoFramerate,
  147. packetLength,
  148. timestamp,
  149. isAnamorphic,
  150. isInterlaced,
  151. refFrames,
  152. numVideoStreams,
  153. numAudioStreams,
  154. videoCodecTag,
  155. isAvc);
  156. var orgPnValues = new List<string>();
  157. if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn))
  158. {
  159. orgPnValues.AddRange(mediaProfile.OrgPn.Split(',', StringSplitOptions.RemoveEmptyEntries));
  160. }
  161. else
  162. {
  163. foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
  164. {
  165. orgPnValues.Add(s);
  166. break;
  167. }
  168. }
  169. var contentFeatureList = new List<string>();
  170. foreach (string orgPn in orgPnValues)
  171. {
  172. string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
  173. var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
  174. contentFeatureList.Add(value);
  175. }
  176. if (orgPnValues.Count == 0)
  177. {
  178. string contentFeatures = string.Empty;
  179. var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
  180. contentFeatureList.Add(value);
  181. }
  182. return contentFeatureList;
  183. }
  184. private static string GetImageOrgPnValue(string container, int? width, int? height)
  185. {
  186. MediaFormatProfile? format = new MediaFormatProfileResolver()
  187. .ResolveImageFormat(
  188. container,
  189. width,
  190. height);
  191. return format.HasValue ? format.Value.ToString() : null;
  192. }
  193. private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
  194. {
  195. MediaFormatProfile? format = new MediaFormatProfileResolver()
  196. .ResolveAudioFormat(
  197. container,
  198. audioBitrate,
  199. audioSampleRate,
  200. audioChannels);
  201. return format.HasValue ? format.Value.ToString() : null;
  202. }
  203. private static string[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
  204. {
  205. return new MediaFormatProfileResolver().ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
  206. }
  207. }
  208. }