From c1208a2f8d73d4c567562a044b77dfe5e6941bd6 Mon Sep 17 00:00:00 2001 From: gerrit507 Date: Sun, 5 Mar 2017 04:02:03 +0100 Subject: Fix naming of nvenc codecs. It should be nvenc_h264. --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ef356c7cd..090232ff0 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(hwType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - return GetAvailableEncoder("h264_nvenc", defaultEncoder); + return GetAvailableEncoder("nvenc_h264", defaultEncoder); } if (string.Equals(hwType, "h264_omx", StringComparison.OrdinalIgnoreCase)) { @@ -591,8 +591,8 @@ namespace MediaBrowser.Controller.MediaEncoding } - // h264 (h264_nvenc) - else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) + // h264 (nvenc_h264) + else if (string.Equals(videoEncoder, "nvenc_h264", StringComparison.OrdinalIgnoreCase)) { param += "-preset default"; } @@ -670,10 +670,10 @@ namespace MediaBrowser.Controller.MediaEncoding { var level = NormalizeTranscodingLevel(state.OutputVideoCodec, request.Level); - // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // h264_qsv and nvenc_h264 expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "nvenc_h264", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (level) -- cgit v1.2.3 From 46b6235b8a974c5f8ab880af97d498c635c3365a Mon Sep 17 00:00:00 2001 From: gerrit507 Date: Sun, 5 Mar 2017 13:25:36 +0100 Subject: Revert "Fix naming of nvenc codecs. It should be nvenc_h264." This reverts commit 44ae8c94fc720fc14d4fc551cd375006691d3d3e. --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 10 +++++----- MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 090232ff0..ef356c7cd 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (string.Equals(hwType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - return GetAvailableEncoder("nvenc_h264", defaultEncoder); + return GetAvailableEncoder("h264_nvenc", defaultEncoder); } if (string.Equals(hwType, "h264_omx", StringComparison.OrdinalIgnoreCase)) { @@ -591,8 +591,8 @@ namespace MediaBrowser.Controller.MediaEncoding } - // h264 (nvenc_h264) - else if (string.Equals(videoEncoder, "nvenc_h264", StringComparison.OrdinalIgnoreCase)) + // h264 (h264_nvenc) + else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)) { param += "-preset default"; } @@ -670,10 +670,10 @@ namespace MediaBrowser.Controller.MediaEncoding { var level = NormalizeTranscodingLevel(state.OutputVideoCodec, request.Level); - // h264_qsv and nvenc_h264 expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format + // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "nvenc_h264", StringComparison.OrdinalIgnoreCase) || + string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (level) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 7bcbc97eb..b37e783b8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "libopus", "libvorbis", "srt", - "nvenc_h264", + "h264_nvenc", "h264_qsv", "h264_omx", "h264_vaapi", -- cgit v1.2.3 From a74373e851f98c66ce39f73b288419a3781b1449 Mon Sep 17 00:00:00 2001 From: gerrit507 Date: Sun, 5 Mar 2017 13:35:23 +0100 Subject: Remove level param for nvenc, because it fails to encode with it. --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ef356c7cd..8afee9f35 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -671,9 +671,8 @@ namespace MediaBrowser.Controller.MediaEncoding var level = NormalizeTranscodingLevel(state.OutputVideoCodec, request.Level); // h264_qsv and h264_nvenc expect levels to be expressed as a decimal. libx264 supports decimal and non-decimal format - // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 + // also needed for libx264 due to https://trac.ffmpeg.org/ticket/3307 if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) || - string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) || string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) { switch (level) @@ -710,10 +709,15 @@ namespace MediaBrowser.Controller.MediaEncoding break; } } + // nvenc doesn't decode with param -level set ?! + if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase)){ + param += ""; + } else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase)) { param += " -level " + level; } + } if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase)) -- cgit v1.2.3 From fc2a5acfca4b12f1f5b7dc17ce34bdd890641dc6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 10 Mar 2017 13:33:17 -0500 Subject: move loopback util --- Emby.Server.Core/ApplicationHost.cs | 46 ++- .../Emby.Server.Implementations.csproj | 1 + MediaBrowser.Api/Playback/MediaInfoService.cs | 68 ++-- .../MediaEncoding/EncodingHelper.cs | 5 + .../MediaInfo/PlaybackInfoRequest.cs | 2 + MediaBrowser.Server.Mac/MacAppHost.cs | 36 --- .../MediaBrowser.ServerApplication.csproj | 1 - .../Native/LoopbackUtil.cs | 358 --------------------- MediaBrowser.ServerApplication/WindowsAppHost.cs | 6 +- .../Net/HttpListenerRequest.cs | 2 +- 10 files changed, 81 insertions(+), 444 deletions(-) delete mode 100644 MediaBrowser.ServerApplication/Native/LoopbackUtil.cs (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index 4425d1a0b..7dbc7760b 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -107,7 +107,7 @@ using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations; using Emby.Server.Implementations.ServerManager; using Emby.Server.Implementations.Session; -using Emby.Server.Implementations.Social; +using Emby.Server.Implementations.Windows; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; using MediaBrowser.Model.Activity; @@ -796,17 +796,25 @@ namespace Emby.Server.Core info.FFMpegFilename = "ffmpeg"; info.FFProbeFilename = "ffprobe"; info.ArchiveType = "7z"; - info.Version = "20160215"; + info.Version = "20170308"; info.DownloadUrls = GetLinuxDownloadUrls(); } else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) { info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20160410"; + info.Version = "20170308"; info.ArchiveType = "7z"; info.DownloadUrls = GetWindowsDownloadUrls(); } + else if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX) + { + info.FFMpegFilename = "ffmpeg"; + info.FFProbeFilename = "ffprobe"; + info.ArchiveType = "7z"; + info.Version = "20170308"; + info.DownloadUrls = GetMacDownloadUrls(); + } else { // No version available - user requirement @@ -816,6 +824,20 @@ namespace Emby.Server.Core return info; } + private string[] GetMacDownloadUrls() + { + switch (EnvironmentInfo.SystemArchitecture) + { + case Architecture.X64: + return new[] + { + "https://embydata.com/downloads/ffmpeg/osx/ffmpeg-x64-20170308.7z" + }; + } + + return new string[] { }; + } + private string[] GetWindowsDownloadUrls() { switch (EnvironmentInfo.SystemArchitecture) @@ -823,12 +845,12 @@ namespace Emby.Server.Core case Architecture.X64: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160410-win64.7z" + "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win64.7z" }; case Architecture.X86: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160410-win32.7z" + "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win32.7z" }; } @@ -842,12 +864,12 @@ namespace Emby.Server.Core case Architecture.X64: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z" + "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-64bit-static.7z" }; case Architecture.X86: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-32bit-static.7z" + "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-32bit-static.7z" }; } @@ -1716,12 +1738,10 @@ namespace Emby.Server.Core public void EnableLoopback(string appName) { - EnableLoopbackInternal(appName); - } - - protected virtual void EnableLoopbackInternal(string appName) - { - + if (EnvironmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) + { + LoopUtil.Run(appName); + } } private void RegisterModules() diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index c704d0e4e..9affe0fdd 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -269,6 +269,7 @@ + diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index ed8449b83..4e4e8858e 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Api.Playback SetDeviceSpecificData(item, result.MediaSource, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, result.MediaSource.Id, request.AudioStreamIndex, - request.SubtitleStreamIndex, request.MaxAudioChannels, request.PlaySessionId, request.UserId, true, true, true); + request.SubtitleStreamIndex, request.MaxAudioChannels, request.PlaySessionId, request.UserId, true, true, true, true); } else { @@ -169,7 +169,7 @@ namespace MediaBrowser.Api.Playback { var mediaSourceId = request.MediaSourceId; - SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.MaxAudioChannels, request.UserId, request.EnableDirectPlay, request.EnableDirectStream, request.EnableTranscoding); + SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate ?? profile.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex, request.MaxAudioChannels, request.UserId, request.EnableDirectPlay, request.ForceDirectPlayRemoteMediaSource, request.EnableDirectStream, request.EnableTranscoding); } return info; @@ -253,6 +253,7 @@ namespace MediaBrowser.Api.Playback int? maxAudioChannels, string userId, bool enableDirectPlay, + bool forceDirectPlayRemoteMediaSource, bool enableDirectStream, bool enableTranscoding) { @@ -260,7 +261,7 @@ namespace MediaBrowser.Api.Playback foreach (var mediaSource in result.MediaSources) { - SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, maxAudioChannels, result.PlaySessionId, userId, enableDirectPlay, enableDirectStream, enableTranscoding); + SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, maxAudioChannels, result.PlaySessionId, userId, enableDirectPlay, forceDirectPlayRemoteMediaSource, enableDirectStream, enableTranscoding); } SortMediaSources(result, maxBitrate); @@ -279,6 +280,7 @@ namespace MediaBrowser.Api.Playback string playSessionId, string userId, bool enableDirectPlay, + bool forceDirectPlayRemoteMediaSource, bool enableDirectStream, bool enableTranscoding) { @@ -318,43 +320,49 @@ namespace MediaBrowser.Api.Playback if (mediaSource.SupportsDirectPlay) { - var supportsDirectStream = mediaSource.SupportsDirectStream; + if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource) + { + } + else + { + var supportsDirectStream = mediaSource.SupportsDirectStream; - // Dummy this up to fool StreamBuilder - mediaSource.SupportsDirectStream = true; - options.MaxBitrate = maxBitrate; + // Dummy this up to fool StreamBuilder + mediaSource.SupportsDirectStream = true; + options.MaxBitrate = maxBitrate; - if (item is Audio) - { - if (!user.Policy.EnableAudioPlaybackTranscoding) + if (item is Audio) { - options.ForceDirectPlay = true; + if (!user.Policy.EnableAudioPlaybackTranscoding) + { + options.ForceDirectPlay = true; + } } - } - else if (item is Video) - { - if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing) + else if (item is Video) { - options.ForceDirectPlay = true; + if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing) + { + options.ForceDirectPlay = true; + } } - } - // 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) - { - mediaSource.SupportsDirectPlay = false; - } + if (streamInfo == null || !streamInfo.IsDirectStream) + { + mediaSource.SupportsDirectPlay = false; + } - // Set this back to what it was - mediaSource.SupportsDirectStream = supportsDirectStream; + // Set this back to what it was + mediaSource.SupportsDirectStream = supportsDirectStream; - if (streamInfo != null) - { - SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); + if (streamInfo != null) + { + SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); + } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 80b9cc154..ebcc9853a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1670,6 +1670,11 @@ namespace MediaBrowser.Controller.MediaEncoding case "h264": if (_mediaEncoder.SupportsDecoder("h264_qsv")) { + // qsv decoder does not support 10-bit input + if ((state.VideoStream.BitDepth ?? 8) > 8) + { + return null; + } return "-c:v h264_qsv "; } break; diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs index 57a2254b0..16c9464ac 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs @@ -27,9 +27,11 @@ namespace MediaBrowser.Model.MediaInfo public bool EnableDirectPlay { get; set; } public bool EnableDirectStream { get; set; } public bool EnableTranscoding { get; set; } + public bool ForceDirectPlayRemoteMediaSource { get; set; } public PlaybackInfoRequest() { + ForceDirectPlayRemoteMediaSource = true; EnableDirectPlay = true; EnableDirectStream = true; EnableTranscoding = true; diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index 59e72e71e..f84e96126 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -56,42 +56,6 @@ namespace MediaBrowser.Server.Mac return new SyncManager(); } - protected override FFMpegInstallInfo GetFfmpegInstallInfo() - { - var info = new FFMpegInstallInfo(); - - info.ArchiveType = "7z"; - - switch (EnvironmentInfo.SystemArchitecture) - { - case Architecture.X64: - info.Version = "20160124"; - break; - case Architecture.X86: - info.Version = "20150110"; - break; - } - - info.DownloadUrls = GetDownloadUrls(); - - return info; - } - - private string[] GetDownloadUrls() - { - switch (EnvironmentInfo.SystemArchitecture) - { - case Architecture.X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" - }; - } - - // No version available - return new string[] { }; - } - protected override void RestartInternal() { MainClass.Restart(); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 7ebbc3809..02916f555 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -143,7 +143,6 @@ - diff --git a/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs b/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs deleted file mode 100644 index 5b260685b..000000000 --- a/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs +++ /dev/null @@ -1,358 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace MediaBrowser.ServerApplication.Native -{ - /// - /// http://blogs.msdn.com/b/fiddler/archive/2011/12/10/fiddler-windows-8-apps-enable-LoopUtil-network-isolation-exemption.aspx - /// - public class LoopUtil - { - //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379595(v=vs.85).aspx - [StructLayout(LayoutKind.Sequential)] - internal struct SID_AND_ATTRIBUTES - { - public IntPtr Sid; - public uint Attributes; - } - - [StructLayoutAttribute(LayoutKind.Sequential)] - internal struct INET_FIREWALL_AC_CAPABILITIES - { - public uint count; - public IntPtr capabilities; //SID_AND_ATTRIBUTES - } - - [StructLayoutAttribute(LayoutKind.Sequential)] - internal struct INET_FIREWALL_AC_BINARIES - { - public uint count; - public IntPtr binaries; - } - - [StructLayoutAttribute(LayoutKind.Sequential)] - internal struct INET_FIREWALL_APP_CONTAINER - { - internal IntPtr appContainerSid; - internal IntPtr userSid; - [MarshalAs(UnmanagedType.LPWStr)] - public string appContainerName; - [MarshalAs(UnmanagedType.LPWStr)] - public string displayName; - [MarshalAs(UnmanagedType.LPWStr)] - public string description; - internal INET_FIREWALL_AC_CAPABILITIES capabilities; - internal INET_FIREWALL_AC_BINARIES binaries; - [MarshalAs(UnmanagedType.LPWStr)] - public string workingDirectory; - [MarshalAs(UnmanagedType.LPWStr)] - public string packageFullName; - } - - - // Call this API to free the memory returned by the Enumeration API - [DllImport("FirewallAPI.dll")] - internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs); - - // Call this API to load the current list of LoopUtil-enabled AppContainers - [DllImport("FirewallAPI.dll")] - internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids); - - // Call this API to set the LoopUtil-exemption list - [DllImport("FirewallAPI.dll")] - private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids); - - - // Use this API to convert a string SID into an actual SID - [DllImport("advapi32.dll", SetLastError = true)] - internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid); - - [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] - static extern bool ConvertSidToStringSid( - [MarshalAs(UnmanagedType.LPArray)] byte[] pSID, - out IntPtr ptrSid); - - [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] - static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid); - - // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] - internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf); - - // Call this API to enumerate all of the AppContainers on the system - [DllImport("FirewallAPI.dll")] - internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs); - // DWORD NetworkIsolationEnumAppContainers( - // _In_ DWORD Flags, - // _Out_ DWORD *pdwNumPublicAppCs, - // _Out_ PINET_FIREWALL_APP_CONTAINER *ppPublicAppCs - //); - - //http://msdn.microsoft.com/en-gb/library/windows/desktop/hh968116.aspx - enum NETISO_FLAG - { - NETISO_FLAG_FORCE_COMPUTE_BINARIES = 0x1, - NETISO_FLAG_MAX = 0x2 - } - - - public class AppContainer - { - public String appContainerName { get; set; } - public String displayName { get; set; } - public String workingDirectory { get; set; } - public String StringSid { get; set; } - public List capabilities { get; set; } - public bool LoopUtil { get; set; } - - public AppContainer(String _appContainerName, String _displayName, String _workingDirectory, IntPtr _sid) - { - this.appContainerName = _appContainerName; - this.displayName = _displayName; - this.workingDirectory = _workingDirectory; - String tempSid; - ConvertSidToStringSid(_sid, out tempSid); - this.StringSid = tempSid; - } - } - - internal List _AppList; - internal List _AppListConfig; - public List Apps = new List(); - internal IntPtr _pACs; - - public LoopUtil() - { - LoadApps(); - } - - public void LoadApps() - { - Apps.Clear(); - _pACs = IntPtr.Zero; - //Full List of Apps - _AppList = PI_NetworkIsolationEnumAppContainers(); - //List of Apps that have LoopUtil enabled. - _AppListConfig = PI_NetworkIsolationGetAppContainerConfig(); - foreach (var PI_app in _AppList) - { - AppContainer app = new AppContainer(PI_app.appContainerName, PI_app.displayName, PI_app.workingDirectory, PI_app.appContainerSid); - - var app_capabilities = LoopUtil.getCapabilites(PI_app.capabilities); - if (app_capabilities.Count > 0) - { - //var sid = new SecurityIdentifier(app_capabilities[0], 0); - - IntPtr arrayValue = IntPtr.Zero; - //var b = LoopUtil.ConvertStringSidToSid(app_capabilities[0].Sid, out arrayValue); - //string mysid; - //var b = LoopUtil.ConvertSidToStringSid(app_capabilities[0].Sid, out mysid); - } - app.LoopUtil = CheckLoopback(PI_app.appContainerSid); - Apps.Add(app); - } - } - private bool CheckLoopback(IntPtr intPtr) - { - foreach (SID_AND_ATTRIBUTES item in _AppListConfig) - { - string left, right; - ConvertSidToStringSid(item.Sid, out left); - ConvertSidToStringSid(intPtr, out right); - - if (left == right) - { - return true; - } - } - return false; - } - - private bool CreateExcemptions(string appName) - { - var hasChanges = false; - - foreach (var app in Apps) - { - if ((app.appContainerName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1 || - (app.displayName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1) - { - if (!app.LoopUtil) - { - app.LoopUtil = true; - hasChanges = true; - } - } - } - - return hasChanges; - } - - public static void Run(string appName) - { - var util = new LoopUtil(); - util.LoadApps(); - - var hasChanges = util.CreateExcemptions(appName); - - if (hasChanges) - { - util.SaveLoopbackState(); - } - util.SaveLoopbackState(); - } - - private static List getCapabilites(INET_FIREWALL_AC_CAPABILITIES cap) - { - List mycap = new List(); - - IntPtr arrayValue = cap.capabilities; - - var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); - for (var i = 0; i < cap.count; i++) - { - var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); - mycap.Add(cur); - arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); - } - - return mycap; - - } - - private static List getContainerSID(INET_FIREWALL_AC_CAPABILITIES cap) - { - List mycap = new List(); - - IntPtr arrayValue = cap.capabilities; - - var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); - for (var i = 0; i < cap.count; i++) - { - var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); - mycap.Add(cur); - arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); - } - - return mycap; - - } - - private static List PI_NetworkIsolationGetAppContainerConfig() - { - - IntPtr arrayValue = IntPtr.Zero; - uint size = 0; - var list = new List(); - - // Pin down variables - GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); - GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); - - uint retval = NetworkIsolationGetAppContainerConfig(out size, out arrayValue); - - var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); - for (var i = 0; i < size; i++) - { - var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); - list.Add(cur); - arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); - } - - //release pinned variables. - handle_pdwCntPublicACs.Free(); - handle_ppACs.Free(); - - return list; - - - } - - private List PI_NetworkIsolationEnumAppContainers() - { - - IntPtr arrayValue = IntPtr.Zero; - uint size = 0; - var list = new List(); - - // Pin down variables - GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); - GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); - - //uint retval2 = NetworkIsolationGetAppContainerConfig( out size, out arrayValue); - - uint retval = NetworkIsolationEnumAppContainers((Int32)NETISO_FLAG.NETISO_FLAG_MAX, out size, out arrayValue); - _pACs = arrayValue; //store the pointer so it can be freed when we close the form - - var structSize = Marshal.SizeOf(typeof(INET_FIREWALL_APP_CONTAINER)); - for (var i = 0; i < size; i++) - { - var cur = (INET_FIREWALL_APP_CONTAINER)Marshal.PtrToStructure(arrayValue, typeof(INET_FIREWALL_APP_CONTAINER)); - list.Add(cur); - arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); - } - - //release pinned variables. - handle_pdwCntPublicACs.Free(); - handle_ppACs.Free(); - - return list; - - - } - - public bool SaveLoopbackState() - { - var countEnabled = CountEnabledLoopUtil(); - SID_AND_ATTRIBUTES[] arr = new SID_AND_ATTRIBUTES[countEnabled]; - int count = 0; - - for (int i = 0; i < Apps.Count; i++) - { - if (Apps[i].LoopUtil) - { - arr[count].Attributes = 0; - //TO DO: - IntPtr ptr; - ConvertStringSidToSid(Apps[i].StringSid, out ptr); - arr[count].Sid = ptr; - count++; - } - - } - - - if (NetworkIsolationSetAppContainerConfig((uint)countEnabled, arr) == 0) - { - return true; - } - else - { return false; } - - } - - private int CountEnabledLoopUtil() - { - var count = 0; - for (int i = 0; i < Apps.Count; i++) - { - if (Apps[i].LoopUtil) - { - count++; - } - - } - return count; - } - - public void FreeResources() - { - NetworkIsolationFreeAppContainers(_pACs); - } - - } -} diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index cc899462a..915a2fa86 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -10,6 +10,7 @@ using Emby.Server.Core; using Emby.Server.Implementations; using Emby.Server.Implementations.EntryPoints; using Emby.Server.Implementations.FFMpeg; +using Emby.Server.Implementations.Windows; using Emby.Server.Sync; using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Sync; @@ -107,11 +108,6 @@ namespace MediaBrowser.ServerApplication } } - protected override void EnableLoopbackInternal(string appName) - { - LoopUtil.Run(appName); - } - public override bool SupportsRunningAsService { get diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs index 811cc6ddb..cfbd49203 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs @@ -456,7 +456,7 @@ namespace SocketHttpListener.Net public long ContentLength64 { - get { return content_length; } + get { return is_chunked ? -1 : content_length; } } public string ContentType -- cgit v1.2.3 From a0934e62261f0fc8788efb13c653973c16d02d3e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 13 Mar 2017 16:42:21 -0400 Subject: continue with tuner discovery --- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 14 ++++++++++++++ Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 5 +++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 1 + MediaBrowser.Api/LiveTv/LiveTvService.cs | 15 ++++++++++++++- MediaBrowser.Controller/Entities/Video.cs | 3 ++- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 1 + MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 6 ++++++ 7 files changed, 43 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index a7ccafd69..42e8c4f5f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2543,6 +2543,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public CancellationTokenSource CancellationTokenSource { get; set; } } + public async Task> DiscoverTuners(CancellationToken cancellationToken) + { + var list = new List(); + + foreach (var host in _liveTvManager.TunerHosts) + { + var discoveredDevices = await DiscoverDevices(host, 3000, cancellationToken).ConfigureAwait(false); + + list.AddRange(discoveredDevices); + } + + return list; + } + public async Task ScanForTunerDeviceChanges(CancellationToken cancellationToken) { foreach (var host in _liveTvManager.TunerHosts) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index de39d3838..92ef24dea 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -160,6 +160,11 @@ namespace Emby.Server.Implementations.LiveTv }).ToList(); } + public Task> DiscoverTuners(CancellationToken cancellationToken) + { + return EmbyTV.EmbyTV.Current.DiscoverTuners(cancellationToken); + } + void service_DataSourceChanged(object sender, EventArgs e) { if (!_isDisposed) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index dbcabd174..6d6730855 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -706,6 +706,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var modelInfo = await GetModelInfo(hostInfo, false, cancellationToken).ConfigureAwait(false); hostInfo.DeviceId = modelInfo.DeviceID; + hostInfo.FriendlyName = modelInfo.FriendlyName; return hostInfo; } diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 639021762..2f7d04936 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -677,7 +677,14 @@ namespace MediaBrowser.Api.LiveTv [Authenticated] public class GetTunerHostTypes : IReturn> { - + + } + + [Route("/LiveTv/Tuners/Discvover", "GET")] + [Authenticated] + public class DiscoverTuners : IReturn> + { + } public class LiveTvService : BaseApiService @@ -730,6 +737,12 @@ namespace MediaBrowser.Api.LiveTv }; } + public async Task Get(DiscoverTuners request) + { + var result = await _liveTvManager.DiscoverTuners(CancellationToken.None).ConfigureAwait(false); + return ToOptimizedResult(result); + } + public async Task Get(GetLiveStreamFile request) { var directStreamProvider = (await _liveTvManager.GetEmbyTvLiveStream(request.Id).ConfigureAwait(false)) as IDirectStreamProvider; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 78f907d61..890626419 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -614,7 +614,8 @@ namespace MediaBrowser.Controller.Entities Timestamp = i.Timestamp, Type = type, PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(), - SupportsDirectStream = i.VideoType == VideoType.VideoFile + SupportsDirectStream = i.VideoType == VideoType.VideoFile, + IsRemote = i.IsShortcut }; if (info.Protocol == MediaProtocol.File) diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index b3467fbbc..0dda303a3 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -382,6 +382,7 @@ namespace MediaBrowser.Controller.LiveTv List ListingProviders { get; } List GetTunerHostTypes(); + Task> DiscoverTuners(CancellationToken cancellationToken); event EventHandler> SeriesTimerCancelled; event EventHandler> TimerCancelled; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index ebcc9853a..6482b6829 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -185,6 +185,12 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } + // obviously don't do this for strm files + if (string.Equals(container, "strm", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + return container; } -- cgit v1.2.3 From ce1ed2bea7492a4e6c4dd26e1a8d73aa65a88236 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 15 Mar 2017 15:57:18 -0400 Subject: update hls to support mpeg2video --- Emby.Dlna/Didl/DidlBuilder.cs | 4 +- Emby.Dlna/PlayTo/PlayToController.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 12 ++- .../LiveTv/LiveTvManager.cs | 4 +- MediaBrowser.Api/LiveTv/LiveTvService.cs | 4 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 14 +++ MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 28 +++-- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 41 +++---- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 2 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 12 +-- MediaBrowser.Api/Playback/StreamRequest.cs | 1 + MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 10 +- .../MediaEncoding/EncodingJobOptions.cs | 4 +- .../Subtitles/SubtitleEncoder.cs | 19 ++-- MediaBrowser.Model/Dlna/ProfileConditionValue.cs | 3 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 34 +++++- MediaBrowser.Model/Dlna/StreamInfo.cs | 52 ++++++++- .../Music/MusicBrainzAlbumProvider.cs | 120 +++++++++++++++------ SharedVersion.cs | 2 +- 20 files changed, 263 insertions(+), 107 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index d048dcde1..c7eae91dd 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -208,7 +208,7 @@ namespace Emby.Dlna.Didl var targetHeight = streamInfo.TargetHeight; var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container, - streamInfo.VideoCodec, + streamInfo.TargetVideoCodec, streamInfo.TargetAudioCodec, targetWidth, targetHeight, @@ -352,7 +352,7 @@ namespace Emby.Dlna.Didl var mediaProfile = _profile.GetVideoMediaProfile(streamInfo.Container, streamInfo.TargetAudioCodec, - streamInfo.VideoCodec, + streamInfo.TargetVideoCodec, streamInfo.TargetAudioBitrate, targetWidth, targetHeight, diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 3c07e95db..b73332c4b 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -542,7 +542,7 @@ namespace Emby.Dlna.PlayTo { var list = new ContentFeatureBuilder(profile) .BuildVideoHeader(streamInfo.Container, - streamInfo.VideoCodec, + streamInfo.TargetVideoCodec, streamInfo.TargetAudioCodec, streamInfo.TargetWidth, streamInfo.TargetHeight, diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index d18004f96..eea562524 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2545,14 +2545,24 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private const int TunerDiscoveryDurationMs = 3000; - public async Task> DiscoverTuners(CancellationToken cancellationToken) + public async Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) { var list = new List(); + var configuredDeviceIds = GetConfiguration().TunerHosts + .Where(i => !string.IsNullOrWhiteSpace(i.DeviceId)) + .Select(i => i.DeviceId) + .ToList(); + foreach (var host in _liveTvManager.TunerHosts) { var discoveredDevices = await DiscoverDevices(host, TunerDiscoveryDurationMs, cancellationToken).ConfigureAwait(false); + if (newDevicesOnly) + { + discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparer.OrdinalIgnoreCase)) + .ToList(); + } list.AddRange(discoveredDevices); } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 92ef24dea..8406d44a7 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -160,9 +160,9 @@ namespace Emby.Server.Implementations.LiveTv }).ToList(); } - public Task> DiscoverTuners(CancellationToken cancellationToken) + public Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) { - return EmbyTV.EmbyTV.Current.DiscoverTuners(cancellationToken); + return EmbyTV.EmbyTV.Current.DiscoverTuners(newDevicesOnly, cancellationToken); } void service_DataSourceChanged(object sender, EventArgs e) diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 2f7d04936..2d8744f70 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -684,7 +684,7 @@ namespace MediaBrowser.Api.LiveTv [Authenticated] public class DiscoverTuners : IReturn> { - + public bool NewDevicesOnly { get; set; } } public class LiveTvService : BaseApiService @@ -739,7 +739,7 @@ namespace MediaBrowser.Api.LiveTv public async Task Get(DiscoverTuners request) { - var result = await _liveTvManager.DiscoverTuners(CancellationToken.None).ConfigureAwait(false); + var result = await _liveTvManager.DiscoverTuners(request.NewDevicesOnly, CancellationToken.None).ConfigureAwait(false); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index e1559cabf..b3a00cc92 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -697,6 +697,20 @@ namespace MediaBrowser.Api.Playback { 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); + } + } } } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index aaca1793c..98115b840 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -41,9 +41,16 @@ namespace MediaBrowser.Api.Playback.Hls /// /// Gets the segment file extension. /// - /// The state. - /// System.String. - protected abstract string GetSegmentFileExtension(StreamState state); + protected string GetSegmentFileExtension(StreamRequest request) + { + var segmentContainer = request.SegmentContainer; + if (!string.IsNullOrWhiteSpace(segmentContainer)) + { + return "." + segmentContainer; + } + + return ".ts"; + } /// /// Gets the type of the transcoding job. @@ -261,11 +268,17 @@ namespace MediaBrowser.Api.Playback.Hls var useGenericSegmenter = false; if (useGenericSegmenter) { - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); + var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var timeDeltaParam = String.Empty; - return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + var segmentFormat = GetSegmentFileExtension(state.Request).TrimStart('.'); + if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) + { + segmentFormat = "mpegts"; + } + + return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, EncodingHelper.GetInputArgument(state, encodingOptions), threads, @@ -276,7 +289,8 @@ namespace MediaBrowser.Api.Playback.Hls startNumberParam, outputPath, outputTsArg, - timeDeltaParam + timeDeltaParam, + segmentFormat ).Trim(); } @@ -286,7 +300,7 @@ namespace MediaBrowser.Api.Playback.Hls var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero {6} -hls_time {7} -individual_header_trailer 0 -start_number {8} -hls_list_size {9}{10} -y \"{11}\"", itsOffset, inputModifier, - EncodingHelper.GetInputArgument(state, encodingOptions), + EncodingHelper.GetInputArgument(state, encodingOptions), threads, EncodingHelper.GetMapArgs(state), GetVideoArguments(state), diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 1074a8bc1..f77a66f8e 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Api.Playback.Hls { } - [Route("/Videos/{Id}/hls1/{PlaylistId}/{SegmentId}.ts", "GET")] + [Route("/Videos/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")] public class GetHlsVideoSegment : VideoStreamRequest { public string PlaylistId { get; set; } @@ -77,8 +77,7 @@ namespace MediaBrowser.Api.Playback.Hls public string SegmentId { get; set; } } - [Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.aac", "GET")] - [Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.ts", "GET")] + [Route("/Audio/{Id}/hls1/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")] public class GetHlsAudioSegment : StreamRequest { public string PlaylistId { get; set; } @@ -158,7 +157,7 @@ namespace MediaBrowser.Api.Playback.Hls var segmentPath = GetSegmentPath(state, playlistPath, requestedIndex); - var segmentExtension = GetSegmentFileExtension(state); + var segmentExtension = GetSegmentFileExtension(state.Request); TranscodingJob job = null; @@ -420,7 +419,7 @@ namespace MediaBrowser.Api.Playback.Hls var filename = Path.GetFileNameWithoutExtension(playlist); - return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state)); + return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state.Request)); } private async Task GetSegmentResult(StreamState state, string playlistPath, @@ -740,7 +739,7 @@ namespace MediaBrowser.Api.Playback.Hls name, index.ToString(UsCulture), - GetSegmentFileExtension(isOutputVideo), + GetSegmentFileExtension(request), queryString)); index++; @@ -848,7 +847,7 @@ namespace MediaBrowser.Api.Playback.Hls var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - args += " " + EncodingHelper.GetVideoQualityParam(state, EncodingHelper.GetH264Encoder(state, encodingOptions), encodingOptions, GetDefaultH264Preset()) + keyFrameArg; + args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg; //args += " -mixed-refs 0 -refs 3 -x264opts b_pyramid=0:weightb=0:weightp=0"; @@ -897,7 +896,7 @@ namespace MediaBrowser.Api.Playback.Hls if (useGenericSegmenter) { - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); + var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request); var timeDeltaParam = String.Empty; @@ -907,7 +906,13 @@ namespace MediaBrowser.Api.Playback.Hls timeDeltaParam = string.Format("-segment_time_delta -{0}", startTime); } - return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + var segmentFormat = GetSegmentFileExtension(state.Request).TrimStart('.'); + if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) + { + segmentFormat = "mpegts"; + } + + return string.Format("{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} {10} -individual_header_trailer 0 -segment_format {11} -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, EncodingHelper.GetInputArgument(state, encodingOptions), threads, @@ -918,7 +923,8 @@ namespace MediaBrowser.Api.Playback.Hls startNumberParam, outputPath, outputTsArg, - timeDeltaParam + timeDeltaParam, + segmentFormat ).Trim(); } @@ -935,20 +941,5 @@ namespace MediaBrowser.Api.Playback.Hls outputPath ).Trim(); } - - /// - /// Gets the segment file extension. - /// - /// The state. - /// System.String. - protected override string GetSegmentFileExtension(StreamState state) - { - return GetSegmentFileExtension(state.IsOutputVideo); - } - - protected string GetSegmentFileExtension(bool isOutputVideo) - { - return isOutputVideo ? ".ts" : ".ts"; - } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index f3683c6cb..bf78e16b3 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Api.Playback.Hls /// /// Class GetHlsVideoSegment /// - [Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.ts", "GET")] + [Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")] public class GetHlsVideoSegmentLegacy : VideoStreamRequest { public string PlaylistId { get; set; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index c9c6acc1b..f9164c36f 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -99,7 +99,7 @@ namespace MediaBrowser.Api.Playback.Hls var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - args += " " + EncodingHelper.GetVideoQualityParam(state, EncodingHelper.GetH264Encoder(state, encodingOptions), encodingOptions, GetDefaultH264Preset()) + keyFrameArg; + args += " " + EncodingHelper.GetVideoQualityParam(state, codec, encodingOptions, GetDefaultH264Preset()) + keyFrameArg; // Add resolution params, if specified if (!hasGraphicalSubs) @@ -118,16 +118,6 @@ namespace MediaBrowser.Api.Playback.Hls return args; } - /// - /// Gets the segment file extension. - /// - /// The state. - /// System.String. - protected override string GetSegmentFileExtension(StreamState state) - { - return ".ts"; - } - public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext) { } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index f223c99ef..d1bf9c120 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -41,6 +41,7 @@ namespace MediaBrowser.Api.Playback public string PlaySessionId { get; set; } public string LiveStreamId { get; set; } public string Tag { get; set; } + public string SegmentContainer { get; set; } } public class VideoStreamRequest : StreamRequest diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 0dda303a3..5242c5b1f 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -382,7 +382,7 @@ namespace MediaBrowser.Controller.LiveTv List ListingProviders { get; } List GetTunerHostTypes(); - Task> DiscoverTuners(CancellationToken cancellationToken); + Task> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken); event EventHandler> SeriesTimerCancelled; event EventHandler> TimerCancelled; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 6482b6829..db23712ba 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -733,12 +733,18 @@ namespace MediaBrowser.Controller.MediaEncoding if (videoStream.IsInterlaced) { - return false; + if (request.DeInterlace) + { + return false; + } } if (videoStream.IsAnamorphic ?? false) { - return false; + if (request.RequireNonAnamorphic) + { + return false; + } } // Can't stream copy if we're burning in subtitles diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 4bb180d4b..6baf87a04 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.MediaEncoding AudioBitRate = info.AudioBitrate; AudioSampleRate = info.TargetAudioSampleRate; DeviceProfile = deviceProfile; - VideoCodec = info.VideoCodec; + VideoCodec = info.TargetVideoCodec; VideoBitRate = info.VideoBitrate; AudioStreamIndex = info.AudioStreamIndex; MaxRefFrames = info.MaxRefFrames; @@ -185,6 +185,8 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "MaxVideoBitDepth", Description = "Optional.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? MaxVideoBitDepth { get; set; } public bool RequireAvc { get; set; } + public bool DeInterlace { get; set; } + public bool RequireNonAnamorphic { get; set; } public int? TranscodingMaxAudioChannels { get; set; } public int? CpuCoreLimit { get; set; } public string OutputContainer { get; set; } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 4a1bf5305..77b976206 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -734,16 +734,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - var charsetFromLanguage = string.IsNullOrWhiteSpace(language) - ? null - : GetSubtitleFileCharacterSetFromLanguage(language); - - // This assumption should only be made for external subtitles - if (!string.IsNullOrWhiteSpace(charsetFromLanguage) && !string.Equals(charsetFromLanguage, "windows-1252", StringComparison.OrdinalIgnoreCase)) - { - return charsetFromLanguage; - } - var charset = await DetectCharset(path, language, protocol, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(charset)) @@ -756,7 +746,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles return charset; } - return charsetFromLanguage; + if (!string.IsNullOrWhiteSpace(language)) + { + return GetSubtitleFileCharacterSetFromLanguage(language); + } + + return null; } public string GetSubtitleFileCharacterSetFromLanguage(string language) @@ -854,4 +849,4 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentOutOfRangeException("protocol"); } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs index 7e2002f17..dbd574f86 100644 --- a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs +++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs @@ -21,6 +21,7 @@ NumVideoStreams = 17, IsSecondaryAudio = 18, VideoCodecTag = 19, - IsAvc = 20 + IsAvc = 20, + IsInterlaced = 21 } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 480eb23a5..80d3ea3fb 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -231,6 +231,7 @@ namespace MediaBrowser.Model.Dlna { playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(','); } + playlistItem.SubProtocol = transcodingProfile.Protocol; List audioCodecProfiles = new List(); @@ -479,7 +480,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.AudioCodecs = transcodingProfile.AudioCodec.Split(','); - playlistItem.VideoCodec = transcodingProfile.VideoCodec; + playlistItem.VideoCodecs = transcodingProfile.VideoCodec.Split(','); playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; @@ -1137,6 +1138,37 @@ namespace MediaBrowser.Model.Dlna break; } case ProfileConditionValue.IsAnamorphic: + { + bool isAnamorphic; + if (bool.TryParse(value, out isAnamorphic)) + { + if (isAnamorphic && condition.Condition == ProfileConditionType.Equals) + { + item.RequireNonAnamorphic = true; + } + else if (!isAnamorphic && condition.Condition == ProfileConditionType.NotEquals) + { + item.RequireNonAnamorphic = true; + } + } + break; + } + case ProfileConditionValue.IsInterlaced: + { + bool isInterlaced; + if (bool.TryParse(value, out isInterlaced)) + { + if (isInterlaced && condition.Condition == ProfileConditionType.Equals) + { + item.DeInterlace = true; + } + else if (!isInterlaced && condition.Condition == ProfileConditionType.NotEquals) + { + item.DeInterlace = true; + } + } + break; + } case ProfileConditionValue.AudioProfile: case ProfileConditionValue.Has64BitOffsets: case ProfileConditionValue.PacketLength: diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index a85e6085b..7e42e7fae 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Model.Dlna public StreamInfo() { AudioCodecs = new string[] { }; + VideoCodecs = new string[] { }; SubtitleCodecs = new string[] { }; } @@ -34,13 +35,15 @@ namespace MediaBrowser.Model.Dlna public long StartPositionTicks { get; set; } - public string VideoCodec { get; set; } public string VideoProfile { get; set; } public bool RequireAvc { get; set; } + public bool DeInterlace { get; set; } + public bool RequireNonAnamorphic { get; set; } public bool CopyTimestamps { get; set; } public bool EnableSubtitlesInManifest { get; set; } public string[] AudioCodecs { get; set; } + public string[] VideoCodecs { get; set; } public int? AudioStreamIndex { get; set; } @@ -204,11 +207,15 @@ namespace MediaBrowser.Model.Dlna string.Empty : string.Join(",", item.AudioCodecs); + string videoCodecs = item.VideoCodecs.Length == 0 ? + string.Empty : + string.Join(",", item.VideoCodecs); + list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty)); list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty)); list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty)); list.Add(new NameValuePair("Static", item.IsDirectStream.ToString().ToLower())); - list.Add(new NameValuePair("VideoCodec", item.VideoCodec ?? string.Empty)); + list.Add(new NameValuePair("VideoCodec", videoCodecs)); list.Add(new NameValuePair("AudioCodec", audioCodecs)); list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty)); list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty)); @@ -232,7 +239,9 @@ namespace MediaBrowser.Model.Dlna // } //} - if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !forceStartPosition) + var isHls = StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls"); + + if (isHls && !forceStartPosition) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -276,6 +285,14 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed ? subtitleCodecs : string.Empty)); + list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString().ToLower())); + list.Add(new NameValuePair("DeInterlace", item.DeInterlace.ToString().ToLower())); + + if (!isDlna && isHls) + { + list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty)); + } + return list; } @@ -609,9 +626,34 @@ namespace MediaBrowser.Model.Dlna } } + public string TargetVideoCodec + { + get + { + MediaStream stream = TargetVideoStream; + + string inputCodec = stream == null ? null : stream.Codec; + + if (IsDirectStream) + { + return inputCodec; + } + + foreach (string codec in VideoCodecs) + { + if (StringHelper.EqualsIgnoreCase(codec, inputCodec)) + { + return codec; + } + } + + return VideoCodecs.Length == 0 ? null : VideoCodecs[0]; + } + } + /// - /// Predicts the audio channels that will be in the output stream - /// + /// Predicts the audio channels that will be in the output stream + /// public long? TargetSize { get diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index e6eb0951d..4aefb62c8 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -45,14 +45,21 @@ namespace MediaBrowser.Providers.Music public async Task> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) { var releaseId = searchInfo.GetReleaseId(); + var releaseGroupId = searchInfo.GetReleaseGroupId(); string url = null; var isNameSearch = false; + bool forceMusicBrainzProper = false; if (!string.IsNullOrEmpty(releaseId)) { url = string.Format("/ws/2/release/?query=reid:{0}", releaseId); } + else if (!string.IsNullOrEmpty(releaseGroupId)) + { + url = string.Format("/ws/2/release?release-group={0}", releaseGroupId); + forceMusicBrainzProper = true; + } else { var artistMusicBrainzId = searchInfo.GetMusicBrainzArtistId(); @@ -75,7 +82,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrWhiteSpace(url)) { - using (var stream = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false)) + using (var stream = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false)) { return GetResultsFromResponse(stream); } @@ -131,7 +138,14 @@ namespace MediaBrowser.Providers.Music Item = new MusicAlbum() }; - if (string.IsNullOrEmpty(releaseId)) + // If we have a release group Id but not a release Id... + if (string.IsNullOrWhiteSpace(releaseId) && !string.IsNullOrWhiteSpace(releaseGroupId)) + { + releaseId = await GetReleaseIdFromReleaseGroupId(releaseGroupId, cancellationToken).ConfigureAwait(false); + result.HasMetadata = true; + } + + if (string.IsNullOrWhiteSpace(releaseId)) { var artistMusicBrainzId = id.GetMusicBrainzArtistId(); @@ -139,13 +153,13 @@ namespace MediaBrowser.Providers.Music if (releaseResult != null) { - if (!string.IsNullOrEmpty(releaseResult.ReleaseId)) + if (!string.IsNullOrWhiteSpace(releaseResult.ReleaseId)) { releaseId = releaseResult.ReleaseId; result.HasMetadata = true; } - if (!string.IsNullOrEmpty(releaseResult.ReleaseGroupId)) + if (!string.IsNullOrWhiteSpace(releaseResult.ReleaseGroupId)) { releaseGroupId = releaseResult.ReleaseGroupId; result.HasMetadata = true; @@ -157,13 +171,13 @@ namespace MediaBrowser.Providers.Music } // If we have a release Id but not a release group Id... - if (!string.IsNullOrEmpty(releaseId) && string.IsNullOrEmpty(releaseGroupId)) + if (!string.IsNullOrWhiteSpace(releaseId) && string.IsNullOrWhiteSpace(releaseGroupId)) { - releaseGroupId = await GetReleaseGroupId(releaseId, cancellationToken).ConfigureAwait(false); + releaseGroupId = await GetReleaseGroupFromReleaseId(releaseId, cancellationToken).ConfigureAwait(false); result.HasMetadata = true; } - if (!string.IsNullOrEmpty(releaseId) || !string.IsNullOrEmpty(releaseGroupId)) + if (!string.IsNullOrWhiteSpace(releaseId) || !string.IsNullOrWhiteSpace(releaseGroupId)) { result.HasMetadata = true; } @@ -411,13 +425,42 @@ namespace MediaBrowser.Providers.Music } } + private async Task GetReleaseIdFromReleaseGroupId(string releaseGroupId, CancellationToken cancellationToken) + { + var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId); + + using (var stream = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false)) + { + using (var oReader = new StreamReader(stream, Encoding.UTF8)) + { + var settings = _xmlSettings.Create(false); + + settings.CheckCharacters = false; + settings.IgnoreProcessingInstructions = true; + settings.IgnoreComments = true; + + using (var reader = XmlReader.Create(oReader, settings)) + { + var result = ReleaseResult.Parse(reader).FirstOrDefault(); + + if (result != null) + { + return result.ReleaseId; + } + } + } + } + + return null; + } + /// /// Gets the release group id internal. /// /// The release entry id. /// The cancellation token. /// Task{System.String}. - private async Task GetReleaseGroupId(string releaseEntryId, CancellationToken cancellationToken) + private async Task GetReleaseGroupFromReleaseId(string releaseEntryId, CancellationToken cancellationToken) { var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId); @@ -514,11 +557,11 @@ namespace MediaBrowser.Providers.Music private List _mbzUrls = null; private MbzUrl _chosenUrl; - private async Task GetMbzUrl() + private async Task GetMbzUrl(bool forceMusicBrainzProper = false) { if (_chosenUrl == null || _mbzUrls == null || (DateTime.UtcNow.Ticks - _lastMbzUrlQueryTicks) > TimeSpan.FromHours(12).Ticks) { - var urls = await RefreshMzbUrls().ConfigureAwait(false); + var urls = await RefreshMzbUrls(forceMusicBrainzProper).ConfigureAwait(false); if (urls.Count > 1) { @@ -533,31 +576,44 @@ namespace MediaBrowser.Providers.Music return _chosenUrl; } - private async Task> RefreshMzbUrls() + private async Task> RefreshMzbUrls(bool forceMusicBrainzProper = false) { List list; - try + if (forceMusicBrainzProper) { - var options = new HttpRequestOptions + list = new List { - Url = "https://mb3admin.com/admin/service/standards/musicBrainzUrls", - UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion + new MbzUrl + { + url = MusicBrainzBaseUrl, + throttleMs = 1000 + } }; - - using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) + } + else + { + try { - var results = _json.DeserializeFromStream>(stream); + var options = new HttpRequestOptions + { + Url = "https://mb3admin.com/admin/service/standards/musicBrainzUrls", + UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion + }; + + using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) + { + var results = _json.DeserializeFromStream>(stream); - list = results; + list = results; + } + _lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks; } - _lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks; - } - catch (Exception ex) - { - _logger.ErrorException("Error getting music brainz info", ex); + catch (Exception ex) + { + _logger.ErrorException("Error getting music brainz info", ex); - list = new List + list = new List { new MbzUrl { @@ -565,6 +621,7 @@ namespace MediaBrowser.Providers.Music throttleMs = 1000 } }; + } } _mbzUrls = list.ToList(); @@ -572,16 +629,17 @@ namespace MediaBrowser.Providers.Music return list; } + internal Task GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken) + { + return GetMusicBrainzResponse(url, isSearch, false, cancellationToken); + } + /// /// Gets the music brainz response. /// - /// The URL. - /// if set to true [is search]. - /// The cancellation token. - /// Task{XmlDocument}. - internal async Task GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken) + internal async Task GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken) { - var urlInfo = await GetMbzUrl().ConfigureAwait(false); + var urlInfo = await GetMbzUrl(forceMusicBrainzProper).ConfigureAwait(false); var throttleMs = urlInfo.throttleMs; if (throttleMs > 0) diff --git a/SharedVersion.cs b/SharedVersion.cs index b001cfb52..1c2997eed 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.7.5")] +[assembly: AssemblyVersion("3.2.8.1")] -- cgit v1.2.3 From 59ac045c6b875fd9ed8dc2ecc2ca580ba4fdab2d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Mar 2017 02:10:11 -0400 Subject: increase unification of param building --- MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs | 6 +- .../Progressive/BaseProgressiveStreamingService.cs | 3 - .../Playback/Progressive/VideoService.cs | 74 +--------------------- MediaBrowser.Api/Playback/StreamRequest.cs | 2 - MediaBrowser.Api/Playback/StreamState.cs | 3 - .../MediaEncoding/EncodingHelper.cs | 74 ++++++++++++++++++++++ .../MediaEncoding/EncodingJobInfo.cs | 5 +- .../MediaEncoding/EncodingJobOptions.cs | 2 + MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 1 - .../Encoder/EncodingJobFactory.cs | 11 +++- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 45 +------------ 12 files changed, 98 insertions(+), 130 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index bf78e16b3..03291670b 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -109,11 +109,13 @@ namespace MediaBrowser.Api.Playback.Hls public Task Get(GetHlsVideoSegmentLegacy request) { var file = request.SegmentId + Path.GetExtension(Request.PathInfo); - file = Path.Combine(_config.ApplicationPaths.TranscodingTempPath, file); + + var transcodeFolderPath = _config.ApplicationPaths.TranscodingTempPath; + file = Path.Combine(transcodeFolderPath, file); var normalizedPlaylistId = request.PlaylistId; - var playlistPath = _fileSystem.GetFilePaths(_config.ApplicationPaths.TranscodingTempPath) + var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath) .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); return GetFileResult(file, playlistPath); diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 23a84e480..441fff849 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -15,9 +15,6 @@ using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Playback.Progressive diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index bc600d3ea..228f50eab 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -1,4 +1,3 @@ -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -9,12 +8,8 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using System; using System.IO; -using System.Linq; using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; @@ -116,11 +111,6 @@ namespace MediaBrowser.Api.Playback.Progressive var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions); - var subtitleArguments = state.SubtitleStream != null && - state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed - ? GetSubtitleArguments(state) - : string.Empty; - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", inputModifier, EncodingHelper.GetInputArgument(state, encodingOptions), @@ -128,30 +118,13 @@ namespace MediaBrowser.Api.Playback.Progressive EncodingHelper.GetMapArgs(state), GetVideoArguments(state, videoCodec), threads, - GetAudioArguments(state), - subtitleArguments, + EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), + EncodingHelper.GetSubtitleEmbedArguments(state), format, outputPath ).Trim(); } - private string GetSubtitleArguments(StreamState state) - { - var format = state.SupportedSubtitleCodecs.FirstOrDefault(); - string codec; - - if (string.IsNullOrWhiteSpace(format) || string.Equals(format, state.SubtitleStream.Codec, StringComparison.OrdinalIgnoreCase)) - { - codec = "copy"; - } - else - { - codec = format; - } - - return " -codec:s:0 " + codec; - } - /// /// Gets video arguments to pass to ffmpeg /// @@ -233,48 +206,5 @@ namespace MediaBrowser.Api.Playback.Progressive return args; } - - /// - /// Gets audio arguments to pass to ffmpeg - /// - /// The state. - /// System.String. - private string GetAudioArguments(StreamState state) - { - // If the video doesn't have an audio stream, return a default. - if (state.AudioStream == null && state.VideoStream != null) - { - return string.Empty; - } - - // Get the output codec name - var codec = EncodingHelper.GetAudioEncoder(state); - - var args = "-codec:a:0 " + codec; - - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) - { - return args; - } - - // Add the number of audio channels - var channels = state.OutputAudioChannels; - - if (channels.HasValue) - { - args += " -ac " + channels.Value; - } - - var bitrate = state.OutputAudioBitrate; - - if (bitrate.HasValue) - { - args += " -ab " + bitrate.Value.ToString(UsCulture); - } - - args += " " + EncodingHelper.GetAudioFilterParam(state, ApiEntryPoint.Instance.GetEncodingOptions(), false); - - return args; - } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index f49fd87e0..551dbf378 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -32,8 +32,6 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "AudioCodec", Description = "Optional. Specify a audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. Options: aac, mp3, vorbis, wma.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string AudioCodec { get; set; } - public string SubtitleCodec { get; set; } - [ApiMember(Name = "DeviceProfileId", Description = "Optional. The dlna device profile id to utilize.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string DeviceProfileId { get; set; } diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index 22a0fa7c9..afc48b64c 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -120,7 +120,6 @@ namespace MediaBrowser.Api.Playback } } - public List SupportedSubtitleCodecs { get; set; } public string UserAgent { get; set; } public TranscodingJobType TranscodingType { get; set; } @@ -129,7 +128,6 @@ namespace MediaBrowser.Api.Playback { _mediaSourceManager = mediaSourceManager; _logger = logger; - SupportedSubtitleCodecs = new List(); TranscodingType = transcodingType; } @@ -209,7 +207,6 @@ namespace MediaBrowser.Api.Playback } public string OutputFilePath { get; set; } - public int? OutputAudioBitrate; public string ActualOutputVideoCodec { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index c73170fcf..8a1e2698a 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1736,5 +1736,79 @@ namespace MediaBrowser.Controller.MediaEncoding return threads; } + + public string GetSubtitleEmbedArguments(EncodingJobInfo state) + { + if (state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Embed) + { + return string.Empty; + } + + var format = state.SupportedSubtitleCodecs.FirstOrDefault(); + string codec; + + if (string.IsNullOrWhiteSpace(format) || string.Equals(format, state.SubtitleStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + codec = "copy"; + } + else + { + codec = format; + } + + // Muxing in dvbsub via either copy or -codec dvbsub does not seem to work + // It doesn't throw any errors but vlc on android will not render them + // They will need to be converted to an alternative format + // TODO: This is incorrectly assuming that dvdsub will be supported by the player + // The api will need to be expanded to accomodate this. + if (string.Equals(state.SubtitleStream.Codec, "DVBSUB", StringComparison.OrdinalIgnoreCase)) + { + codec = "dvdsub"; + } + + var args = " -codec:s:0 " + codec; + + args += " -disposition:s:0 default"; + + return args; + } + + public string GetProgressiveVideoAudioArguments(EncodingJobInfo state, EncodingOptions encodingOptions) + { + // If the video doesn't have an audio stream, return a default. + if (state.AudioStream == null && state.VideoStream != null) + { + return string.Empty; + } + + // Get the output codec name + var codec = GetAudioEncoder(state); + + var args = "-codec:a:0 " + codec; + + if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) + { + return args; + } + + // Add the number of audio channels + var channels = state.OutputAudioChannels; + + if (channels.HasValue) + { + args += " -ac " + channels.Value; + } + + var bitrate = state.OutputAudioBitrate; + + if (bitrate.HasValue) + { + args += " -ab " + bitrate.Value.ToString(_usCulture); + } + + args += " " + GetAudioFilterParam(state, encodingOptions, false); + + return args; + } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index a18b86432..ac33b8c8c 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.MediaEncoding public int? OutputVideoBitrate { get; set; } public MediaStream SubtitleStream { get; set; } public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; } + public List SupportedSubtitleCodecs { get; set; } public int InternalSubtitleStreamOffset { get; set; } public MediaSourceInfo MediaSource { get; set; } @@ -64,6 +65,7 @@ namespace MediaBrowser.Controller.MediaEncoding get { return BaseRequest.CopyTimestamps; } } + public int? OutputAudioBitrate; public int? OutputAudioChannels; public int? OutputAudioSampleRate; public bool DeInterlace { get; set; } @@ -74,8 +76,9 @@ namespace MediaBrowser.Controller.MediaEncoding _logger = logger; RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); PlayableStreamFileNames = new List(); + SupportedAudioCodecs = new List(); SupportedVideoCodecs = new List(); - SupportedVideoCodecs = new List(); + SupportedSubtitleCodecs = new List(); } /// diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 6baf87a04..41f146375 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -198,6 +198,8 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "VideoCodec", Description = "Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. Options: h264, mpeg4, theora, vpx, wmv.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string VideoCodec { get; set; } + public string SubtitleCodec { get; set; } + /// /// Gets or sets the index of the audio stream. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index b0b37f2d6..635c8deac 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.MediaEncoding.Encoder IProgress progress, CancellationToken cancellationToken) { - var encodingJob = await new EncodingJobFactory(Logger, LibraryManager, MediaSourceManager, ConfigurationManager) + var encodingJob = await new EncodingJobFactory(Logger, LibraryManager, MediaSourceManager, ConfigurationManager, MediaEncoder) .CreateJob(options, EncodingHelper, IsVideoEncoder, progress, cancellationToken).ConfigureAwait(false); encodingJob.OutputFilePath = GetOutputFilePath(encodingJob); diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index f6895696a..1b26d3b2a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -109,7 +109,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } public string OutputFilePath { get; set; } - public int? OutputAudioBitrate; public string ActualOutputVideoCodec { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 4b336e671..3e99d68ce 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -22,15 +22,17 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IConfigurationManager _config; + private readonly IMediaEncoder _mediaEncoder; protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - public EncodingJobFactory(ILogger logger, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, IConfigurationManager config) + public EncodingJobFactory(ILogger logger, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, IConfigurationManager config, IMediaEncoder mediaEncoder) { _logger = logger; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; _config = config; + _mediaEncoder = mediaEncoder; } public async Task CreateJob(EncodingJobOptions options, EncodingHelper encodingHelper, bool isVideoRequest, IProgress progress, CancellationToken cancellationToken) @@ -61,6 +63,13 @@ namespace MediaBrowser.MediaEncoding.Encoder request.AudioCodec = state.SupportedAudioCodecs.FirstOrDefault(); } + if (!string.IsNullOrWhiteSpace(request.SubtitleCodec)) + { + state.SupportedSubtitleCodecs = request.SubtitleCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); + request.SubtitleCodec = state.SupportedSubtitleCodecs.FirstOrDefault(i => _mediaEncoder.CanEncodeToSubtitleCodec(i)) + ?? state.SupportedSubtitleCodecs.FirstOrDefault(); + } + var item = _libraryManager.GetItemById(request.ItemId); state.ItemType = item.GetType().Name; diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 52ef4d834..a779c1bca 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Encoder EncodingHelper.GetMapArgs(state), videoArguments, threads, - GetAudioArguments(state), + EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), format, state.OutputFilePath ).Trim(); @@ -114,49 +114,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return args; } - /// - /// Gets audio arguments to pass to ffmpeg - /// - /// The state. - /// System.String. - private string GetAudioArguments(EncodingJob state) - { - // If the video doesn't have an audio stream, return a default. - if (state.AudioStream == null && state.VideoStream != null) - { - return string.Empty; - } - - // Get the output codec name - var codec = EncodingHelper.GetAudioEncoder(state); - - var args = "-codec:a:0 " + codec; - - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) - { - return args; - } - - // Add the number of audio channels - var channels = state.OutputAudioChannels; - - if (channels.HasValue) - { - args += " -ac " + channels.Value; - } - - var bitrate = state.OutputAudioBitrate; - - if (bitrate.HasValue) - { - args += " -ab " + bitrate.Value.ToString(UsCulture); - } - - args += " " + EncodingHelper.GetAudioFilterParam(state, GetEncodingOptions(), false); - - return args; - } - protected override string GetOutputFileExtension(EncodingJob state) { var ext = base.GetOutputFileExtension(state); -- cgit v1.2.3 From 38e05b11e2cef0ee15d8c6d0ee063db08dafde24 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 19 Mar 2017 14:59:05 -0400 Subject: unify encodng param creation --- .../Data/SqliteItemRepository.cs | 79 ++++++++++---- .../Emby.Server.Implementations.csproj | 2 - .../HttpServer/GetSwaggerResource.cs | 17 --- .../HttpServer/SwaggerService.cs | 47 --------- .../Playback/Progressive/VideoService.cs | 114 +-------------------- MediaBrowser.Api/Playback/StreamState.cs | 1 - .../MediaEncoding/EncodingHelper.cs | 108 +++++++++++++++++++ .../MediaEncoding/EncodingJobInfo.cs | 2 + .../MediaEncoding/EncodingJobOptions.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs | 1 - MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 92 +---------------- 13 files changed, 180 insertions(+), 295 deletions(-) delete mode 100644 Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs delete mode 100644 Emby.Server.Implementations/HttpServer/SwaggerService.cs (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index e65ebeb04..c5ba6c892 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3204,6 +3204,40 @@ namespace Emby.Server.Implementations.Data } } + private bool IsAlphaNumeric(string str) + { + if (string.IsNullOrWhiteSpace(str)) + return false; + + for (int i = 0; i < str.Length; i++) + { + if (!(char.IsLetter(str[i])) && (!(char.IsNumber(str[i])))) + return false; + } + + return true; + } + + private bool IsValidType(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidMediaType(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidId(string value) + { + return IsAlphaNumeric(value); + } + + private bool IsValidPersonType(string value) + { + return IsAlphaNumeric(value); + } + private List GetWhereClauses(InternalItemsQuery query, IStatement statement, string paramSuffix = "") { if (query.IsResumable ?? false) @@ -3423,9 +3457,9 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@ChannelId", query.ChannelIds[0]); } } - if (query.ChannelIds.Length > 1) + else if (query.ChannelIds.Length > 1) { - var inClause = string.Join(",", query.ChannelIds.Select(i => "'" + i + "'").ToArray()); + var inClause = string.Join(",", query.ChannelIds.Where(IsValidId).Select(i => "'" + i + "'").ToArray()); whereClauses.Add(string.Format("ChannelId in ({0})", inClause)); } @@ -4157,17 +4191,18 @@ namespace Emby.Server.Implementations.Data whereClauses.Add("(IsVirtualItem=0 OR PremiereDate < DATETIME('now'))"); } } - if (query.MediaTypes.Length == 1) + var queryMediaTypes = query.MediaTypes.Where(IsValidMediaType).ToArray(); + if (queryMediaTypes.Length == 1) { whereClauses.Add("MediaType=@MediaTypes"); if (statement != null) { - statement.TryBind("@MediaTypes", query.MediaTypes[0]); + statement.TryBind("@MediaTypes", queryMediaTypes[0]); } } - if (query.MediaTypes.Length > 1) + else if (queryMediaTypes.Length > 1) { - var val = string.Join(",", query.MediaTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryMediaTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("MediaType in (" + val + ")"); } @@ -4273,7 +4308,9 @@ namespace Emby.Server.Implementations.Data //var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0; var enableItemsByName = query.IncludeItemsByName ?? false; - if (query.TopParentIds.Length == 1) + var queryTopParentIds = query.TopParentIds.Where(IsValidId).ToArray(); + + if (queryTopParentIds.Length == 1) { if (enableItemsByName) { @@ -4289,12 +4326,12 @@ namespace Emby.Server.Implementations.Data } if (statement != null) { - statement.TryBind("@TopParentId", query.TopParentIds[0]); + statement.TryBind("@TopParentId", queryTopParentIds[0]); } } - if (query.TopParentIds.Length > 1) + else if (queryTopParentIds.Length > 1) { - var val = string.Join(",", query.TopParentIds.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryTopParentIds.Select(i => "'" + i + "'").ToArray()); if (enableItemsByName) { @@ -4544,7 +4581,7 @@ namespace Emby.Server.Implementations.Data return result; } - return new[] { value }; + return new[] { value }.Where(IsValidType); } public async Task DeleteItem(Guid id, CancellationToken cancellationToken) @@ -4696,31 +4733,35 @@ namespace Emby.Server.Implementations.Data statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToGuidParamValue()); } } - if (query.PersonTypes.Count == 1) + var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList(); + + if (queryPersonTypes.Count == 1) { whereClauses.Add("PersonType=@PersonType"); if (statement != null) { - statement.TryBind("@PersonType", query.PersonTypes[0]); + statement.TryBind("@PersonType", queryPersonTypes[0]); } } - if (query.PersonTypes.Count > 1) + else if (queryPersonTypes.Count > 1) { - var val = string.Join(",", query.PersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryPersonTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("PersonType in (" + val + ")"); } - if (query.ExcludePersonTypes.Count == 1) + var queryExcludePersonTypes = query.ExcludePersonTypes.Where(IsValidPersonType).ToList(); + + if (queryExcludePersonTypes.Count == 1) { whereClauses.Add("PersonType<>@PersonType"); if (statement != null) { - statement.TryBind("@PersonType", query.ExcludePersonTypes[0]); + statement.TryBind("@PersonType", queryExcludePersonTypes[0]); } } - if (query.ExcludePersonTypes.Count > 1) + else if (queryExcludePersonTypes.Count > 1) { - var val = string.Join(",", query.ExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); + var val = string.Join(",", queryExcludePersonTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add("PersonType not in (" + val + ")"); } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index ecd86d507..afd437fe8 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -85,7 +85,6 @@ - @@ -103,7 +102,6 @@ - diff --git a/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs b/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs deleted file mode 100644 index 819ede1ab..000000000 --- a/Emby.Server.Implementations/HttpServer/GetSwaggerResource.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediaBrowser.Model.Services; - -namespace Emby.Server.Implementations.HttpServer -{ - /// - /// Class GetDashboardResource - /// - [Route("/swagger-ui/{ResourceName*}", "GET")] - public class GetSwaggerResource - { - /// - /// Gets or sets the name. - /// - /// The name. - public string ResourceName { get; set; } - } -} \ No newline at end of file diff --git a/Emby.Server.Implementations/HttpServer/SwaggerService.cs b/Emby.Server.Implementations/HttpServer/SwaggerService.cs deleted file mode 100644 index d41946645..000000000 --- a/Emby.Server.Implementations/HttpServer/SwaggerService.cs +++ /dev/null @@ -1,47 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Net; -using System.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Services; - -namespace Emby.Server.Implementations.HttpServer -{ - public class SwaggerService : IService, IRequiresRequest - { - private readonly IServerApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public SwaggerService(IServerApplicationPaths appPaths, IFileSystem fileSystem, IHttpResultFactory resultFactory) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - _resultFactory = resultFactory; - } - - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetSwaggerResource request) - { - var swaggerDirectory = Path.Combine(_appPaths.ApplicationResourcesPath, "swagger-ui"); - - var requestedFile = Path.Combine(swaggerDirectory, request.ResourceName.Replace('/', _fileSystem.DirectorySeparatorChar)); - - return _resultFactory.GetStaticFileResult(Request, requestedFile).Result; - } - - /// - /// Gets or sets the result factory. - /// - /// The result factory. - private readonly IHttpResultFactory _resultFactory; - - /// - /// Gets or sets the request context. - /// - /// The request context. - public IRequest Request { get; set; } - } -} diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 228f50eab..8394e016c 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -6,11 +6,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using System; -using System.IO; using System.Threading.Tasks; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Services; namespace MediaBrowser.Api.Playback.Progressive @@ -95,116 +92,7 @@ namespace MediaBrowser.Api.Playback.Progressive { var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - // Get the output codec name - var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions); - - var format = string.Empty; - var keyFrame = string.Empty; - - if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase)) - { - // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js - format = " -f mp4 -movflags frag_keyframe+empty_moov"; - } - - var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); - - var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions); - - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", - inputModifier, - EncodingHelper.GetInputArgument(state, encodingOptions), - keyFrame, - EncodingHelper.GetMapArgs(state), - GetVideoArguments(state, videoCodec), - threads, - EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), - EncodingHelper.GetSubtitleEmbedArguments(state), - format, - outputPath - ).Trim(); - } - - /// - /// Gets video arguments to pass to ffmpeg - /// - /// The state. - /// The video codec. - /// System.String. - private string GetVideoArguments(StreamState state, string videoCodec) - { - var args = "-codec:v:0 " + videoCodec; - - if (state.EnableMpegtsM2TsMode) - { - args += " -mpegts_m2ts_mode 1"; - } - - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) - { - args += " -bsf:v h264_mp4toannexb"; - } - - if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) - { - args += " -copyts -avoid_negative_ts disabled -start_at_zero"; - } - - if (!state.RunTimeTicks.HasValue) - { - args += " -flags -global_header -fflags +genpts"; - } - - return args; - } - - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - 5.ToString(UsCulture)); - - args += keyFrameArg; - - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; - - var hasCopyTs = false; - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - var outputSizeParam = EncodingHelper.GetOutputSizeParam(state, videoCodec); - args += outputSizeParam; - hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1; - } - - if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) - { - if (!hasCopyTs) - { - args += " -copyts"; - } - args += " -avoid_negative_ts disabled -start_at_zero"; - } - - var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions(); - var qualityParam = EncodingHelper.GetVideoQualityParam(state, videoCodec, encodingOptions, GetDefaultH264Preset()); - - if (!string.IsNullOrEmpty(qualityParam)) - { - args += " " + qualityParam.Trim(); - } - - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += EncodingHelper.GetGraphicalSubtitleParam(state, videoCodec); - } - - if (!state.RunTimeTicks.HasValue) - { - args += " -flags -global_header"; - } - - return args; + return EncodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, GetDefaultH264Preset()); } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index afc48b64c..24ba0606d 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -134,7 +134,6 @@ namespace MediaBrowser.Api.Playback public string MimeType { get; set; } public bool EstimateContentLength { get; set; } - public bool EnableMpegtsM2TsMode { get; set; } public TranscodeSeekInfo TranscodeSeekInfo { get; set; } public long? EncodingDurationTicks { get; set; } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8a1e2698a..939a473c5 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1773,6 +1773,114 @@ namespace MediaBrowser.Controller.MediaEncoding return args; } + public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath, string defaultH264Preset) + { + // Get the output codec name + var videoCodec = GetVideoEncoder(state, encodingOptions); + + var format = string.Empty; + var keyFrame = string.Empty; + + if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase) && + state.BaseRequest.Context == EncodingContext.Streaming) + { + // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js + format = " -f mp4 -movflags frag_keyframe+empty_moov"; + } + + var threads = GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); + + var inputModifier = GetInputModifier(state, encodingOptions); + + return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7}{8} -y \"{9}\"", + inputModifier, + GetInputArgument(state, encodingOptions), + keyFrame, + GetMapArgs(state), + GetProgressiveVideoArguments(state, encodingOptions, videoCodec, defaultH264Preset), + threads, + GetProgressiveVideoAudioArguments(state, encodingOptions), + GetSubtitleEmbedArguments(state), + format, + outputPath + ).Trim(); + } + + public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset) + { + var args = "-codec:v:0 " + videoCodec; + + if (state.EnableMpegtsM2TsMode) + { + args += " -mpegts_m2ts_mode 1"; + } + + if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) + { + args += " -bsf:v h264_mp4toannexb"; + } + + if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps) + { + args += " -copyts -avoid_negative_ts disabled -start_at_zero"; + } + + if (!state.RunTimeTicks.HasValue) + { + args += " -flags -global_header -fflags +genpts"; + } + + return args; + } + + var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", + 5.ToString(_usCulture)); + + args += keyFrameArg; + + var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.BaseRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; + + var hasCopyTs = false; + // Add resolution params, if specified + if (!hasGraphicalSubs) + { + var outputSizeParam = GetOutputSizeParam(state, videoCodec); + args += outputSizeParam; + hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1; + } + + if (state.RunTimeTicks.HasValue && state.BaseRequest.CopyTimestamps) + { + if (!hasCopyTs) + { + args += " -copyts"; + } + args += " -avoid_negative_ts disabled -start_at_zero"; + } + + var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultH264Preset); + + if (!string.IsNullOrEmpty(qualityParam)) + { + args += " " + qualityParam.Trim(); + } + + // This is for internal graphical subs + if (hasGraphicalSubs) + { + args += GetGraphicalSubtitleParam(state, videoCodec); + } + + if (!state.RunTimeTicks.HasValue) + { + args += " -flags -global_header"; + } + + return args; + } + public string GetProgressiveVideoAudioArguments(EncodingJobInfo state, EncodingOptions encodingOptions) { // If the video doesn't have an audio stream, return a default. diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index ac33b8c8c..6f566515e 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -53,6 +53,8 @@ namespace MediaBrowser.Controller.MediaEncoding public string InputContainer { get; set; } public IsoType? IsoType { get; set; } + public bool EnableMpegtsM2TsMode { get; set; } + public BaseEncodingJobOptions BaseRequest { get; set; } public long? StartTimeTicks diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index 41f146375..73be78dc9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -14,7 +14,6 @@ namespace MediaBrowser.Controller.MediaEncoding public string AudioCodec { get; set; } public DeviceProfile DeviceProfile { get; set; } - public EncodingContext Context { get; set; } public bool ReadInputAtNativeFramerate { get; set; } @@ -214,9 +213,12 @@ namespace MediaBrowser.Controller.MediaEncoding [ApiMember(Name = "VideoStreamIndex", Description = "Optional. The index of the video stream to use. If omitted the first video stream will be used.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? VideoStreamIndex { get; set; } + public EncodingContext Context { get; set; } + public BaseEncodingJobOptions() { EnableAutoStreamCopy = true; + Context = EncodingContext.Streaming; } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs index a4db8f3b8..05b3ca5fc 100644 --- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { } - protected override Task GetCommandLineArguments(EncodingJob state) + protected override string GetCommandLineArguments(EncodingJob state) { var audioTranscodeParams = new List(); @@ -78,7 +78,7 @@ namespace MediaBrowser.MediaEncoding.Encoder mapArgs, metadata).Trim(); - return Task.FromResult(result); + return result; } protected override string GetOutputFileExtension(EncodingJob state) diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 635c8deac..ef68fb90a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -76,7 +76,7 @@ namespace MediaBrowser.MediaEncoding.Encoder await AcquireResources(encodingJob, cancellationToken).ConfigureAwait(false); - var commandLineArgs = await GetCommandLineArguments(encodingJob).ConfigureAwait(false); + var commandLineArgs = GetCommandLineArguments(encodingJob); var process = ProcessFactory.Create(new ProcessOptions { @@ -265,7 +265,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return ConfigurationManager.GetConfiguration("encoding"); } - protected abstract Task GetCommandLineArguments(EncodingJob job); + protected abstract string GetCommandLineArguments(EncodingJob job); private string GetOutputFilePath(EncodingJob state) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index 1b26d3b2a..449c31ace 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -36,7 +36,6 @@ namespace MediaBrowser.MediaEncoding.Encoder public string MimeType { get; set; } public bool EstimateContentLength { get; set; } - public bool EnableMpegtsM2TsMode { get; set; } public TranscodeSeekInfo TranscodeSeekInfo { get; set; } public long? EncodingDurationTicks { get; set; } public string LiveStreamId { get; set; } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index a779c1bca..96c126923 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -18,100 +18,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { } - protected override async Task GetCommandLineArguments(EncodingJob state) + protected override string GetCommandLineArguments(EncodingJob state) { // Get the output codec name var encodingOptions = GetEncodingOptions(); - var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions); - var format = string.Empty; - var keyFrame = string.Empty; - - if (string.Equals(Path.GetExtension(state.OutputFilePath), ".mp4", StringComparison.OrdinalIgnoreCase) && - state.Options.Context == EncodingContext.Streaming) - { - // Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js - format = " -f mp4 -movflags frag_keyframe+empty_moov"; - } - - var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)); - - var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions); - - var videoArguments = await GetVideoArguments(state, videoCodec).ConfigureAwait(false); - - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -threads {5} {6}{7} -y \"{8}\"", - inputModifier, - EncodingHelper.GetInputArgument(state, encodingOptions), - keyFrame, - EncodingHelper.GetMapArgs(state), - videoArguments, - threads, - EncodingHelper.GetProgressiveVideoAudioArguments(state, encodingOptions), - format, - state.OutputFilePath - ).Trim(); - } - - /// - /// Gets video arguments to pass to ffmpeg - /// - /// The state. - /// The video codec. - /// System.String. - private async Task GetVideoArguments(EncodingJob state, string videoCodec) - { - var args = "-codec:v:0 " + videoCodec; - - if (state.EnableMpegtsM2TsMode) - { - args += " -mpegts_m2ts_mode 1"; - } - - var isOutputMkv = string.Equals(state.Options.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); - - if (state.RunTimeTicks.HasValue) - { - //args += " -copyts -avoid_negative_ts disabled -start_at_zero"; - } - - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) - { - if (state.VideoStream != null && EncodingHelper.IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) - { - args += " -bsf:v h264_mp4toannexb"; - } - - return args; - } - - var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", - 5.ToString(UsCulture)); - - args += keyFrameArg; - - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.Options.SubtitleMethod == SubtitleDeliveryMethod.Encode; - - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - args += EncodingHelper.GetOutputSizeParam(state, videoCodec); - } - - var qualityParam = EncodingHelper.GetVideoQualityParam(state, videoCodec, GetEncodingOptions(), "superfast"); - - if (!string.IsNullOrEmpty(qualityParam)) - { - args += " " + qualityParam.Trim(); - } - - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += EncodingHelper.GetGraphicalSubtitleParam(state, videoCodec); - } - - return args; + return EncodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, state.OutputFilePath, "superfast"); } protected override string GetOutputFileExtension(EncodingJob state) -- cgit v1.2.3 From da88fbb8241b35076ff368f94b49b9b97d8d826d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Mar 2017 15:10:10 -0400 Subject: update hd homerun udp stream --- Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 9 ++++++--- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 6 ++++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index c9cd289e7..74b8a7764 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var result = await GetChannelsInternal(tuner, cancellationToken).ConfigureAwait(false); var list = result.ToList(); - Logger.Debug("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); + Logger.Info("Channels from {0}: {1}", tuner.Url, JsonSerializer.SerializeToString(list)); if (!string.IsNullOrWhiteSpace(key) && list.Count > 0) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index a881d0ea1..867e07e87 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -120,7 +120,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // send url to start streaming await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelCommands, _numTuners, cancellationToken).ConfigureAwait(false); - var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); + var timeoutToken = CancellationTokenSource.CreateLinkedTokenSource(new CancellationTokenSource(5000).Token, cancellationToken).Token; + var response = await udpClient.ReceiveAsync(timeoutToken).ConfigureAwait(false); _logger.Info("Opened HDHR UDP stream from {0}", remoteAddress); if (!cancellationToken.IsCancellationRequested) @@ -135,8 +136,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await _multicastStream.CopyUntilCancelled(stream, onStarted, cancellationToken).ConfigureAwait(false); } } - catch (OperationCanceledException) + catch (OperationCanceledException ex) { + _logger.Info("HDHR UDP stream cancelled or timed out from {0}", remoteAddress); + openTaskCompletionSource.TrySetException(ex); break; } catch (Exception ex) @@ -291,4 +294,4 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun throw new NotImplementedException(); } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 939a473c5..eb69a8f7b 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -154,6 +154,7 @@ namespace MediaBrowser.Controller.MediaEncoding { return "mpegts"; } + // For these need to find out the ffmpeg names if (string.Equals(container, "m2ts", StringComparison.OrdinalIgnoreCase)) { @@ -179,6 +180,11 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(container, "dvr-ms", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + // Seeing reported failures here, not sure yet if this is related to specfying input format if (string.Equals(container, "m4v", StringComparison.OrdinalIgnoreCase)) { -- cgit v1.2.3 From ce0547abde8a245bd2e107156be2549582fbe5bc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 26 Mar 2017 00:20:50 -0400 Subject: throw exceptions on bad input --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index eb69a8f7b..5eaab4110 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1583,6 +1583,15 @@ namespace MediaBrowser.Controller.MediaEncoding MediaSourceInfo mediaSource, string requestedUrl) { + if (state == null) + { + throw new ArgumentNullException("state"); + } + if (mediaSource == null) + { + throw new ArgumentNullException("mediaSource"); + } + state.MediaPath = mediaSource.Path; state.InputProtocol = mediaSource.Protocol; state.InputContainer = mediaSource.Container; -- cgit v1.2.3 From 2dbe162e45269df00fb44fbe5340b72758399307 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 28 Mar 2017 13:32:24 -0400 Subject: revert buffer size --- Emby.Common.Implementations/Net/UdpSocket.cs | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs') diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index a97b2e668..f9181eb6a 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -49,7 +49,7 @@ namespace Emby.Common.Implementations.Net private void InitReceiveSocketAsyncEventArgs() { - var receiveBuffer = new byte[81920]; + var receiveBuffer = new byte[8192]; _receiveSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); _receiveSocketAsyncEventArgs.Completed += _receiveSocketAsyncEventArgs_Completed; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 5eaab4110..b7b31509c 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -164,6 +164,10 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(container, "mts", StringComparison.OrdinalIgnoreCase)) + { + return null; + } if (string.Equals(container, "vob", StringComparison.OrdinalIgnoreCase)) { return null; @@ -1709,6 +1713,13 @@ namespace MediaBrowser.Controller.MediaEncoding return "-c:v h264_qsv "; } break; + //case "hevc": + //case "h265": + // if (_mediaEncoder.SupportsDecoder("hevc_qsv")) + // { + // return "-c:v hevc_qsv "; + // } + // break; case "mpeg2video": if (_mediaEncoder.SupportsDecoder("mpeg2_qsv")) { -- cgit v1.2.3