2023년 11월 24일 금요일

Rendering Video in Avalonia's NativeControlHost with SDL2.

 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





댓글 없음:

댓글 쓰기