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; }