VideoHandler.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using MediaBrowser.Common.IO;
  2. using MediaBrowser.Controller.Entities;
  3. using MediaBrowser.Controller.Resolvers;
  4. using System;
  5. using System.Linq;
  6. using System.Net;
  7. namespace MediaBrowser.Api.Streaming
  8. {
  9. /// <summary>
  10. /// Providers a progressive streaming video api
  11. /// </summary>
  12. class VideoHandler : BaseProgressiveStreamingHandler<Video>
  13. {
  14. /// <summary>
  15. /// Handleses the request.
  16. /// </summary>
  17. /// <param name="request">The request.</param>
  18. /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
  19. public override bool HandlesRequest(HttpListenerRequest request)
  20. {
  21. return EntityResolutionHelper.VideoFileExtensions.Any(a => ApiService.IsApiUrlMatch("video" + a, request));
  22. }
  23. /// <summary>
  24. /// Creates arguments to pass to ffmpeg
  25. /// </summary>
  26. /// <param name="outputPath">The output path.</param>
  27. /// <param name="isoMount">The iso mount.</param>
  28. /// <returns>System.String.</returns>
  29. protected override string GetCommandLineArguments(string outputPath, IIsoMount isoMount)
  30. {
  31. var probeSize = Kernel.FFMpegManager.GetProbeSizeArgument(LibraryItem.VideoType, LibraryItem.IsoType);
  32. // Get the output codec name
  33. var videoCodec = GetVideoCodec();
  34. var graphicalSubtitleParam = string.Empty;
  35. if (SubtitleStream != null)
  36. {
  37. // This is for internal graphical subs
  38. if (!SubtitleStream.IsExternal && (SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 || SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1))
  39. {
  40. graphicalSubtitleParam = GetInternalGraphicalSubtitleParam(SubtitleStream, videoCodec);
  41. }
  42. }
  43. return string.Format("{0} {1} -i {2}{3} -threads 0 {4} {5}{6} {7} \"{8}\"",
  44. probeSize,
  45. FastSeekCommandLineParameter,
  46. GetInputArgument(isoMount),
  47. SlowSeekCommandLineParameter,
  48. MapArgs,
  49. GetVideoArguments(videoCodec),
  50. graphicalSubtitleParam,
  51. GetAudioArguments(),
  52. outputPath
  53. ).Trim();
  54. }
  55. /// <summary>
  56. /// Gets video arguments to pass to ffmpeg
  57. /// </summary>
  58. /// <returns>System.String.</returns>
  59. private string GetVideoArguments(string videoCodec)
  60. {
  61. var args = "-vcodec " + videoCodec;
  62. // If we're encoding video, add additional params
  63. if (!videoCodec.Equals("copy", StringComparison.OrdinalIgnoreCase))
  64. {
  65. // Add resolution params, if specified
  66. if (Width.HasValue || Height.HasValue || MaxHeight.HasValue || MaxWidth.HasValue)
  67. {
  68. args += GetOutputSizeParam(videoCodec);
  69. }
  70. if (FrameRate.HasValue)
  71. {
  72. args += string.Format(" -r {0}", FrameRate.Value);
  73. }
  74. // Add the audio bitrate
  75. var qualityParam = GetVideoQualityParam(videoCodec);
  76. if (!string.IsNullOrEmpty(qualityParam))
  77. {
  78. args += " " + qualityParam;
  79. }
  80. }
  81. else if (IsH264(VideoStream))
  82. {
  83. args += " -bsf h264_mp4toannexb";
  84. }
  85. return args;
  86. }
  87. /// <summary>
  88. /// Gets audio arguments to pass to ffmpeg
  89. /// </summary>
  90. /// <returns>System.String.</returns>
  91. private string GetAudioArguments()
  92. {
  93. // If the video doesn't have an audio stream, return a default.
  94. if (AudioStream == null)
  95. {
  96. return string.Empty;
  97. }
  98. // Get the output codec name
  99. var codec = GetAudioCodec();
  100. var args = "-acodec " + codec;
  101. // If we're encoding audio, add additional params
  102. if (!codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
  103. {
  104. // Add the number of audio channels
  105. var channels = GetNumAudioChannelsParam();
  106. if (channels.HasValue)
  107. {
  108. args += " -ac " + channels.Value;
  109. }
  110. // Add the audio sample rate
  111. var sampleRate = GetSampleRateParam();
  112. if (sampleRate.HasValue)
  113. {
  114. args += " -ar " + sampleRate.Value;
  115. }
  116. if (AudioBitRate.HasValue)
  117. {
  118. args += " -ab " + AudioBitRate.Value;
  119. }
  120. }
  121. return args;
  122. }
  123. /// <summary>
  124. /// Gets the video bitrate to specify on the command line
  125. /// </summary>
  126. /// <param name="videoCodec">The video codec.</param>
  127. /// <returns>System.String.</returns>
  128. private string GetVideoQualityParam(string videoCodec)
  129. {
  130. var args = string.Empty;
  131. // webm
  132. if (videoCodec.Equals("libvpx", StringComparison.OrdinalIgnoreCase))
  133. {
  134. args = "-g 120 -cpu-used 1 -lag-in-frames 16 -deadline realtime -slices 4 -vprofile 0";
  135. }
  136. // asf/wmv
  137. else if (videoCodec.Equals("wmv2", StringComparison.OrdinalIgnoreCase))
  138. {
  139. args = "-g 100 -qmax 15";
  140. }
  141. else if (videoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase))
  142. {
  143. args = "-preset superfast";
  144. }
  145. if (VideoBitRate.HasValue)
  146. {
  147. args += " -b:v " + VideoBitRate;
  148. }
  149. return args.Trim();
  150. }
  151. }
  152. }