aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api/Playback/BaseStreamingService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api/Playback/BaseStreamingService.cs')
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs113
1 files changed, 64 insertions, 49 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 531d67eed..36207c8b4 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -23,6 +23,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using CommonIO;
namespace MediaBrowser.Api.Playback
{
@@ -290,13 +291,6 @@ namespace MediaBrowser.Api.Playback
{
get
{
- var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder;
-
- if (!string.IsNullOrWhiteSpace(lib))
- {
- return lib;
- }
-
return "libx264";
}
}
@@ -810,13 +804,53 @@ namespace MediaBrowser.Api.Playback
}
/// <summary>
+ /// Gets the name of the output video codec
+ /// </summary>
+ /// <param name="state">The state.</param>
+ /// <returns>System.String.</returns>
+ protected string GetVideoDecoder(StreamState state)
+ {
+ if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase))
+ {
+ if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
+ {
+ switch (state.MediaSource.VideoStream.Codec.ToLower())
+ {
+ case "avc":
+ case "h264":
+ if (MediaEncoder.SupportsDecoder("h264_qsv"))
+ {
+ return "-c:v h264_qsv ";
+ }
+ break;
+ case "mpeg2video":
+ if (MediaEncoder.SupportsDecoder("mpeg2_qsv"))
+ {
+ return "-c:v mpeg2_qsv ";
+ }
+ break;
+ case "vc1":
+ if (MediaEncoder.SupportsDecoder("vc1_qsv"))
+ {
+ return "-c:v vc1_qsv ";
+ }
+ break;
+ }
+ }
+ }
+
+ // leave blank so ffmpeg will decide
+ return null;
+ }
+
+ /// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
- var arg = "-i " + GetInputPathArgument(state);
+ var arg = string.Format("-i {0}", GetInputPathArgument(state));
if (state.SubtitleStream != null)
{
@@ -826,7 +860,7 @@ namespace MediaBrowser.Api.Playback
}
}
- return arg;
+ return arg.Trim();
}
private string GetInputPathArgument(StreamState state)
@@ -840,7 +874,7 @@ namespace MediaBrowser.Api.Playback
{
if (!(state.VideoType == VideoType.Iso && state.IsoMount == null))
{
- inputPath = MediaEncoderHelpers.GetInputArgument(mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames);
+ inputPath = MediaEncoderHelpers.GetInputArgument(FileSystem, mediaPath, state.InputProtocol, state.IsoMount, state.PlayableStreamFileNames);
}
}
@@ -889,7 +923,7 @@ namespace MediaBrowser.Api.Playback
CancellationTokenSource cancellationTokenSource,
string workingDirectory = null)
{
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
@@ -942,7 +976,7 @@ namespace MediaBrowser.Api.Playback
Logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
@@ -972,7 +1006,7 @@ namespace MediaBrowser.Api.Playback
StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream);
// Wait for the file to exist before proceeeding
- while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
+ while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
{
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
}
@@ -1027,6 +1061,7 @@ namespace MediaBrowser.Api.Playback
var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line);
await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
+ await target.FlushAsync().ConfigureAwait(false);
}
}
}
@@ -1151,15 +1186,8 @@ namespace MediaBrowser.Api.Playback
if (bitrate.HasValue)
{
- var hasFixedResolution = state.VideoRequest.HasFixedResolution;
-
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
{
- if (hasFixedResolution)
- {
- return string.Format(" -minrate:v ({0}*.90) -maxrate:v ({0}*1.10) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture));
- }
-
// With vpx when crf is used, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide. But higher bitrate source files -b:v causes judder so limite the bitrate but dont allow it to "saturate" the bitrate. So dont contrain it down just up.
return string.Format(" -maxrate:v {0} -bufsize:v ({0}*2) -b:v {0}", bitrate.Value.ToString(UsCulture));
@@ -1170,36 +1198,15 @@ namespace MediaBrowser.Api.Playback
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
- // h264_qsv
- if (string.Equals(videoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "libnvenc", StringComparison.OrdinalIgnoreCase))
+ // h264
+ if (isHls)
{
- if (hasFixedResolution)
- {
- if (isHls)
- {
- return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
- }
-
- return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
- }
-
- return string.Format(" -b:v {0} -maxrate ({0}*1.2) -bufsize ({0}*2)", bitrate.Value.ToString(UsCulture));
+ return string.Format(" -b:v {0} -maxrate {0} -bufsize {1}",
+ bitrate.Value.ToString(UsCulture),
+ (bitrate.Value * 2).ToString(UsCulture));
}
- // H264
- if (hasFixedResolution)
- {
- if (isHls)
- {
- return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
- }
-
- return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
- }
-
- return string.Format(" -maxrate {0} -bufsize {1}",
- bitrate.Value.ToString(UsCulture),
- (bitrate.Value * 2).ToString(UsCulture));
+ return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
return string.Empty;
@@ -1986,7 +1993,8 @@ namespace MediaBrowser.Api.Playback
state.IsTargetCabac,
state.TargetRefFrames,
state.TargetVideoStreamCount,
- state.TargetAudioStreamCount);
+ state.TargetAudioStreamCount,
+ state.TargetVideoCodecTag);
if (mediaProfile != null)
{
@@ -2083,7 +2091,8 @@ namespace MediaBrowser.Api.Playback
state.IsTargetCabac,
state.TargetRefFrames,
state.TargetVideoStreamCount,
- state.TargetAudioStreamCount
+ state.TargetAudioStreamCount,
+ state.TargetVideoCodecTag
).FirstOrDefault() ?? string.Empty;
}
@@ -2158,6 +2167,12 @@ namespace MediaBrowser.Api.Playback
inputModifier += " -re";
}
+ var videoDecoder = GetVideoDecoder(state);
+ if (!string.IsNullOrWhiteSpace(videoDecoder))
+ {
+ inputModifier += " " + videoDecoder;
+ }
+
return inputModifier;
}