Add a NativeEmbeddingControl class that inherits from NativeControlHost in MainWindow.axaml.cs
namespace AvaloniaDXPlayer
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
...
public class NativeEmbeddingControl : NativeControlHost
{
public IntPtr Handle { get; private set; }
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
var handle = base.CreateNativeControlCore(parent);
Handle = handle.Handle;
Console.WriteLine($"Handle : {Handle}");
return handle;
}
}
}
Add a NativeEmbeddingControl class that inherits from NativeControlHost in MainWindow.axaml.cs
<Window 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:nec="clr-namespace:AvaloniaDXPlayer"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:Class="AvaloniaDXPlayer.MainWindow"
Width="800" Height="600" Title="AvaloniaDXPlayer">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Black">
<nec:NativeEmbeddingControl x:Name="host" Grid.Row="0" SizeChanged="Host_SizeChanged" />
</Grid>
<Canvas Grid.Row="1">
<TextBox x:Name="textURL" Margin="10" Width="300" Height="20" FontSize="14" Text=""/>
<Button x:Name="btnConnect" Content="Connect" Margin="320,10,0,0" />
<Button x:Name="btnClose" Content="Close" Margin="400,10,0,0" />
<Button x:Name="btnTest" Content="Test" Margin="460,10,0,0" />
</Canvas>
</Grid>
</Window>
Initialize SDL2. During this, insert the Handle of NativeEmbeddingControl as an argument into SDL_CreateWindowFrom
#if defined(LINUX)
typedef void* HWND;
#endif
...
int VideoSDLDraw::init(HWND hwnd, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
{
release();
DXPRINTF("VideoSDLDraw::init %dx%d, %dx%d\n", targetWidth, targetHeight, srcWidth, srcHeight);
MUTEX_LOCK(&m_mutex);
Uint32 pixelFormat = SDL_PIXELFORMAT_UNKNOWN;
m_pWindow = SDL_CreateWindowFrom(hwnd);
if (m_pWindow == NULL) {
DXPRINTF("Window could not be created! SDL Error: %s\n", SDL_GetError());
goto fail;
}
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (m_pRenderer == NULL) {
DXPRINTF("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
m_nTextureWidth = m_nTextureHeight = 0;
goto fail;
}
else {
//Initialize renderer color
SDL_SetRenderDrawColor(m_pRenderer, 0x00, 0x00, 0x00, 0xFF);
for (int i = 0; i < m_nTextDraw; i++) m_pTextDraw[i]->setSDLRenderer(m_pRenderer);
}
#if defined(LINUX)
if (targetWidth == 0 && targetHeight == 0) {
SDL_GetWindowSize(m_pWindow, &targetWidth, &targetHeight);
}
#endif
pixelFormat = SDL_GetWindowPixelFormat(m_pWindow);
m_pTexture = SDL_CreateTexture(m_pRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING, targetWidth, targetHeight);
if (m_pTexture == NULL) {
DXPRINTF("Unable to create streamable texture! SDL Error: %s\n", SDL_GetError());
m_nTextureWidth = m_nTextureHeight = 0;
goto fail;
}
m_nTextureWidth = targetWidth;
m_nTextureHeight = targetHeight;
SetRectEmpty(&m_rectTargetLast);
SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(m_pRenderer, &rendererInfo);
DXPRINTF("SDL Renderer : %s\n", rendererInfo.name);
MUTEX_UNLOCK(&m_mutex);
return 0;
fail:
MUTEX_UNLOCK(&m_mutex);
return -1;
}
After initialization as described above, render the decoded video data on m_pTexture with SDL2 rendering function.
The result is as shown in the figure below.
Linux
Windows