diff --git a/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs b/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs
index 69d783cef..038a9ab55 100644
--- a/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs
+++ b/Unosquare.FFME.Windows.Sample/MainWindow.MediaEvents.cs
@@ -90,9 +90,13 @@ private void OnMediaFFmpegMessageLogged(object sender, MediaLogMessageEventArgs
/// The instance containing the event data.
private void OnMediaFailed(object sender, MediaFailedEventArgs e)
{
+ var errorCategory = e.ErrorException is TimeoutException
+ ? "Timeout"
+ : "General";
+
MessageBox.Show(
Application.Current.MainWindow,
- $"Media Failed: {e.ErrorException.GetType()}\r\n{e.ErrorException.Message}",
+ $"Media Failed ({errorCategory}): {e.ErrorException.GetType()}\r\n{e.ErrorException.Message}",
$"{nameof(MediaElement)} Error",
MessageBoxButton.OK,
MessageBoxImage.Error,
@@ -131,7 +135,8 @@ private void OnMediaInitializing(object sender, MediaInitializingEventArgs e)
e.Configuration.GlobalOptions.FlagNoBuffer = true;
// You can change the open/read timeout before the packet reading
- // operation fails.
+ // operation fails. Reaching a tiemout limit will fire the MediaFailed event
+ // with a TiemoutException
e.Configuration.ReadTimeout = TimeSpan.FromSeconds(10);
}
diff --git a/Unosquare.FFME/Commands/CommandManager.Direct.cs b/Unosquare.FFME/Commands/CommandManager.Direct.cs
index d8a96f054..c037f9b79 100644
--- a/Unosquare.FFME/Commands/CommandManager.Direct.cs
+++ b/Unosquare.FFME/Commands/CommandManager.Direct.cs
@@ -337,6 +337,9 @@ private bool CommandOpenMedia(IMediaInputStream inputStream, Uri streamUri)
}
}
+ // Wire up the interrupt callback
+ containerConfig.ReadTimeoutCallback = (t) => MediaCore?.SendOnMediaFailed(new TimeoutException($"Stream read operation timed out: {t.Format()}"));
+
// Allow the stream input options to be changed
MediaCore.SendOnMediaInitializing(containerConfig, mediaSource);
diff --git a/Unosquare.FFME/Common/ContainerConfiguration.cs b/Unosquare.FFME/Common/ContainerConfiguration.cs
index 8bd012f4d..c96e6be09 100644
--- a/Unosquare.FFME/Common/ContainerConfiguration.cs
+++ b/Unosquare.FFME/Common/ContainerConfiguration.cs
@@ -52,5 +52,10 @@ internal ContainerConfiguration()
///
public Dictionary PrivateOptions { get; } =
new(512, StringComparer.InvariantCultureIgnoreCase);
+
+ ///
+ /// Gets or sets a method to be called when reading the input stream has timed out.
+ ///
+ internal Action ReadTimeoutCallback { get; set; }
}
}
diff --git a/Unosquare.FFME/Container/MediaContainer.cs b/Unosquare.FFME/Container/MediaContainer.cs
index 87da2024d..616664dcb 100644
--- a/Unosquare.FFME/Container/MediaContainer.cs
+++ b/Unosquare.FFME/Container/MediaContainer.cs
@@ -1034,6 +1034,7 @@ private int OnStreamReadInterrupt(void* opaque)
return OkResult;
this.LogError(Aspects.Container, $"{nameof(OnStreamReadInterrupt)} timed out with {timeDifference.Format()}");
+ Configuration.ReadTimeoutCallback?.Invoke(timeDifference);
return ErrorResult;
}