unosquare/ffmediaelement

FFME crashes silently in WPF application

Wicrules opened this issue · 6 comments

FFME crashes silently in WPF application

I have a .Net 6.0 WPF application that uses FFME.Windows 4.4.350. Occasionally, the application exits when a call to MediaElement.Open is made.

Issue Categories

  • [X ] Bug
  • Feature Request
  • Question
  • [X ] Not sure

Version Information

  • [X ] NuGet Package 4.4.350
  • Build From Master branch, Commit Enter commit id. Example: 704c482
  • Build from Branch Name, Commit Enter commit id. Example: 704c482

Steps to Reproduce

  1. Step 1
    Call MediaElement.Open
  2. Step 2
    Several seconds later, call MediaElement.Open again
  3. Step 3
    Crash

Expected Results

Second media is played.

Sample Code

XAML

<ffme:MediaElement x:Name="MediaPlayer" Background="Gray" LoadedBehavior="Play" UnloadedBehavior="Manual" Grid.Column="0"
                           HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>

C#

if (mDispatcher != Dispatcher.CurrentDispatcher)
            {
                mDispatcher.Invoke(() => PlayFile(fileName, loop));
            }
            else
            {
                try
                {
                    if (MediaPlayer.MediaState != MediaPlaybackState.Stop)
                    {
                        await MediaPlayer.Stop();
                        await MediaPlayer.Close();
                    }

                    MediaPlayer.LoopingBehavior = loop ? MediaPlaybackState.Play : MediaPlaybackState.Stop;
                    await MediaPlayer.Open(new FileInputStream(fileName));
                    mLogger?.Info($"Playing {fileName}.");
                }
                catch (Exception ex)
                {
                    mLogger?.Error($"Error trying to play video {fileName}.{Environment.NewLine}{ex.Message}");
                }
            }

I am ensuring the call is being made from the main UI thread and it is wrapped in a try/catch block. However, I never catch the exception in that try/catch or even the Dispatcher.UnhandledException handler in the main application. My understanding is that for c# 5.0 and above, I should be able to catch the exception using that syntax. Any suggestions on how to catch this exception and/or find out what is going on via a log file, etc. would be greatly appreciated.

        // Add in your's loaded function or other init function,it's global ^-^
        Library.FFmpegDirectory ="c:\\ffmpeg"; // The ffmpeg install path 
        Library.LoadFFmpeg();

`private void FfPlayer_OnMediaOpening(object? sender, MediaOpeningEventArgs e) { if (e.Options.VideoStream is { } videoStream) { // Hardware device priorities var deviceCandidates = new[] { AVHWDeviceType.AV_HWDEVICE_TYPE_CUDA, AVHWDeviceType.AV_HWDEVICE_TYPE_D3D11VA, AVHWDeviceType.AV_HWDEVICE_TYPE_DXVA2 };

        // Hardware device selection
        if (videoStream.FPS <= 30)
            foreach (var deviceType in deviceCandidates)
            {
                var accelerator = videoStream.HardwareDevices.FirstOrDefault(d => d.DeviceType == deviceType);
                if (accelerator == null) continue;
                if (Debugger.IsAttached)
                    e.Options.VideoHardwareDevice = accelerator;

                break;
            }
    }
}`

I don't know why, but after I added this code, the problem was solved

I'll try it and then reply,thanks!

I can confirm: bug exist, reproducible and pretty annoying; trick above (with providing VideoHardwareDevice) just hides the issue (especially if you update your project to NET Core 3.1, crashes become very rare) but not resolving it completely.

It's a pity, FFME is a pretty useful project.

FFME crashes silently in WPF application

I have a .Net 6.0 WPF application that uses FFME.Windows 4.4.350. Occasionally, the application exits when a call to MediaElement.Open is made.

Issue Categories

  • [X ] Bug
  • Feature Request
  • Question
  • [X ] Not sure

Version Information

  • [X ] NuGet Package 4.4.350
  • Build From Master branch, Commit Enter commit id. Example: 704c482
  • Build from Branch Name, Commit Enter commit id. Example: 704c482

Steps to Reproduce

  1. Step 1
    Call MediaElement.Open
  2. Step 2
    Several seconds later, call MediaElement.Open again
  3. Step 3
    Crash

Expected Results

Second media is played.

Sample Code

XAML

<ffme:MediaElement x:Name="MediaPlayer" Background="Gray" LoadedBehavior="Play" UnloadedBehavior="Manual" Grid.Column="0"
                           HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>

C#

if (mDispatcher != Dispatcher.CurrentDispatcher)
            {
                mDispatcher.Invoke(() => PlayFile(fileName, loop));
            }
            else
            {
                try
                {
                    if (MediaPlayer.MediaState != MediaPlaybackState.Stop)
                    {
                        await MediaPlayer.Stop();
                        await MediaPlayer.Close();
                    }

                    MediaPlayer.LoopingBehavior = loop ? MediaPlaybackState.Play : MediaPlaybackState.Stop;
                    await MediaPlayer.Open(new FileInputStream(fileName));
                    mLogger?.Info($"Playing {fileName}.");
                }
                catch (Exception ex)
                {
                    mLogger?.Error($"Error trying to play video {fileName}.{Environment.NewLine}{ex.Message}");
                }
            }

I am ensuring the call is being made from the main UI thread and it is wrapped in a try/catch block. However, I never catch the exception in that try/catch or even the Dispatcher.UnhandledException handler in the main application. My understanding is that for c# 5.0 and above, I should be able to catch the exception using that syntax. Any suggestions on how to catch this exception and/or find out what is going on via a log file, etc. would be greatly appreciated.

I guess that the exception is thrown on another thread.
Maybe this will give you some guidance.
AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
{
Debug.WriteLine(eventArgs.Exception.ToString());
};
Is the origin of the exception in the native code, there might be a need to wrap-around a native c++ try-catch that then submits the exception as an out parameter to the CLR that rethrows the exception as an CLR exception.

@MrBean2016, actually issue isn't how to catch an exception but how to make FFME working with .NET standard stack without crashing. Same code is working perfectly on .NET Framework from 3.7 till 3.8.1 but crashes periodically on media opening on NET 5.0 - .NET Core 3.1

@MrBean2016, actually issue isn't how to catch an exception but how to make FFME working with .NET standard stack without crashing. Same code is working perfectly on .NET Framework from 3.7 till 3.8.1 but crashes periodically on media opening on NET 5.0 - .NET Core 3.1

Sorry, I was a bit unclear. The purpose of catching the native exception is to find out which part of the code where the problem is. C/C++ exceptions are not compatible with .Net 5/6/7 so one must build a CLR-wrapper and catching the native exceptions in the wrapper (they wont show up in the debugger).

But one thing to try is in the example in the first post to change from invoke() to begininvoke() since you may not want a thread to wait on finish execution, especially if that delegate performs I/O (which could make the delegate and your gui thread block) and the risk of deadlock since the mediaopening event will be called.