unosquare / ffmediaelement

FFME: The Advanced WPF MediaElement (based on FFmpeg)
https://unosquare.github.io/ffmediaelement/
Other
1.17k stars 238 forks source link

MediaEnded event is called multiple times #586

Open alesebi91 opened 2 years ago

alesebi91 commented 2 years ago

MediaEnded event is called multiple times

MediaEnded event is called multiple times. I'm trying to develop a video wall that changes video when MediaEnded is called. That causes the issue #582 in .net 6.0 project and makes my app not working in .net 5.0.

the bug is present starting from the nuget package version 4.3.340 and is similar to #314.

Issue Categories

Version Information

Steps to Reproduce

  1. Open a video and play
  2. Bind event MediaElement.MediaEnded and open another video

Expected Results

Sample Code

Attached to bug: VideoWallTest.zip Once open in VS copy examples videos inside "Videos" folder and set "CopyToOutput: Always".

markoweb2 commented 2 years ago

I ran into the same issue. I have my FFME control wired up with Media_Ended event handler, in which I do Close() -> Open() -> Play(), to switch to the next video to play. The first switching works fine, Media_Ended is called once. But from the second switching onwords, Media_Ended is fired multiple of times.

When debugging I found an anomaly, that after Open(), although the Position property was 00:00:00, the ActualPosition property was showing the full length of the previous clip. So I wrote this piece of code, that for the life of me, I can't figure out how this is happening:

private async void videoPlayer_MediaEnded(object sender, EventArgs e)
{
    await this.videoPlayer.Close();
    await this.videoPlayer.Open(uri);
    System.Diagnostics.Trace.WriteLine(this.videoPlayer.ActualPosition.ToString()); // I place the debugger on this line, ActualPosition is 00:00:00 at this point in time and that is what is shown in the Output window
    await this.videoPlayer.Play(); // hit F11 to come to this line and now the debugger is showing that ActualPosition is the length of the previous clip??
}

You would assume, that the bug which exists in Open() not resetting the internal ActualPosition, would show up with the Trace.WriteLine command, but alas no; await should be synchronous in the sense that whatever Open() did has finished by the time you move on to next line, but that does not seem to be the case...

Anyway, my workaround is to simply Seek() after Open() to force the ActualPosition to become 0. I think that the Media_Ended is fired multiple times, because the internal position is already at the end, and the moment you call Play(), the media has already Ended, thus it gets fired again and you get into a loop...

My workaround code:

private async void videoPlayer_MediaEnded(object sender, EventArgs e)
{
    await this.videoPlayer.Close();
    await this.videoPlayer.Open(uri);
    await this.videPlayer.Seek(TimeSpan.Zero);
    await this.videoPlayer.Play();
}

Do take note, that if you place a breakpoint at Seek() for example and use Shift+F11 to skip over, the Media_Ended event is still fired multiple times. But without a breakpoint, just running the code, everything works, go figure...

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. Thank you for your contributions.

benwilkinson commented 1 year ago

If you use this flag you can filter out the actual end of media videoPlayer.IsAtEndOfStream