SuRGeoNix / Flyleaf

Media Player .NET Library for WinUI 3/ WPF/WinForms (based on FFmpeg/DirectX)
GNU Lesser General Public License v3.0
700 stars 95 forks source link

How to use this player just from code without XAML #124

Closed OneB1t closed 2 years ago

OneB1t commented 2 years ago

hello is it possible to use this player inside WPF just from code? without XAML? i need to create it on the fly when app is running but i cannot find any way how to avoid binding etc.. my aproach was something like this

SuRGeoNix commented 2 years ago

Just use the Player's methods? I can't really understand the question. Let me know what you want to do so I can help you more.

OneB1t commented 2 years ago
        FlyleafLib.Engine.Start(new EngineConfig()
        {
            UIRefresh = true,  // Required for Activity,BufferedDuration,Stats in combination with Config.Player.Stats = true
            UIRefreshInterval = 250,   // How often to update the UI
            UICurTimePerSecond = false, // Whether to update CurTime only when it's second changed or by UIRefreshInterval
            HighPerformaceTimers = true, // Forces TimeBeginPeriod(1) always active

            //LogOutput           = ":debug",
            LogOutput           = ":console",
            //LogOutput = "C:\\logs\\file.log",

            LogLevel = FlyleafLib.LogLevel.Debug,
            FFmpegLogLevel = FFmpegLogLevel.Warning,

            FFmpegPath = Environment.CurrentDirectory + Path.DirectorySeparatorChar,
        });

        var started = FlyleafLib.Engine.Started;
        Config Config = new Config();

        // Inform the lib to refresh stats
        Config.Player.Stats = true;

        // To prevent capturing keys while we type within textboxes etc
        Config.Player.KeyBindings.FlyleafWindow = false;
        Config.Player.Usage = Usage.LowLatencyVideo;
        Config.Player.AutoPlay = false;

        Player player = new Player(Config);
        player.Control = new FlyleafLib.Controls.Flyleaf(); // this is only for winforms
        player.VideoView = new VideoView() { Player = player };
        player.Open(videoUri.AbsolutePath,true,true,true);
        player.Seek(1000);
        player.Play();
        return player.VideoView;

i need something like this but this just shows yellow square.. :-/

basically i need "UIelement" in order to add it into existing canvas

SuRGeoNix commented 2 years ago

You Open before the application (winform) loads. Add button and run the open/seek/play from there. Check the winforms samples

OneB1t commented 2 years ago

I already checked that but there is nothing which can help me :-/ i have WPF application where i create UIelements on the fly (based on data from server)

i have other FFMPEG based c# player but it is lacking performance for 4K video playback due to copy of video image into bitmap. Is this player better or i will have same issue? Thanks :-)

SuRGeoNix commented 2 years ago

You confused me. Are you using winforms or wpf? For the example that you say (WPF on the fly), you might want to check the Test PlayerDispose

FlyleafLib supports VA/HW Acceleration so you will not have this issue as far as your GPU supports the video codec profile for hardware acceleration decoding.

(Just noticed that you manually set the VideoView, check PlayerDispose if you want to dynamically create the videoview on wpf)

OneB1t commented 2 years ago

I have WPF app :-) problem is that when i remove player.Control = new FlyleafLib.Controls.Flyleaf(); // this is only for winforms

it will wait forever for control (11.50.47.352 | Debug | [#1] [Player ] Creating (Usage = LowLatencyVideo) ... (1/3 waiting for control to set)

i do not care about control that much i just want to autoplay video in UIelement (that player.VideoView to place it into canvas)

my FFMPEG based player (https://github.com/unosquare/ffmediaelement) also supports HW accel but problem is not with video decode it is with copy of final decoded image into WPF bitmap (that is slow for example same issue as here https://github.com/cefsharp/CefSharp/issues/1058)

it works well for 1080p but as you go higher in resolution it is really painfully slow. This does not happen with winforms but i cannot really use it easily (airgap issues)

SuRGeoNix commented 2 years ago

Flyleaf works all the way in GPU, so you should play 4K smoothly. Now, I'm not sure what you are trying to do but it requires to have a VideoView which will create also the control (so no need to create the control manually, just apply the template of the video view). I think the PlayerDispose sample it's straight forward by using the content control only in XAML.

VideoView will create a winforms control (requires a different window handle control) and a follower foreground window for it with videoview's content to achieve true transparency.

OneB1t commented 2 years ago

I want to add it into WPF canvas all the way from code no XAML involved when i copy FlyleafWPFControl.xaml.cs + FlyleafWPFControl.xaml from that example into my codebase i receive following exception on InitializeComponent();

TypeLoadException: Typ FlyleafLib.Master from FlyleafLib, Version=3.4.9.0, Culture=neutral, PublicKeyToken=null cannot be loaded

but it works well when i download your repository and run disposeplayer so i will try to trace it...

thanks for support it is very helpfull 👍

SuRGeoNix commented 2 years ago

No problem, however you will need to read some basics about C# and WPF. The error that you get is because the solution project (PlayerDispose) has a project reference to FlyleafLib project and not the NuGet package. So if you copying the files to another solution you will need to fix the reference. Just remove it and add the nuget package. Now to add the videoview manually you will need a content control. Why don't you just use the VideoView in xaml directly?

OneB1t commented 2 years ago

ok i sucesfully managed to make it run inside my project now thanks :-) final code is

            Player player = new Player();

            player.VideoView = new VideoView();
            player.VideoView.ApplyTemplate();

            player.VideoView.Player = player;
            player.OpenAsync(videoUri.AbsolutePath);
            return player.VideoView;