Skip to content

Commit

Permalink
MP1-4942: Trying to fix rare deadlock when seeking in video
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastiii committed Mar 2, 2019
1 parent ea67d33 commit 45ed6cc
Showing 1 changed file with 144 additions and 45 deletions.
189 changes: 144 additions & 45 deletions mediaportal/Core/Player/g_player.cs
Expand Up @@ -114,6 +114,8 @@ public enum DriveType
private static string _externalPlayerExtensions = string.Empty;
private static int _titleToDB = 0;

public static readonly AutoResetEvent SeekFinished = new AutoResetEvent(false);

/// <param name="default Blu-ray remuxed">BdRemuxTitle</param>
public const int BdRemuxTitle = 900;

Expand Down Expand Up @@ -1517,6 +1519,7 @@ public static bool Play(string strFile, MediaType type, TextReader chapters, boo

g_Player.SetResumeBDTitleState = title;
bool UseEVRMadVRForTV = false;
bool _NoBDMenu = false;

IsPicture = false;
IsExtTS = false;
Expand Down Expand Up @@ -1626,7 +1629,56 @@ public static bool Play(string strFile, MediaType type, TextReader chapters, boo
{
_BDInternalMenu = xmlreader.GetValueAsBool("bdplayer", "useInternalBDPlayer", true);
UseEVRMadVRForTV = xmlreader.GetValueAsBool("general", "useEVRMadVRForTV", false);
_NoBDMenu = xmlreader.GetValueAsBool("bdplayer", "DisableSelectMenuBDPlayer", true);
}

if (extension == ".bdmv" && !GUIGraphicsContext.BlurayMenu && !_NoBDMenu)
{
IDialogbox dialog = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU);
while (true)
{
// todo: translation for all string
dialog.Reset();
dialog.SetHeading("Select blu-ray player mode");

// Add play with internal BDReader menu
//dialog.AddLocalizedString(222);
GUIListItem itemBlurayMenu = new GUIListItem("Play blu-ray with menu");
dialog.Add(itemBlurayMenu);

// Add play with normal MP player (LAV)
//dialog.AddLocalizedString(222);
GUIListItem itemLav = new GUIListItem("Play blu-ray without menu");
dialog.Add(itemLav);

dialog.DoModal(GUIWindowManager.ActiveWindow);

if (dialog.SelectedId == itemBlurayMenu.ItemId)
{
_BDInternalMenu = true;
}
if (dialog.SelectedId == itemLav.ItemId)
{
_BDInternalMenu = false;
}

// Write the new detected settings
using (Settings xmlwriter = new MPSettings())
{
xmlwriter.SetValueAsBool("bdplayer", "useInternalBDPlayer", _BDInternalMenu);
}

if (dialog.SelectedId < 1)
{
// user cancelled so we return
return false;
}

// end dialog
break;
}
}

if (_BDInternalMenu && extension == ".bdmv")
{
AskForRefresh = false;
Expand Down Expand Up @@ -1842,6 +1894,7 @@ public static bool Play(string strFile, MediaType type, TextReader chapters, boo
_currentMediaForBassEngine = _currentMedia;
currentMediaInfoFilePlaying = "";
Starting = false;
GUIGraphicsContext.BlurayMenu = false;
}
UnableToPlay(strFile, type);
return false;
Expand Down Expand Up @@ -2311,6 +2364,7 @@ public static void SeekRelative(double dTime)
// Suspending GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.RUNNING)
{
Log.Debug("g_Player: StepNow GUIGraphicsContext.State.SUSPENDING");
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
}

Expand All @@ -2331,43 +2385,67 @@ public static void SeekRelative(double dTime)

public static void StepNow()
{
// Suspending GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.RUNNING)
// Resume automatic operation
if (!_StepNowDone) //_SeekAbsoluteDone
{
Log.Debug("g_Player: StepNow GUIGraphicsContext.State.SUSPENDING");
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
}
_StepNowDone = true;

if (_currentStep != 0 && _player != null)
{
if (_currentStep < 0 || (_player.CurrentPosition + 4 < _player.Duration) || !IsTV)
// Start seek in a thread to avoid deadlock
new Thread(() =>
{
double dTime = (int)_currentStep + _player.CurrentPosition;
Log.Debug("g_Player.StepNow() - Preparing to seek to {0}:{1}", _player.CurrentPosition, _player.Duration);
if (!IsTV && (dTime > _player.Duration)) dTime = _player.Duration - 5;
if (IsTV && (dTime + 3 > _player.Duration)) dTime = _player.Duration - 3; // Margin for live Tv
if (dTime < 0) dTime = 0d;
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "StepNow";
Log.Debug("g_Player.StepNow() - Preparing to seek to {0}:{1}:{2} isTv {3}", (int)(dTime / 3600d),
(int)((dTime % 3600d) / 60d), (int)(dTime % 60d), IsTV);
_player.SeekAbsolute(dTime);
Speed = Speed;
GUIMessage msgUpdate = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYER_POSITION_CHANGED, 0, 0, 0, 0, 0,
null);
GUIGraphicsContext.SendMessage(msgUpdate);
}
}
_currentStep = 0;
_currentStepIndex = -1;
_seekTimer = DateTime.MinValue;
// Suspending GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.RUNNING)
{
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
}
// Restore GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.SUSPENDING)
{
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.RUNNING;
if (_currentStep != 0 && _player != null)
{
if (_currentStep < 0 || (_player.CurrentPosition + 4 < _player.Duration) || !IsTV)
{
double dTime = (int) _currentStep + _player.CurrentPosition;
Log.Debug("g_Player.StepNow() - Preparing to seek to {0}:{1}", _player.CurrentPosition, _player.Duration);
if (!IsTV && (dTime > _player.Duration)) dTime = _player.Duration - 5;
if (IsTV && (dTime + 3 > _player.Duration)) dTime = _player.Duration - 3; // Margin for live Tv
if (dTime < 0) dTime = 0d;
Log.Debug("g_Player.StepNow() - Preparing to seek to {0}:{1}:{2} isTv {3}", (int) (dTime / 3600d),
(int) ((dTime % 3600d) / 60d), (int) (dTime % 60d), IsTV);
_player.SeekAbsolute(dTime);
Speed = Speed;
GUIMessage msgUpdate = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYER_POSITION_CHANGED, 0, 0, 0, 0,
0,
null);
GUIGraphicsContext.SendMessage(msgUpdate);
}
}
_currentStep = 0;
_currentStepIndex = -1;
_seekTimer = DateTime.MinValue;
// Restore GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.SUSPENDING)
{
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.RUNNING;
}
// Wait until is done
SeekFinished.Set();
}).Start();

// Reset seek
SeekFinished.WaitOne(5000);
_StepNowDone = false;
}
}

public static bool _StepNowDone { get; set; }
public static bool _SeekAbsoluteDone { get; set; }

/// <summary>
/// This function returns the localized time units for "Step" (seconds) in human readable format.
/// </summary>
Expand Down Expand Up @@ -2565,26 +2643,47 @@ public static void SeekAbsolute(double dTime)
{
return;
}
// Suspending GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.RUNNING)

if (!_SeekAbsoluteDone)
{
_SeekAbsoluteDone = true;

// Start seek in a thread to avoid deadlock
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "SeekAbsolute";
// Suspending GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.RUNNING)
{
Log.Debug("g_Player: SeekAbsolute GUIGraphicsContext.State.SUSPENDING");
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
}
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.SUSPENDING;
}
Log.Debug("g_Player.SeekAbsolute() - Preparing to seek to {0}:{1}:{2}", (int)(dTime / 3600d),
(int)((dTime % 3600d) / 60d), (int)(dTime % 60d));
_player.SeekAbsolute(dTime);
GUIMessage msgUpdate = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYER_POSITION_CHANGED, 0, 0, 0, 0, 0, null);
GUIGraphicsContext.SendMessage(msgUpdate);
_currentStep = 0;
_currentStepIndex = -1;
_seekTimer = DateTime.MinValue;
Log.Debug("g_Player.SeekAbsolute() - Preparing to seek to {0}:{1}:{2}", (int) (dTime / 3600d),
(int) ((dTime % 3600d) / 60d), (int) (dTime % 60d));
_player.SeekAbsolute(dTime);
GUIMessage msgUpdate =
new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYER_POSITION_CHANGED, 0, 0, 0, 0, 0, null);
GUIGraphicsContext.SendMessage(msgUpdate);
_currentStep = 0;
_currentStepIndex = -1;
_seekTimer = DateTime.MinValue;
// Restore GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.SUSPENDING)
{
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.RUNNING;
// Restore GUIGraphicsContext.State
if (GUIGraphicsContext.CurrentState == GUIGraphicsContext.State.SUSPENDING)
{
GUIGraphicsContext.CurrentState = GUIGraphicsContext.State.RUNNING;
}
// Wait until is done
SeekFinished.Set();
}).Start();

// Reset seek
SeekFinished.WaitOne(5000);
_SeekAbsoluteDone = false;
}
}

Expand Down

0 comments on commit 45ed6cc

Please sign in to comment.