aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api/Playback
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api/Playback')
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs411
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs73
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs61
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs47
-rw-r--r--MediaBrowser.Api/Playback/UniversalAudioService.cs4
5 files changed, 271 insertions, 325 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 5029ce0bb..928ca1612 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -134,15 +134,12 @@ namespace MediaBrowser.Api.Playback
var data = $"{state.MediaPath}-{state.UserAgent}-{state.Request.DeviceId}-{state.Request.PlaySessionId}";
var filename = data.GetMD5().ToString("N", CultureInfo.InvariantCulture);
- var ext = outputFileExtension.ToLowerInvariant();
+ var ext = outputFileExtension?.ToLowerInvariant();
var folder = ServerConfigurationManager.GetTranscodePath();
- if (EnableOutputInSubFolder)
- {
- return Path.Combine(folder, filename, filename + ext);
- }
-
- return Path.Combine(folder, filename + ext);
+ return EnableOutputInSubFolder
+ ? Path.Combine(folder, filename, filename + ext)
+ : Path.Combine(folder, filename + ext);
}
protected virtual string GetDefaultEncoderPreset()
@@ -248,14 +245,8 @@ namespace MediaBrowser.Api.Playback
if (state.VideoRequest != null
&& string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
- if (string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
- {
- logFilePrefix = "ffmpeg-remux";
- }
- else
- {
- logFilePrefix = "ffmpeg-directstream";
- }
+ logFilePrefix = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase)
+ ? "ffmpeg-remux" : "ffmpeg-directstream";
}
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
@@ -330,7 +321,7 @@ namespace MediaBrowser.Api.Playback
var encodingOptions = ServerConfigurationManager.GetEncodingOptions();
// enable throttling when NOT using hardware acceleration
- if (encodingOptions.HardwareAccelerationType == string.Empty)
+ if (string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
{
return state.InputProtocol == MediaProtocol.File &&
state.RunTimeTicks.HasValue &&
@@ -339,6 +330,7 @@ namespace MediaBrowser.Api.Playback
state.VideoType == VideoType.VideoFile &&
!string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase);
}
+
return false;
}
@@ -389,195 +381,181 @@ namespace MediaBrowser.Api.Playback
continue;
}
- if (i == 0)
- {
- request.DeviceProfileId = val;
- }
- else if (i == 1)
- {
- request.DeviceId = val;
- }
- else if (i == 2)
- {
- request.MediaSourceId = val;
- }
- else if (i == 3)
- {
- request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- else if (i == 4)
- {
- if (videoRequest != null)
- {
- videoRequest.VideoCodec = val;
- }
- }
- else if (i == 5)
- {
- request.AudioCodec = val;
- }
- else if (i == 6)
- {
- if (videoRequest != null)
- {
- videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 7)
- {
- if (videoRequest != null)
- {
- videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 8)
- {
- if (videoRequest != null)
- {
- videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 9)
- {
- request.AudioBitRate = int.Parse(val, CultureInfo.InvariantCulture);
- }
- else if (i == 10)
- {
- request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
- }
- else if (i == 11)
- {
- if (videoRequest != null)
- {
- videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 12)
- {
- if (videoRequest != null)
- {
- videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 13)
- {
- if (videoRequest != null)
- {
- videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 14)
- {
- request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture);
- }
- else if (i == 15)
- {
- if (videoRequest != null)
- {
- videoRequest.Level = val;
- }
- }
- else if (i == 16)
- {
- if (videoRequest != null)
- {
- videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 17)
- {
- if (videoRequest != null)
- {
- videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture);
- }
- }
- else if (i == 18)
- {
- if (videoRequest != null)
- {
- videoRequest.Profile = val;
- }
- }
- else if (i == 19)
- {
- // cabac no longer used
- }
- else if (i == 20)
- {
- request.PlaySessionId = val;
- }
- else if (i == 21)
- {
- // api_key
- }
- else if (i == 22)
- {
- request.LiveStreamId = val;
- }
- else if (i == 23)
- {
- // Duplicating ItemId because of MediaMonkey
- }
- else if (i == 24)
- {
- if (videoRequest != null)
- {
- videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- }
- else if (i == 25)
- {
- if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
- {
- if (Enum.TryParse(val, out SubtitleDeliveryMethod method))
+ switch (i)
+ {
+ case 0:
+ request.DeviceProfileId = val;
+ break;
+ case 1:
+ request.DeviceId = val;
+ break;
+ case 2:
+ request.MediaSourceId = val;
+ break;
+ case 3:
+ request.Static = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ break;
+ case 4:
+ if (videoRequest != null)
{
- videoRequest.SubtitleMethod = method;
+ videoRequest.VideoCodec = val;
}
- }
- }
- else if (i == 26)
- {
- request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
- }
- else if (i == 27)
- {
- if (videoRequest != null)
- {
- videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- }
- else if (i == 28)
- {
- request.Tag = val;
- }
- else if (i == 29)
- {
- if (videoRequest != null)
- {
- videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- }
- else if (i == 30)
- {
- request.SubtitleCodec = val;
- }
- else if (i == 31)
- {
- if (videoRequest != null)
- {
- videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- }
- else if (i == 32)
- {
- if (videoRequest != null)
- {
- videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
- }
- }
- else if (i == 33)
- {
- request.TranscodeReasons = val;
+
+ break;
+ case 5:
+ request.AudioCodec = val;
+ break;
+ case 6:
+ if (videoRequest != null)
+ {
+ videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 7:
+ if (videoRequest != null)
+ {
+ videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 8:
+ if (videoRequest != null)
+ {
+ videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 9:
+ request.AudioBitRate = int.Parse(val, CultureInfo.InvariantCulture);
+ break;
+ case 10:
+ request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
+ break;
+ case 11:
+ if (videoRequest != null)
+ {
+ videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 12:
+ if (videoRequest != null)
+ {
+ videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 13:
+ if (videoRequest != null)
+ {
+ videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 14:
+ request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture);
+ break;
+ case 15:
+ if (videoRequest != null)
+ {
+ videoRequest.Level = val;
+ }
+
+ break;
+ case 16:
+ if (videoRequest != null)
+ {
+ videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 17:
+ if (videoRequest != null)
+ {
+ videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture);
+ }
+
+ break;
+ case 18:
+ if (videoRequest != null)
+ {
+ videoRequest.Profile = val;
+ }
+
+ break;
+ case 19:
+ // cabac no longer used
+ break;
+ case 20:
+ request.PlaySessionId = val;
+ break;
+ case 21:
+ // api_key
+ break;
+ case 22:
+ request.LiveStreamId = val;
+ break;
+ case 23:
+ // Duplicating ItemId because of MediaMonkey
+ break;
+ case 24:
+ if (videoRequest != null)
+ {
+ videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+
+ break;
+ case 25:
+ if (!string.IsNullOrWhiteSpace(val) && videoRequest != null)
+ {
+ if (Enum.TryParse(val, out SubtitleDeliveryMethod method))
+ {
+ videoRequest.SubtitleMethod = method;
+ }
+ }
+
+ break;
+ case 26:
+ request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
+ break;
+ case 27:
+ if (videoRequest != null)
+ {
+ videoRequest.EnableSubtitlesInManifest = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+
+ break;
+ case 28:
+ request.Tag = val;
+ break;
+ case 29:
+ if (videoRequest != null)
+ {
+ videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+
+ break;
+ case 30:
+ request.SubtitleCodec = val;
+ break;
+ case 31:
+ if (videoRequest != null)
+ {
+ videoRequest.RequireNonAnamorphic = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+
+ break;
+ case 32:
+ if (videoRequest != null)
+ {
+ videoRequest.DeInterlace = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+
+ break;
+ case 33:
+ request.TranscodeReasons = val;
+ break;
}
}
}
@@ -630,14 +608,9 @@ namespace MediaBrowser.Api.Playback
throw new ArgumentException("Invalid timeseek header");
}
int index = value.IndexOf('-');
- if (index == -1)
- {
- value = value.Substring(Npt.Length);
- }
- else
- {
- value = value.Substring(Npt.Length, index - Npt.Length);
- }
+ value = index == -1
+ ? value.Substring(Npt.Length)
+ : value.Substring(Npt.Length, index - Npt.Length);
if (value.IndexOf(':') == -1)
{
@@ -856,21 +829,11 @@ namespace MediaBrowser.Api.Playback
{
state.DeviceProfile = DlnaManager.GetProfile(state.Request.DeviceProfileId);
}
- else
+ else if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
{
- if (!string.IsNullOrWhiteSpace(state.Request.DeviceId))
- {
- var caps = DeviceManager.GetCapabilities(state.Request.DeviceId);
+ var caps = DeviceManager.GetCapabilities(state.Request.DeviceId);
- if (caps != null)
- {
- state.DeviceProfile = caps.DeviceProfile;
- }
- else
- {
- state.DeviceProfile = DlnaManager.GetProfile(headers);
- }
- }
+ state.DeviceProfile = caps == null ? DlnaManager.GetProfile(headers) : caps.DeviceProfile;
}
var profile = state.DeviceProfile;
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 0cbfe4bdf..52962366c 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (isLive)
{
- job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
+ job ??= ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
if (job != null)
{
@@ -156,7 +156,7 @@ namespace MediaBrowser.Api.Playback.Hls
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, baselineStreamBitrate);
- job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
+ job ??= ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
if (job != null)
{
@@ -168,22 +168,19 @@ namespace MediaBrowser.Api.Playback.Hls
private string GetLivePlaylistText(string path, int segmentLength)
{
- using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
- {
- using (var reader = new StreamReader(stream))
- {
- var text = reader.ReadToEnd();
+ using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ using var reader = new StreamReader(stream);
- text = text.Replace("#EXTM3U", "#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT");
+ var text = reader.ReadToEnd();
- var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture);
+ text = text.Replace("#EXTM3U", "#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT");
- text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
- //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture);
- return text;
- }
- }
+ text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+
+ return text;
}
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, int baselineStreamBitrate)
@@ -212,29 +209,25 @@ namespace MediaBrowser.Api.Playback.Hls
try
{
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
- using (var fileStream = GetPlaylistFileStream(playlist))
+ using var fileStream = GetPlaylistFileStream(playlist);
+ using var reader = new StreamReader(fileStream);
+ var count = 0;
+
+ while (!reader.EndOfStream)
{
- using (var reader = new StreamReader(fileStream))
- {
- var count = 0;
+ var line = reader.ReadLine();
- while (!reader.EndOfStream)
+ if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ count++;
+ if (count >= segmentCount)
{
- var line = reader.ReadLine();
-
- if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
- {
- count++;
- if (count >= segmentCount)
- {
- Logger.LogDebug("Finished waiting for {0} segments in {1}", segmentCount, playlist);
- return;
- }
- }
+ Logger.LogDebug("Finished waiting for {0} segments in {1}", segmentCount, playlist);
+ return;
}
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
}
+ await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
catch (IOException)
{
@@ -247,17 +240,13 @@ namespace MediaBrowser.Api.Playback.Hls
protected Stream GetPlaylistFileStream(string path)
{
- var tmpPath = path + ".tmp";
- tmpPath = path;
-
- try
- {
- return new FileStream(tmpPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.SequentialScan);
- }
- catch (IOException)
- {
- return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.SequentialScan);
- }
+ return new FileStream(
+ path,
+ FileMode.Open,
+ FileAccess.Read,
+ FileShare.ReadWrite,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.SequentialScan);
}
protected override string GetCommandLineArguments(string outputPath, EncodingOptions encodingOptions, StreamState state, bool isEncoding)
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 9071ef18f..7f74e85e9 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -284,7 +284,7 @@ namespace MediaBrowser.Api.Playback.Hls
//}
Logger.LogDebug("returning {0} [general case]", segmentPath);
- job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
+ job ??= ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, requestedIndex, job, cancellationToken).ConfigureAwait(false);
}
@@ -438,8 +438,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
var segmentId = "0";
- var segmentRequest = request as GetHlsVideoSegment;
- if (segmentRequest != null)
+ if (request is GetHlsVideoSegment segmentRequest)
{
segmentId = segmentRequest.SegmentId;
}
@@ -690,8 +689,7 @@ namespace MediaBrowser.Api.Playback.Hls
return false;
}
- var request = state.Request as IMasterHlsRequest;
- if (request != null && !request.EnableAdaptiveBitrateStreaming)
+ if (state.Request is IMasterHlsRequest request && !request.EnableAdaptiveBitrateStreaming)
{
return false;
}
@@ -1108,61 +1106,69 @@ namespace MediaBrowser.Api.Playback.Hls
}
else
{
+ var gopArg = string.Empty;
var keyFrameArg = string.Format(
CultureInfo.InvariantCulture,
" -force_key_frames:0 \"expr:gte(t,{0}+n_forced*{1})\"",
GetStartNumber(state) * state.SegmentLength,
state.SegmentLength);
- if (state.TargetFramerate.HasValue)
+
+ var framerate = state.VideoStream?.RealFrameRate;
+
+ if (framerate.HasValue)
{
// This is to make sure keyframe interval is limited to our segment,
// as forcing keyframes is not enough.
// Example: we encoded half of desired length, then codec detected
// scene cut and inserted a keyframe; next forced keyframe would
- // be created outside of segment, which breaks seeking.
- keyFrameArg += string.Format(
+ // be created outside of segment, which breaks seeking
+ // -sc_threshold 0 is used to prevent the hardware encoder from post processing to break the set keyframe
+ gopArg = string.Format(
CultureInfo.InvariantCulture,
- " -g {0} -keyint_min {0}",
- (int)(state.SegmentLength * state.TargetFramerate)
+ " -g {0} -keyint_min {0} -sc_threshold 0",
+ Math.Ceiling(state.SegmentLength * framerate.Value)
);
}
- var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
-
args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultEncoderPreset());
- // Unable to force key frames to h264_qsv transcode
- if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
+ // Unable to force key frames using these hw encoders, set key frames by GOP
+ if (string.Equals(codec, "h264_qsv", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "h264_nvenc", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(codec, "h264_amf", StringComparison.OrdinalIgnoreCase))
{
- Logger.LogInformation("Bug Workaround: Disabling force_key_frames for h264_qsv");
+ args += " " + gopArg;
}
else
{
- args += " " + keyFrameArg;
+ args += " " + keyFrameArg + gopArg;
}
//args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0";
+ var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
+
+ // This is for graphical subs
+ if (hasGraphicalSubs)
+ {
+ args += EncodingHelper.GetGraphicalSubtitleParam(state, encodingOptions, codec);
+ }
// Add resolution params, if specified
- if (!hasGraphicalSubs)
+ else
{
- args += EncodingHelper.GetOutputSizeParam(state, encodingOptions, codec, true);
+ args += EncodingHelper.GetOutputSizeParam(state, encodingOptions, codec);
}
- // This is for internal graphical subs
- if (hasGraphicalSubs)
+ // -start_at_zero is necessary to use with -ss when seeking,
+ // otherwise the target position cannot be determined.
+ if (!(state.SubtitleStream != null && state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream))
{
- args += EncodingHelper.GetGraphicalSubtitleParam(state, encodingOptions, codec);
+ args += " -start_at_zero";
}
//args += " -flags -global_header";
}
- if (args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
- {
- args += " -copyts";
- }
-
if (!string.IsNullOrEmpty(state.OutputVideoSync))
{
args += " -vsync " + state.OutputVideoSync;
@@ -1188,6 +1194,7 @@ namespace MediaBrowser.Api.Playback.Hls
Logger.LogInformation("Current HLS implementation doesn't support non-keyframe breaks but one is requested, ignoring that request");
state.BaseRequest.BreakOnNonKeyFrames = false;
}
+
var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
// If isEncoding is true we're actually starting ffmpeg
@@ -1205,7 +1212,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
return string.Format(
- "{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f hls -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
+ "{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -f hls -max_delay 5000000 -hls_time {6} -individual_header_trailer 0 -hls_segment_type {7} -start_number {8} -hls_segment_filename \"{9}\" -hls_playlist_type vod -hls_list_size 0 -y \"{10}\"",
inputModifier,
EncodingHelper.GetInputArgument(state, encodingOptions),
threads,
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 08a7e534f..db24eaca6 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -1,13 +1,12 @@
#pragma warning disable CS1591
#pragma warning disable SA1402
-#pragma warning disable SA1600
#pragma warning disable SA1649
using System;
using System.Buffers;
using System.Globalization;
-using System.Text.Json;
using System.Linq;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
@@ -235,7 +234,7 @@ namespace MediaBrowser.Api.Playback
OpenToken = mediaSource.OpenToken
}).ConfigureAwait(false);
- info.MediaSources = new MediaSourceInfo[] { openStreamResult.MediaSource };
+ info.MediaSources = new[] { openStreamResult.MediaSource };
}
}
@@ -290,7 +289,7 @@ namespace MediaBrowser.Api.Playback
{
var mediaSource = await _mediaSourceManager.GetLiveStream(liveStreamId, CancellationToken.None).ConfigureAwait(false);
- mediaSources = new MediaSourceInfo[] { mediaSource };
+ mediaSources = new[] { mediaSource };
}
if (mediaSources.Length == 0)
@@ -367,7 +366,7 @@ namespace MediaBrowser.Api.Playback
var options = new VideoOptions
{
- MediaSources = new MediaSourceInfo[] { mediaSource },
+ MediaSources = new[] { mediaSource },
Context = EncodingContext.Streaming,
DeviceId = auth.DeviceId,
ItemId = item.Id,
@@ -471,7 +470,7 @@ namespace MediaBrowser.Api.Playback
else
{
options.MaxBitrate = GetMaxBitrate(maxBitrate, user);
-
+
if (item is Audio)
{
if (!user.Policy.EnableAudioPlaybackTranscoding)
@@ -487,10 +486,10 @@ namespace MediaBrowser.Api.Playback
}
}
- // The MediaSource supports direct stream, now test to see if the client supports it
- var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
- ? streamBuilder.BuildAudioItem(options)
- : streamBuilder.BuildVideoItem(options);
+ // The MediaSource supports direct stream, now test to see if the client supports it
+ var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
+ ? streamBuilder.BuildAudioItem(options)
+ : streamBuilder.BuildVideoItem(options);
if (streamInfo == null || !streamInfo.IsDirectStream)
{
@@ -517,20 +516,17 @@ namespace MediaBrowser.Api.Playback
{
if (streamInfo != null)
{
- streamInfo.PlaySessionId = playSessionId;
+ streamInfo.PlaySessionId = playSessionId;
streamInfo.StartPositionTicks = startTimeTicks;
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
- if (!allowAudioStreamCopy)
- {
- mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
- }
+ mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
-
+
// Do this after the above so that StartPositionTicks is set
SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
- }
+ }
}
else
{
@@ -573,8 +569,7 @@ namespace MediaBrowser.Api.Playback
{
attachment.DeliveryUrl = string.Format(
CultureInfo.InvariantCulture,
- "{0}/Videos/{1}/{2}/Attachments/{3}",
- ServerConfigurationManager.Configuration.BaseUrl,
+ "/Videos/{0}/{1}/Attachments/{2}",
item.Id,
mediaSource.Id,
attachment.Index);
@@ -584,7 +579,7 @@ namespace MediaBrowser.Api.Playback
private long? GetMaxBitrate(long? clientMaxBitrate, User user)
{
var maxBitrate = clientMaxBitrate;
- var remoteClientMaxBitrate = user == null ? 0 : user.Policy.RemoteClientBitrateLimit;
+ var remoteClientMaxBitrate = user?.Policy.RemoteClientBitrateLimit ?? 0;
if (remoteClientMaxBitrate <= 0)
{
@@ -663,17 +658,9 @@ namespace MediaBrowser.Api.Playback
};
}).ThenBy(i =>
{
- if (maxBitrate.HasValue)
+ if (maxBitrate.HasValue && i.Bitrate.HasValue)
{
- if (i.Bitrate.HasValue)
- {
- if (i.Bitrate.Value <= maxBitrate.Value)
- {
- return 0;
- }
-
- return 2;
- }
+ return i.Bitrate.Value <= maxBitrate.Value ? 0 : 2;
}
return 1;
diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs
index cbf981dfe..cebd4b49a 100644
--- a/MediaBrowser.Api/Playback/UniversalAudioService.cs
+++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs
@@ -167,7 +167,7 @@ namespace MediaBrowser.Api.Playback
AudioCodec = request.AudioCodec,
Protocol = request.TranscodingProtocol,
BreakOnNonKeyFrames = request.BreakOnNonKeyFrames,
- MaxAudioChannels = request.TranscodingAudioChannels.HasValue ? request.TranscodingAudioChannels.Value.ToString(CultureInfo.InvariantCulture) : null
+ MaxAudioChannels = request.TranscodingAudioChannels?.ToString(CultureInfo.InvariantCulture)
}
};
@@ -300,7 +300,7 @@ namespace MediaBrowser.Api.Playback
// hls segment container can only be mpegts or fmp4 per ffmpeg documentation
// TODO: remove this when we switch back to the segment muxer
- var supportedHLSContainers = new string[] { "mpegts", "fmp4" };
+ var supportedHLSContainers = new[] { "mpegts", "fmp4" };
var newRequest = new GetMasterHlsAudioPlaylist
{