Jelajahi Sumber

Merge pull request #2887 from MediaBrowser/dev

Dev
Luke 7 tahun lalu
induk
melakukan
3cc6c739c9

+ 4 - 1
Emby.Dlna/PlayTo/PlayToManager.cs

@@ -194,7 +194,10 @@ namespace Emby.Dlna.PlayTo
                             GeneralCommandType.SetSubtitleStreamIndex.ToString()
                         },
 
-                        SupportsMediaControl = true
+                        SupportsMediaControl = true,
+
+                        // xbox one creates a new uuid everytime it restarts
+                        SupportsPersistentIdentifier = (device.Properties.ModelName ?? string.Empty).IndexOf("xbox", StringComparison.OrdinalIgnoreCase) == -1
                     });
 
                     _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);

+ 84 - 44
Emby.Server.Implementations/Library/UserManager.cs

@@ -180,11 +180,6 @@ namespace Emby.Server.Implementations.Library
             }
         }
 
-        public Task<User> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint)
-        {
-            return AuthenticateUser(username, passwordSha1, null, remoteEndPoint);
-        }
-
         public bool IsValidUsername(string username)
         {
             // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
@@ -223,7 +218,7 @@ namespace Emby.Server.Implementations.Library
             return builder.ToString();
         }
 
-        public async Task<User> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint)
+        public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string passwordMd5, string remoteEndPoint)
         {
             if (string.IsNullOrWhiteSpace(username))
             {
@@ -237,23 +232,23 @@ namespace Emby.Server.Implementations.Library
 
             if (user != null)
             {
+                if (password != null)
+                {
+                    hashedPassword = GetHashedString(user, password);
+                }
+
                 // Authenticate using local credentials if not a guest
                 if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest)
                 {
-                    success = string.Equals(GetPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
-
-                    if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
-                    {
-                        success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
-                    }
+                    success = AuthenticateLocalUser(user, password, hashedPassword, remoteEndPoint);
                 }
 
                 // Maybe user accidently entered connect credentials. let's be flexible
-                if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5) && !string.IsNullOrWhiteSpace(user.ConnectUserName))
+                if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(user.ConnectUserName))
                 {
                     try
                     {
-                        await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
+                        await _connectFactory().Authenticate(user.ConnectUserName, password, passwordMd5).ConfigureAwait(false);
                         success = true;
                     }
                     catch
@@ -268,7 +263,7 @@ namespace Emby.Server.Implementations.Library
             {
                 try
                 {
-                    var connectAuthResult = await _connectFactory().Authenticate(username, passwordMd5).ConfigureAwait(false);
+                    var connectAuthResult = await _connectFactory().Authenticate(username, password, passwordMd5).ConfigureAwait(false);
 
                     user = Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectAuthResult.User.Id, StringComparison.OrdinalIgnoreCase));
 
@@ -307,6 +302,36 @@ namespace Emby.Server.Implementations.Library
             return success ? user : null;
         }
 
+        private bool AuthenticateLocalUser(User user, string password, string hashedPassword, string remoteEndPoint)
+        {
+            bool success;
+
+            if (password == null)
+            {
+                // legacy
+                success = string.Equals(GetPasswordHash(user), hashedPassword.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+            }
+            else
+            {
+                success = string.Equals(GetPasswordHash(user), GetHashedString(user, password), StringComparison.OrdinalIgnoreCase);
+            }
+
+            if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
+            {
+                if (password == null)
+                {
+                    // legacy
+                    success = string.Equals(GetLocalPasswordHash(user), hashedPassword.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+                }
+                else
+                {
+                    success = string.Equals(GetLocalPasswordHash(user), GetHashedString(user, password), StringComparison.OrdinalIgnoreCase);
+                }
+            }
+
+            return success;
+        }
+
         private void UpdateInvalidLoginAttemptCount(User user, int newValue)
         {
             if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0)
@@ -342,29 +367,39 @@ namespace Emby.Server.Implementations.Library
         private string GetPasswordHash(User user)
         {
             return string.IsNullOrEmpty(user.Password)
-                ? GetSha1String(string.Empty)
+                ? GetEmptyHashedString(user)
                 : user.Password;
         }
 
         private string GetLocalPasswordHash(User user)
         {
             return string.IsNullOrEmpty(user.EasyPassword)
-                ? GetSha1String(string.Empty)
+                ? GetEmptyHashedString(user)
                 : user.EasyPassword;
         }
 
-        private bool IsPasswordEmpty(string passwordHash)
+        private bool IsPasswordEmpty(User user, string passwordHash)
         {
-            return string.Equals(passwordHash, GetSha1String(string.Empty), StringComparison.OrdinalIgnoreCase);
+            return string.Equals(passwordHash, GetEmptyHashedString(user), StringComparison.OrdinalIgnoreCase);
+        }
+
+        private string GetEmptyHashedString(User user)
+        {
+            return GetHashedString(user, string.Empty);
         }
 
         /// <summary>
-        /// Gets the sha1 string.
+        /// Gets the hashed string.
         /// </summary>
-        /// <param name="str">The STR.</param>
-        /// <returns>System.String.</returns>
-        private string GetSha1String(string str)
+        private string GetHashedString(User user, string str)
         {
+            var salt = user.Salt;
+            if (salt != null)
+            {
+                // return BCrypt.HashPassword(str, salt);
+            }
+
+            // legacy
             return BitConverter.ToString(_cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str))).Replace("-", string.Empty);
         }
 
@@ -407,8 +442,8 @@ namespace Emby.Server.Implementations.Library
 
             var passwordHash = GetPasswordHash(user);
 
-            var hasConfiguredPassword = !IsPasswordEmpty(passwordHash);
-            var hasConfiguredEasyPassword = !IsPasswordEmpty(GetLocalPasswordHash(user));
+            var hasConfiguredPassword = !IsPasswordEmpty(user, passwordHash);
+            var hasConfiguredEasyPassword = !IsPasswordEmpty(user, GetLocalPasswordHash(user));
 
             var hasPassword = user.Configuration.EnableLocalPassword && !string.IsNullOrEmpty(remoteEndPoint) && _networkManager.IsInLocalNetwork(remoteEndPoint) ?
                 hasConfiguredEasyPassword :
@@ -460,14 +495,6 @@ namespace Emby.Server.Implementations.Library
         {
             var dto = GetUserDto(user);
 
-            var offlinePasswordHash = GetLocalPasswordHash(user);
-            dto.HasPassword = !IsPasswordEmpty(offlinePasswordHash);
-
-            dto.OfflinePasswordSalt = Guid.NewGuid().ToString("N");
-
-            // Hash the pin with the device Id to create a unique result for this device
-            dto.OfflinePassword = GetSha1String((offlinePasswordHash + dto.OfflinePasswordSalt).ToLower());
-
             dto.ServerName = _appHost.FriendlyName;
 
             return dto;
@@ -682,23 +709,29 @@ namespace Emby.Server.Implementations.Library
         /// <returns>Task.</returns>
         public void ResetPassword(User user)
         {
-            ChangePassword(user, GetSha1String(string.Empty));
+            ChangePassword(user, string.Empty, null);
         }
 
         public void ResetEasyPassword(User user)
         {
-            ChangeEasyPassword(user, GetSha1String(string.Empty));
+            ChangeEasyPassword(user, string.Empty, null);
         }
 
-        public void ChangePassword(User user, string newPasswordSha1)
+        public void ChangePassword(User user, string newPassword, string newPasswordHash)
         {
             if (user == null)
             {
                 throw new ArgumentNullException("user");
             }
-            if (string.IsNullOrWhiteSpace(newPasswordSha1))
+
+            if (newPassword != null)
+            {
+                newPasswordHash = GetHashedString(user, newPassword);
+            }
+
+            if (string.IsNullOrWhiteSpace(newPasswordHash))
             {
-                throw new ArgumentNullException("newPasswordSha1");
+                throw new ArgumentNullException("newPasswordHash");
             }
 
             if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest)
@@ -706,25 +739,31 @@ namespace Emby.Server.Implementations.Library
                 throw new ArgumentException("Passwords for guests cannot be changed.");
             }
 
-            user.Password = newPasswordSha1;
+            user.Password = newPasswordHash;
 
             UpdateUser(user);
 
             EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
         }
 
-        public void ChangeEasyPassword(User user, string newPasswordSha1)
+        public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash)
         {
             if (user == null)
             {
                 throw new ArgumentNullException("user");
             }
-            if (string.IsNullOrWhiteSpace(newPasswordSha1))
+
+            if (newPassword != null)
+            {
+                newPasswordHash = GetHashedString(user, newPassword);
+            }
+
+            if (string.IsNullOrWhiteSpace(newPasswordHash))
             {
-                throw new ArgumentNullException("newPasswordSha1");
+                throw new ArgumentNullException("newPasswordHash");
             }
 
-            user.EasyPassword = newPasswordSha1;
+            user.EasyPassword = newPasswordHash;
 
             UpdateUser(user);
 
@@ -744,7 +783,8 @@ namespace Emby.Server.Implementations.Library
                 Id = Guid.NewGuid(),
                 DateCreated = DateTime.UtcNow,
                 DateModified = DateTime.UtcNow,
-                UsesIdForConfigurationPath = true
+                UsesIdForConfigurationPath = true,
+                //Salt = BCrypt.GenerateSalt()
             };
         }
 

+ 9 - 2
Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs

@@ -284,8 +284,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
         protected string GetOutputSizeParam()
         {
             var filters = new List<string>();
-
-            filters.Add("yadif=0:-1:0");
+            
+            if (string.Equals(GetEncodingOptions().DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase))
+            {
+                filters.Add("yadif=1:-1:0");
+            }
+            else
+            {
+                filters.Add("yadif=0:-1:0");
+            }
 
             var output = string.Empty;
 

+ 18 - 6
MediaBrowser.Api/UserService.cs

@@ -97,6 +97,9 @@ namespace MediaBrowser.Api
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
         public string Id { get; set; }
 
+        [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
+        public string Pw { get; set; }
+
         /// <summary>
         /// Gets or sets the password.
         /// </summary>
@@ -125,6 +128,9 @@ namespace MediaBrowser.Api
         [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
         public string Password { get; set; }
 
+        [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
+        public string Pw { get; set; }
+
         [ApiMember(Name = "PasswordMd5", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
         public string PasswordMd5 { get; set; }
     }
@@ -148,12 +154,16 @@ namespace MediaBrowser.Api
         /// <value>The password.</value>
         public string CurrentPassword { get; set; }
 
+        public string CurrentPw { get; set; }
+
         /// <summary>
         /// Gets or sets the new password.
         /// </summary>
         /// <value>The new password.</value>
         public string NewPassword { get; set; }
 
+        public string NewPw { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether [reset password].
         /// </summary>
@@ -180,6 +190,8 @@ namespace MediaBrowser.Api
         /// <value>The new password.</value>
         public string NewPassword { get; set; }
 
+        public string NewPw { get; set; }
+
         /// <summary>
         /// Gets or sets a value indicating whether [reset password].
         /// </summary>
@@ -408,7 +420,8 @@ namespace MediaBrowser.Api
             return Post(new AuthenticateUserByName
             {
                 Username = user.Name,
-                Password = request.Password
+                Password = request.Password,
+                Pw = request.Pw
             });
         }
 
@@ -422,6 +435,7 @@ namespace MediaBrowser.Api
                 AppVersion = auth.Version,
                 DeviceId = auth.DeviceId,
                 DeviceName = auth.Device,
+                Password = request.Pw,
                 PasswordSha1 = request.Password,
                 PasswordMd5 = request.PasswordMd5,
                 RemoteEndPoint = Request.RemoteIp,
@@ -459,14 +473,14 @@ namespace MediaBrowser.Api
             }
             else
             {
-                var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPassword, Request.RemoteIp).ConfigureAwait(false);
+                var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPw, request.CurrentPassword, null, Request.RemoteIp).ConfigureAwait(false);
 
                 if (success == null)
                 {
                     throw new ArgumentException("Invalid user or password entered.");
                 }
 
-                _userManager.ChangePassword(user, request.NewPassword);
+                _userManager.ChangePassword(user, request.NewPw, request.NewPassword);
 
                 var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
 
@@ -491,7 +505,7 @@ namespace MediaBrowser.Api
             }
             else
             {
-                _userManager.ChangeEasyPassword(user, request.NewPassword);
+                _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword);
             }
         }
 
@@ -501,8 +515,6 @@ namespace MediaBrowser.Api
         /// <param name="request">The request.</param>
         public void Post(UpdateUser request)
         {
-            // We need to parse this manually because we told service stack not to with IRequiresRequestStream
-            // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
             var id = GetPathValue(1);
 
             AssertCanUpdateUser(_authContext, _userManager, id, false);

+ 1 - 4
MediaBrowser.Controller/Connect/IConnectManager.cs

@@ -58,10 +58,7 @@ namespace MediaBrowser.Controller.Connect
         /// <summary>
         /// Authenticates the specified username.
         /// </summary>
-        /// <param name="username">The username.</param>
-        /// <param name="passwordMd5">The password MD5.</param>
-        /// <returns>Task.</returns>
-        Task<ConnectAuthenticationResult> Authenticate(string username, string passwordMd5);
+        Task<ConnectAuthenticationResult> Authenticate(string username, string password, string passwordMd5);
 
         /// <summary>
         /// Gets the local user.

+ 1 - 0
MediaBrowser.Controller/Entities/User.cs

@@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The password.</value>
         public string Password { get; set; }
         public string EasyPassword { get; set; }
+        public string Salt { get; set; }
 
         public string ConnectUserName { get; set; }
         public string ConnectUserId { get; set; }

+ 3 - 24
MediaBrowser.Controller/Library/IUserManager.cs

@@ -58,16 +58,6 @@ namespace MediaBrowser.Controller.Library
         /// <returns>User.</returns>
         User GetUserByName(string name);
 
-        /// <summary>
-        /// Authenticates a User and returns a result indicating whether or not it succeeded
-        /// </summary>
-        /// <param name="username">The username.</param>
-        /// <param name="passwordSha1">The password sha1.</param>
-        /// <param name="remoteEndPoint">The remote end point.</param>
-        /// <returns>Task{System.Boolean}.</returns>
-        /// <exception cref="System.ArgumentNullException">user</exception>
-        Task<User> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint);
-        
         /// <summary>
         /// Refreshes metadata for each user
         /// </summary>
@@ -135,18 +125,12 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Changes the password.
         /// </summary>
-        /// <param name="user">The user.</param>
-        /// <param name="newPasswordSha1">The new password sha1.</param>
-        /// <returns>Task.</returns>
-        void ChangePassword(User user, string newPasswordSha1);
+        void ChangePassword(User user, string newPassword, string newPasswordSha1);
 
         /// <summary>
         /// Changes the easy password.
         /// </summary>
-        /// <param name="user">The user.</param>
-        /// <param name="newPasswordSha1">The new password sha1.</param>
-        /// <returns>Task.</returns>
-        void ChangeEasyPassword(User user, string newPasswordSha1);
+        void ChangeEasyPassword(User user, string newPassword, string newPasswordSha1);
         
         /// <summary>
         /// Gets the user dto.
@@ -159,12 +143,7 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Authenticates the user.
         /// </summary>
-        /// <param name="username">The username.</param>
-        /// <param name="passwordSha1">The password sha1.</param>
-        /// <param name="passwordMd5">The password MD5.</param>
-        /// <param name="remoteEndPoint">The remote end point.</param>
-        /// <returns>Task&lt;System.Boolean&gt;.</returns>
-        Task<User> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint);
+        Task<User> AuthenticateUser(string username, string password, string passwordSha1, string passwordMd5, string remoteEndPoint);
 
         /// <summary>
         /// Starts the forgot password process.

+ 57 - 19
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -1288,10 +1288,7 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <summary>
         /// Gets the internal graphical subtitle param.
         /// </summary>
-        /// <param name="state">The state.</param>
-        /// <param name="outputVideoCodec">The output video codec.</param>
-        /// <returns>System.String.</returns>
-        public string GetGraphicalSubtitleParam(EncodingJobInfo state, string outputVideoCodec)
+        public string GetGraphicalSubtitleParam(EncodingJobInfo state, EncodingOptions options, string outputVideoCodec)
         {
             var outputSizeParam = string.Empty;
 
@@ -1300,7 +1297,7 @@ namespace MediaBrowser.Controller.MediaEncoding
             // Add resolution params, if specified
             if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
             {
-                outputSizeParam = GetOutputSizeParam(state, outputVideoCodec).TrimEnd('"');
+                outputSizeParam = GetOutputSizeParam(state, options, outputVideoCodec).TrimEnd('"');
 
                 if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
                 {
@@ -1343,11 +1340,8 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <summary>
         /// If we're going to put a fixed size on the command line, this will calculate it
         /// </summary>
-        /// <param name="state">The state.</param>
-        /// <param name="outputVideoCodec">The output video codec.</param>
-        /// <param name="allowTimeStampCopy">if set to <c>true</c> [allow time stamp copy].</param>
-        /// <returns>System.String.</returns>
         public string GetOutputSizeParam(EncodingJobInfo state,
+            EncodingOptions options,
             string outputVideoCodec,
             bool allowTimeStampCopy = true)
         {
@@ -1365,7 +1359,14 @@ namespace MediaBrowser.Controller.MediaEncoding
 
             if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
             {
-                filters.Add("yadif=0:-1:0");
+                if (string.Equals(options.DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase))
+                {
+                    filters.Add("yadif=1:-1:0");
+                }
+                else
+                {
+                    filters.Add("yadif=0:-1:0");
+                }
             }
 
             if (string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
@@ -1400,13 +1401,22 @@ namespace MediaBrowser.Controller.MediaEncoding
             }
             else
             {
+                var isExynosV4L2 = string.Equals(outputVideoCodec, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase);
+
                 // If fixed dimensions were supplied
                 if (request.Width.HasValue && request.Height.HasValue)
                 {
                     var widthParam = request.Width.Value.ToString(_usCulture);
                     var heightParam = request.Height.Value.ToString(_usCulture);
 
-                    filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam));
+                    if (isExynosV4L2)
+                    {
+                        filters.Add(string.Format("scale=trunc({0}/64)*64:trunc({1}/2)*2", widthParam, heightParam));
+                    }
+                    else
+                    {
+                        filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", widthParam, heightParam));
+                    }
                 }
 
                 // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size
@@ -1415,7 +1425,14 @@ namespace MediaBrowser.Controller.MediaEncoding
                     var maxWidthParam = request.MaxWidth.Value.ToString(_usCulture);
                     var maxHeightParam = request.MaxHeight.Value.ToString(_usCulture);
 
-                    filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+                    if (isExynosV4L2)
+                    {
+                        filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/64)*64:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+                    }
+                    else
+                    {
+                        filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam));
+                    }
                 }
 
                 // If a fixed width was requested
@@ -1431,7 +1448,14 @@ namespace MediaBrowser.Controller.MediaEncoding
                 {
                     var heightParam = request.Height.Value.ToString(_usCulture);
 
-                    filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam));
+                    if (isExynosV4L2)
+                    {
+                        filters.Add(string.Format("scale=trunc(oh*a/64)*64:{0}", heightParam));
+                    }
+                    else
+                    {
+                        filters.Add(string.Format("scale=trunc(oh*a/2)*2:{0}", heightParam));
+                    }
                 }
 
                 // If a max width was requested
@@ -1439,7 +1463,14 @@ namespace MediaBrowser.Controller.MediaEncoding
                 {
                     var maxWidthParam = request.MaxWidth.Value.ToString(_usCulture);
 
-                    filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam));
+                    if (isExynosV4L2)
+                    {
+                        filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/64)*64:trunc(ow/dar/2)*2", maxWidthParam));
+                    }
+                    else
+                    {
+                        filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,{0})/2)*2:trunc(ow/dar/2)*2", maxWidthParam));
+                    }
                 }
 
                 // If a max height was requested
@@ -1447,7 +1478,14 @@ namespace MediaBrowser.Controller.MediaEncoding
                 {
                     var maxHeightParam = request.MaxHeight.Value.ToString(_usCulture);
 
-                    filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam));
+                    if (isExynosV4L2)
+                    {
+                        filters.Add(string.Format("scale=trunc(oh*a/64)*64:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam));
+                    }
+                    else
+                    {
+                        filters.Add(string.Format("scale=trunc(oh*a/2)*2:min(max(iw/dar\\,ih)\\,{0})", maxHeightParam));
+                    }
                 }
             }
 
@@ -1903,9 +1941,9 @@ namespace MediaBrowser.Controller.MediaEncoding
                     {
                         case "avc":
                         case "h264":
-                            if (_mediaEncoder.SupportsDecoder("h264_omx") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
+                            if (_mediaEncoder.SupportsDecoder("h264_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
                             {
-                                return "-c:v h264_omx ";
+                                return "-c:v h264_mmal";
                             }
                             break;
                     }
@@ -2055,7 +2093,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                 // Add resolution params, if specified
                 if (!hasGraphicalSubs)
                 {
-                    var outputSizeParam = GetOutputSizeParam(state, videoCodec);
+                    var outputSizeParam = GetOutputSizeParam(state, encodingOptions, videoCodec);
                     args += outputSizeParam;
                     hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1;
                 }
@@ -2079,7 +2117,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                 // This is for internal graphical subs
                 if (hasGraphicalSubs)
                 {
-                    args += GetGraphicalSubtitleParam(state, videoCodec);
+                    args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec);
                 }
 
                 if (!state.RunTimeTicks.HasValue)

+ 1 - 0
MediaBrowser.Controller/Session/AuthenticationRequest.cs

@@ -5,6 +5,7 @@ namespace MediaBrowser.Controller.Session
     {
         public string Username { get; set; }
         public string UserId { get; set; }
+        public string Password { get; set; }
         public string PasswordSha1 { get; set; }
         public string PasswordMd5 { get; set; }
         public string App { get; set; }

+ 1 - 0
MediaBrowser.Model/Configuration/EncodingOptions.cs

@@ -13,6 +13,7 @@ namespace MediaBrowser.Model.Configuration
         public string VaapiDevice { get; set; }
         public int H264Crf { get; set; }
         public string H264Preset { get; set; }
+        public string DeinterlaceMethod { get; set; }
         public bool EnableHardwareEncoding { get; set; }
         public bool EnableSubtitleExtraction { get; set; }
 

+ 0 - 12
MediaBrowser.Model/Dto/UserDto.cs

@@ -54,18 +54,6 @@ namespace MediaBrowser.Model.Dto
         /// <value>The id.</value>
         public string Id { get; set; }
         
-        /// <summary>
-        /// Gets or sets the offline password.
-        /// </summary>
-        /// <value>The offline password.</value>
-        public string OfflinePassword { get; set; }
-
-        /// <summary>
-        /// Gets or sets the offline password salt.
-        /// </summary>
-        /// <value>The offline password salt.</value>
-        public string OfflinePasswordSalt { get; set; }
-        
         /// <summary>
         /// Gets or sets the primary image tag.
         /// </summary>

+ 1 - 1
SharedVersion.cs

@@ -1,3 +1,3 @@
 using System.Reflection;
 
-[assembly: AssemblyVersion("3.2.30.23")]
+[assembly: AssemblyVersion("3.2.30.24")]

+ 5 - 8
SocketHttpListener/Net/HttpResponseStream.Managed.cs

@@ -285,16 +285,11 @@ namespace SocketHttpListener.Net
             }
         }
 
-        private bool EnableSendFileWithSocket = false;
-
         public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
         {
-            //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !_response.SendChunked && _response.ContentLength64 > 8192)
+            //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !_response.SendChunked)
             //{
-            //    if (EnableSendFileWithSocket)
-            //    {
-            //        return TransmitFileOverSocket(path, offset, count, fileShareMode, cancellationToken);
-            //    }
+            //    return TransmitFileOverSocket(path, offset, count, fileShareMode, cancellationToken);
             //}
 
             return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
@@ -319,7 +314,9 @@ namespace SocketHttpListener.Net
                 return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
             }
 
-            //_logger.Info("Socket sending file {0} {1}", path, response.ContentLength64);
+            _stream.Flush();
+
+            _logger.Info("Socket sending file {0}", path);
 
             var taskCompletion = new TaskCompletionSource<bool>();