'AvaloniaUI: Cannot embed VideoView control (LibVlcSharp) in a UserControl
I am new to AvaloniaUI 0.10.5. Currently I am using the VideoView control (LibVLCSharp.Avalonia 3.5.0) in an application on macOS. The code is a copy of Donadren example 2: (https://github.com/donandren/vlcsharpavalonia/tree/master/samples/LibVLCSharp.Avalonia.Sample).
The video player works fine in a Window control but when I copy the code into UserControl (to reuse the player in a different place in my application) I hear the sound of the video but not the image. In the console I have this error:
[h264 @ 0x7ff85e8d3600] get_buffer () failed
[h264 @ 0x7ff85e8d3600] thread_get_buffer () failed
[h264 @ 0x7ff85e8d3600] decode_slice_header error
[h264 @ 0x7ff85e8d3600] no frame!
I tried to search all over the web but couldn't find anything.
Can you help me please, Thanks and Sorry for my bad english.
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Avalonia.NETCoreMVVMApp3.ViewModels"
xmlns:avalonia="clr-namespace:LibVLCSharp.Avalonia;assembly=LibVLCSharp.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Avalonia.NETCoreMVVMApp3.Views.VlcControl">
<Design.DataContext>
<viewModels:VlcControlViewModel/>
</Design.DataContext>
<Grid RowDefinitions="*, Auto">
<avalonia:VideoView x:Name="VideoView" Grid.Row="0" MediaPlayer="{Binding MediaPlayer}">
</avalonia:VideoView>
<Grid Grid.Row="1" RowDefinitions="Auto,Auto,Auto">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<TextBlock Text="File (url):" Grid.Column="0" VerticalAlignment="Center" />
<AutoCompleteBox Name="mediaUrl" Text="{Binding MediaUrl, Mode=TwoWay}" Items="{Binding Played}" FilterMode="Contains" Grid.Column="1" IsDropDownOpen="False" />
<Button Content="Open File" Command="{Binding OpenCommand}" Grid.Column="2" />
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="Auto,*,Auto">
<TextBlock Text="{Binding CurrentTime}" Grid.Column="0" />
<TextBlock Text="{Binding Duration}" Grid.Column="2" />
<Slider Minimum="0" Maximum="100" Value="{Binding Position}" Grid.Column="1" />
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="Auto, *,Auto">
<StackPanel Orientation="Horizontal" Grid.Column="0" Spacing="5">
<Button Content="Play" Command="{Binding PlayCommand}" />
<Button Content="Stop" Command="{Binding StopCommand}" />
<Button Content="Pause" Command="{Binding PauseCommand}" />
<Button Content="-1s" Command="{Binding BackwardCommand}" />
<Button Content="+1s" Command="{Binding ForwardCommand}" />
<Button Content="Next Frame" Command="{Binding NextFrameCommand}" />
</StackPanel>
<Grid ColumnDefinitions="Auto,*" Grid.Column="1">
<TextBlock Text="{Binding State, StringFormat='State:\{0\}'}" Grid.Column="0" VerticalAlignment="Center" />
<ScrollViewer Grid.Column="1" MaxHeight="40" HorizontalScrollBarVisibility="Disabled">
<TextBlock Margin="5,0,0,0" Text="{Binding Information}" TextWrapping="Wrap" VerticalAlignment="Center" />
</ScrollViewer>
</Grid>
<StackPanel Orientation="Horizontal" Grid.Column="2" Spacing="2">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Rendering:" VerticalAlignment="Center" />
<ComboBox SelectedIndex="{Binding #VideoView.VlcRenderingOptions}">
<ComboBoxItem Content="{x:Static avalonia:LibVLCAvaloniaRenderingOptions.VlcNative}" />
<ComboBoxItem Content="{x:Static avalonia:LibVLCAvaloniaRenderingOptions.Avalonia}" />
<ComboBoxItem Content="{x:Static avalonia:LibVLCAvaloniaRenderingOptions.AvaloniaCustomDrawingOperation}" />
</ComboBox>
</StackPanel>
<CheckBox Content="Stats" IsChecked="{Binding #VideoView.DisplayRenderStats}" />
<CheckBox Content="Volume:" IsChecked="{Binding !IsMuted, Mode=TwoWay}" />
<Slider IsEnabled="{Binding !IsMuted}" Minimum="0" Maximum="100" Width="200" Value="{Binding Volume}" VerticalAlignment="Center">
<Slider.Styles>
<Style Selector="Slider:disabled">
<Setter Property="Opacity" Value="0.5" />
</Style>
</Slider.Styles>
</Slider>
</StackPanel>
</Grid>
</Grid>
</Grid>
</UserControl>
Solution 1:[1]
Well known are the problems of Avalonia regarding not being able to use VideoView in an Avalonia UserControl (only in a window) and not being able to use a control in a layer on top of the VLC MediaPlayer.
With a little "luck" I managed to put together a fairly elegant method (perhaps one of many possible, though none so far) to solve all these problems.
So that, on Github I created 2 repositories to share and show how to:
- Embed LibVLCSharp Avalonia VLC VideoView in Avalonia Window (AvaVLCWindow)
- Embed LibVLCSharp Avalonia VLC VideoView in Avalonia UserControl (AvaVLCControl)
- Put and use an Avalonia UserControl on top of VideoView (VLC MediaPlayer), for example, a set of buttons/controls to control the VLC MediaPlayer (in both repositories).
Feel free to explore and understand the code and build/run it. VS 2019 needed.
The standard VideoView.cs code (from LibVLCSharp.Avalonia standard project) has been modified to reach the listed results and the modified (very small) LibVLCSharp.Avalonia project has been included in both repos.
To give the ability to put an Avalonia UserControl on top of the VLC MediaPlayer, I added a new Content property to VideoView which will create and handle its own new top window and add the Content to this window.
You can create the Content as a new UserControl (for example, a MediaPlayer set of controls) and add this UserControl to the VideoView content, like in:
<vlcsharp:VideoView
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
x:Name="VideoViewer">
<!-- Content -->
<Panel
VerticalAlignment="Bottom"
Opacity="0.8"
Background="Gray">
<controls:PlayerControls/>
</Panel>
</vlcsharp:VideoView>
To show the results I reached, in both repositories I created a user control with 2 buttons: Play and Stop. The control position is at the bottom and the buttons are shown using PointerEnter/PointerLeave events, so the buttons will be shown/hided moving your mouse in the right places. I used a simple not animated opacity, set to 0.8 (Enter) and to 0 (Leave).
You can add some kind of animation and/or expand the features. I'm too lazy to do this in the repos, as they are just POCs (Proof of Concepts).
Note: everything has been tested on Windows 10, Kubuntu 18.04, MacOS 10.13, Raspberry Pi3 Model B DietPi(MATE), without any change in code source.
EDIT: Successfully tested on Kubuntu 18.04
Successfully tested on MacOS 10.13 (High Sierra)
EDIT: Successfully tested on Raspberry DietPi (MATE or Xfce)
Previous tests with Raspbian Stretch were not working (transparency and opacity didn't work and playback was full of jerks and pixelated)
With DietPi and MATE (or Xfce) transparency and opacity properties of the overlay control (buttons) are fully honored. Playback is smooth without jerks, interruptions or whatever.
As root, I installed libx11-dev, libvlc-dev and vlc
, copied the published sample (built in Windows 10 with dotnet publish -c release -f net5.0 -r linux-arm
), chmod 777 the whole folder content
and ran the sample. It has to be ran as root or with sudo.
EDIT April 27,2022
The new release of the Unofficial Avalonia LibVLCSharp, allows to display multiple draggable controls over the scene of a video played with LibVLCSharp in an Avalonia app.
For anyone is interested. Enjoy.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |