Add setting page for decoder

This commit is contained in:
2025-09-26 23:46:21 +09:00
parent 0647630959
commit e87c602b5f
9 changed files with 479 additions and 7 deletions

View File

@@ -3,6 +3,7 @@
#include "MainVideoPage.xaml.h"
#include "MultiVideoPage.xaml.h"
#include "LayeredVideoPage.xaml.h"
#include "SettingsPage.xaml.h"
#include "src/Logger/LogManager.h"
#include <microsoft.ui.xaml.window.h>
#include <dwmapi.h>
@@ -101,8 +102,10 @@ namespace winrt::Vav2Player::implementation
void MainWindow::Settings_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
{
// Could implement Settings functionality
// For now, just show a message (no status bar in frame layout)
TypeName pageTypeName;
pageTypeName.Name = winrt::name_of<Vav2Player::SettingsPage>();
pageTypeName.Kind = TypeKind::Metadata;
ContentFrame().Navigate(pageTypeName);
}
void MainWindow::About_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)

View File

@@ -0,0 +1,8 @@
namespace Vav2Player
{
[default_interface]
runtimeclass SettingsPage : Microsoft.UI.Xaml.Controls.Page
{
SettingsPage();
};
}

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="Vav2Player.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Vav2Player"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer>
<StackPanel Margin="40,20,40,40" Spacing="24">
<!-- Page Header -->
<TextBlock Text="Settings"
Style="{StaticResource TitleTextBlockStyle}"
Margin="0,0,0,20"/>
<!-- Decoder Settings Section -->
<StackPanel Spacing="16">
<TextBlock Text="Video Decoder"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Select the preferred AV1 video decoder. AUTO mode automatically selects the best available decoder."
Style="{StaticResource BodyTextBlockStyle}"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
TextWrapping="Wrap"
Margin="0,0,0,8"/>
<ComboBox x:Name="DecoderComboBox"
Header="Decoder Type"
MinWidth="300"
SelectionChanged="DecoderComboBox_SelectionChanged">
<ComboBoxItem Content="AUTO - Best Available" Tag="AUTO"/>
<ComboBoxItem Content="NVDEC - NVIDIA Hardware" Tag="NVDEC"/>
<ComboBoxItem Content="VPL - Intel Hardware" Tag="VPL"/>
<ComboBoxItem Content="AMF - AMD Hardware" Tag="AMF"/>
<ComboBoxItem Content="DAV1D - Software" Tag="DAV1D"/>
<ComboBoxItem Content="Media Foundation - Windows" Tag="MEDIA_FOUNDATION"/>
</ComboBox>
<!-- Decoder Status Info -->
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
Padding="16"
Margin="0,8,0,0">
<StackPanel Spacing="8">
<TextBlock Text="Current Decoder Status"
Style="{StaticResource BodyStrongTextBlockStyle}"/>
<TextBlock x:Name="DecoderStatusText"
Text="Status will be displayed here..."
Style="{StaticResource BodyTextBlockStyle}"
TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Quality Settings Section -->
<StackPanel Spacing="16">
<TextBlock Text="Video Quality"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Adjust quality settings for optimal performance on your hardware."
Style="{StaticResource BodyTextBlockStyle}"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
TextWrapping="Wrap"
Margin="0,0,0,8"/>
<ComboBox x:Name="QualityComboBox"
Header="Quality Mode"
MinWidth="300"
SelectionChanged="QualityComboBox_SelectionChanged">
<ComboBoxItem Content="CONSERVATIVE - Highest Quality" Tag="CONSERVATIVE"/>
<ComboBoxItem Content="FAST - Balanced" Tag="FAST"/>
<ComboBoxItem Content="ULTRA_FAST - Performance" Tag="ULTRA_FAST"/>
</ComboBox>
</StackPanel>
<!-- About Section -->
<StackPanel Spacing="16">
<TextBlock Text="About"
Style="{StaticResource SubtitleTextBlockStyle}"/>
<Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
Padding="16">
<StackPanel Spacing="8">
<TextBlock Text="Vav2Player"
Style="{StaticResource BodyStrongTextBlockStyle}"/>
<TextBlock Text="Advanced AV1 Video Player with Hardware Acceleration"
Style="{StaticResource BodyTextBlockStyle}"/>
<TextBlock Text="Supported Decoders: NVDEC, Intel VPL, AMD AMF, dav1d, Media Foundation"
Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"/>
</StackPanel>
</Border>
</StackPanel>
<!-- Action Buttons -->
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,20,0,0">
<Button x:Name="ApplyButton"
Content="Apply Settings"
Style="{StaticResource AccentButtonStyle}"
Click="ApplyButton_Click"/>
<Button x:Name="ResetButton"
Content="Reset to Defaults"
Click="ResetButton_Click"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Page>

View File

@@ -0,0 +1,222 @@
#include "pch.h"
#include "SettingsPage.xaml.h"
#include "src/Logger/LogManager.h"
#if __has_include("SettingsPage.g.cpp")
#include "SettingsPage.g.cpp"
#endif
using namespace winrt;
using namespace winrt::Microsoft::UI::Xaml;
using namespace winrt::Microsoft::UI::Xaml::Controls;
namespace winrt::Vav2Player::implementation
{
SettingsPage::SettingsPage()
{
this->InitializeComponent();
LoadSettings();
UpdateDecoderStatus();
}
void SettingsPage::DecoderComboBox_SelectionChanged(IInspectable const& sender, SelectionChangedEventArgs const& e)
{
auto comboBox = sender.as<ComboBox>();
auto selectedItem = comboBox.SelectedItem().as<ComboBoxItem>();
if (selectedItem)
{
auto tag = selectedItem.Tag().as<hstring>();
m_selectedDecoderType = GetDecoderTypeFromTag(tag);
UpdateDecoderStatus();
}
}
void SettingsPage::QualityComboBox_SelectionChanged(IInspectable const& sender, SelectionChangedEventArgs const& e)
{
auto comboBox = sender.as<ComboBox>();
auto selectedItem = comboBox.SelectedItem().as<ComboBoxItem>();
if (selectedItem)
{
auto tag = selectedItem.Tag().as<hstring>();
m_selectedQualityMode = GetQualityModeFromTag(tag);
}
}
void SettingsPage::ApplyButton_Click(IInspectable const& sender, RoutedEventArgs const& e)
{
SaveSettings();
// Log settings application for VideoPlayerControl to detect
std::wstring message = L"Settings applied - Decoder: ";
switch (m_selectedDecoderType) {
case VAVCORE_DECODER_AUTO: message += L"Auto"; break;
case VAVCORE_DECODER_DAV1D: message += L"Software (dav1d)"; break;
case VAVCORE_DECODER_MEDIA_FOUNDATION: message += L"Hardware (Media Foundation)"; break;
case VAVCORE_DECODER_NVDEC: message += L"Hardware (NVDEC)"; break;
case VAVCORE_DECODER_VPL: message += L"Hardware (Intel VPL)"; break;
case VAVCORE_DECODER_AMF: message += L"Hardware (AMD AMF)"; break;
}
// Use LogManager to notify about settings change
::Vav2Player::LogManager::GetInstance().LogInfo(message, L"Settings");
// Show confirmation
auto dialog = ContentDialog();
dialog.Title(box_value(L"Settings Applied"));
dialog.Content(box_value(L"Settings have been saved successfully. The new decoder settings will be used for new video files. Currently playing videos will use the new decoder when reloaded."));
dialog.CloseButtonText(L"OK");
dialog.XamlRoot(this->XamlRoot());
// Show dialog asynchronously
[dialog]() -> winrt::Windows::Foundation::IAsyncAction {
co_await dialog.ShowAsync();
}();
}
void SettingsPage::ResetButton_Click(IInspectable const& sender, RoutedEventArgs const& e)
{
// Reset to defaults
m_selectedDecoderType = VAVCORE_DECODER_AUTO;
m_selectedQualityMode = VAVCORE_QUALITY_FAST;
// Update UI
DecoderComboBox().SelectedIndex(0); // AUTO
QualityComboBox().SelectedIndex(1); // FAST
UpdateDecoderStatus();
// Auto-save
SaveSettings();
}
void SettingsPage::LoadSettings()
{
// Load from Windows.Storage.ApplicationData.Current.LocalSettings
auto localSettings = Windows::Storage::ApplicationData::Current().LocalSettings();
auto values = localSettings.Values();
// Load decoder type (default: AUTO)
if (values.HasKey(L"DecoderType"))
{
m_selectedDecoderType = static_cast<VavCoreDecoderType>(unbox_value<int32_t>(values.Lookup(L"DecoderType")));
}
else
{
m_selectedDecoderType = VAVCORE_DECODER_AUTO;
}
// Load quality mode (default: FAST)
if (values.HasKey(L"QualityMode"))
{
m_selectedQualityMode = static_cast<VavCoreQualityMode>(unbox_value<int32_t>(values.Lookup(L"QualityMode")));
}
else
{
m_selectedQualityMode = VAVCORE_QUALITY_FAST;
}
// Update UI controls
auto decoderTag = GetTagFromDecoderType(m_selectedDecoderType);
auto qualityTag = GetTagFromQualityMode(m_selectedQualityMode);
// Set decoder combobox selection
for (uint32_t i = 0; i < DecoderComboBox().Items().Size(); ++i)
{
auto item = DecoderComboBox().Items().GetAt(i).as<ComboBoxItem>();
if (item.Tag().as<hstring>() == decoderTag)
{
DecoderComboBox().SelectedIndex(i);
break;
}
}
// Set quality combobox selection
for (uint32_t i = 0; i < QualityComboBox().Items().Size(); ++i)
{
auto item = QualityComboBox().Items().GetAt(i).as<ComboBoxItem>();
if (item.Tag().as<hstring>() == qualityTag)
{
QualityComboBox().SelectedIndex(i);
break;
}
}
}
void SettingsPage::SaveSettings()
{
// Save to Windows.Storage.ApplicationData.Current.LocalSettings
auto localSettings = Windows::Storage::ApplicationData::Current().LocalSettings();
auto values = localSettings.Values();
values.Insert(L"DecoderType", box_value(static_cast<int32_t>(m_selectedDecoderType)));
values.Insert(L"QualityMode", box_value(static_cast<int32_t>(m_selectedQualityMode)));
}
void SettingsPage::UpdateDecoderStatus()
{
auto description = GetDecoderDescription(m_selectedDecoderType);
DecoderStatusText().Text(description);
}
hstring SettingsPage::GetDecoderDescription(VavCoreDecoderType type)
{
switch (type)
{
case VAVCORE_DECODER_AUTO:
return L"Automatically selects the best available decoder based on hardware capabilities and performance. Recommended for most users.";
case VAVCORE_DECODER_NVDEC:
return L"NVIDIA hardware-accelerated decoder. Requires NVIDIA GPU with AV1 decode support (RTX 30 series or newer).";
case VAVCORE_DECODER_DAV1D:
return L"Software decoder with CPU optimization. Works on all systems but may use more CPU resources.";
case VAVCORE_DECODER_MEDIA_FOUNDATION:
return L"Windows Media Foundation decoder. Uses system-provided AV1 decoding capabilities.";
default:
return L"Unknown decoder type.";
}
}
VavCoreDecoderType SettingsPage::GetDecoderTypeFromTag(hstring const& tag)
{
if (tag == L"AUTO") return VAVCORE_DECODER_AUTO;
if (tag == L"NVDEC") return VAVCORE_DECODER_NVDEC;
if (tag == L"VPL") return VAVCORE_DECODER_VPL;
if (tag == L"AMF") return VAVCORE_DECODER_AMF;
if (tag == L"DAV1D") return VAVCORE_DECODER_DAV1D;
if (tag == L"MEDIA_FOUNDATION") return VAVCORE_DECODER_MEDIA_FOUNDATION;
return VAVCORE_DECODER_AUTO;
}
VavCoreQualityMode SettingsPage::GetQualityModeFromTag(hstring const& tag)
{
if (tag == L"CONSERVATIVE") return VAVCORE_QUALITY_CONSERVATIVE;
if (tag == L"FAST") return VAVCORE_QUALITY_FAST;
if (tag == L"ULTRA_FAST") return VAVCORE_QUALITY_ULTRA_FAST;
return VAVCORE_QUALITY_FAST;
}
hstring SettingsPage::GetTagFromDecoderType(VavCoreDecoderType type)
{
switch (type)
{
case VAVCORE_DECODER_AUTO: return L"AUTO";
case VAVCORE_DECODER_NVDEC: return L"NVDEC";
case VAVCORE_DECODER_VPL: return L"VPL";
case VAVCORE_DECODER_AMF: return L"AMF";
case VAVCORE_DECODER_DAV1D: return L"DAV1D";
case VAVCORE_DECODER_MEDIA_FOUNDATION: return L"MEDIA_FOUNDATION";
default: return L"AUTO";
}
}
hstring SettingsPage::GetTagFromQualityMode(VavCoreQualityMode mode)
{
switch (mode)
{
case VAVCORE_QUALITY_CONSERVATIVE: return L"CONSERVATIVE";
case VAVCORE_QUALITY_FAST: return L"FAST";
case VAVCORE_QUALITY_ULTRA_FAST: return L"ULTRA_FAST";
default: return L"FAST";
}
}
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "SettingsPage.g.h"
#include "VavCore/VavCore.h"
namespace winrt::Vav2Player::implementation
{
struct SettingsPage : SettingsPageT<SettingsPage>
{
SettingsPage();
// Event handlers
void DecoderComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
void QualityComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
void ApplyButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
void ResetButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
private:
// Settings storage
VavCoreDecoderType m_selectedDecoderType;
VavCoreQualityMode m_selectedQualityMode;
// Helper methods
void LoadSettings();
void SaveSettings();
void UpdateDecoderStatus();
winrt::hstring GetDecoderDescription(VavCoreDecoderType type);
VavCoreDecoderType GetDecoderTypeFromTag(winrt::hstring const& tag);
VavCoreQualityMode GetQualityModeFromTag(winrt::hstring const& tag);
winrt::hstring GetTagFromDecoderType(VavCoreDecoderType type);
winrt::hstring GetTagFromQualityMode(VavCoreQualityMode mode);
};
}
namespace winrt::Vav2Player::factory_implementation
{
struct SettingsPage : SettingsPageT<SettingsPage, implementation::SettingsPage>
{
};
}

View File

@@ -156,6 +156,9 @@
<ClInclude Include="LogMessagePage.xaml.h">
<DependentUpon>LogMessagePage.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SettingsPage.xaml.h">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="src\Logger\SimpleLogger.h" />
<ClInclude Include="src\Logger\ILogManager.h" />
<ClInclude Include="src\Logger\ILogOutput.h" />
@@ -184,6 +187,7 @@
<Page Include="MultiVideoPage.xaml" />
<Page Include="LayeredVideoPage.xaml" />
<Page Include="LogMessagePage.xaml" />
<Page Include="SettingsPage.xaml" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
@@ -213,6 +217,9 @@
<ClCompile Include="LogMessagePage.xaml.cpp">
<DependentUpon>LogMessagePage.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="SettingsPage.xaml.cpp">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="src\Logger\LogManager.cpp" />
<ClCompile Include="src\Logger\LogOutputs.cpp" />
<!-- <ClCompile Include="src\Decoder\VideoDecoderFactory.cpp" /> -->
@@ -253,6 +260,10 @@
<SubType>Code</SubType>
<DependentUpon>LogMessagePage.xaml</DependentUpon>
</Midl>
<Midl Include="SettingsPage.idl">
<SubType>Code</SubType>
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Midl>
</ItemGroup>
<ItemGroup>
<Text Include="readme.txt">

View File

@@ -7,6 +7,7 @@
// Note: VideoTypes.h not included due to VavCore migration guard
#include <winrt/Microsoft.UI.Dispatching.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Storage.h>
#include <windows.storage.streams.h>
#include <chrono>
#include <algorithm>
@@ -32,6 +33,9 @@ namespace winrt::Vav2Player::implementation
{
InitializeComponent();
// Load decoder settings from Windows.Storage.ApplicationData
LoadDecoderSettings();
// Initialize VavCore library (only once)
static bool vavCoreInitialized = false;
if (!vavCoreInitialized) {
@@ -341,6 +345,8 @@ namespace winrt::Vav2Player::implementation
case VAVCORE_DECODER_DAV1D: decoderName = L"Software (dav1d)"; break;
case VAVCORE_DECODER_MEDIA_FOUNDATION: decoderName = L"Hardware (Media Foundation)"; break;
case VAVCORE_DECODER_NVDEC: decoderName = L"Hardware (NVDEC)"; break;
case VAVCORE_DECODER_VPL: decoderName = L"Hardware (Intel VPL)"; break;
case VAVCORE_DECODER_AMF: decoderName = L"Hardware (AMD AMF)"; break;
}
LogMgr::GetInstance().LogDecoderInfo(decoderName, L"Decoder type selected");
@@ -897,5 +903,63 @@ namespace winrt::Vav2Player::implementation
double VideoPlayerControl::Duration() { return m_duration; }
winrt::hstring VideoPlayerControl::Status() { return m_status; }
void VideoPlayerControl::LoadDecoderSettings()
{
try {
// Load from Windows.Storage.ApplicationData.Current.LocalSettings
auto localSettings = winrt::Windows::Storage::ApplicationData::Current().LocalSettings();
auto values = localSettings.Values();
// Load decoder type (default: AUTO)
if (values.HasKey(L"DecoderType")) {
auto decoderValue = values.Lookup(L"DecoderType");
if (decoderValue) {
int32_t decoderInt = winrt::unbox_value<int32_t>(decoderValue);
m_decoderType = static_cast<VavCoreDecoderType>(decoderInt);
// Log loaded decoder setting
std::wstring decoderName = L"Unknown";
switch (m_decoderType) {
case VAVCORE_DECODER_AUTO: decoderName = L"Auto"; break;
case VAVCORE_DECODER_DAV1D: decoderName = L"Software (dav1d)"; break;
case VAVCORE_DECODER_MEDIA_FOUNDATION: decoderName = L"Hardware (Media Foundation)"; break;
case VAVCORE_DECODER_NVDEC: decoderName = L"Hardware (NVDEC)"; break;
case VAVCORE_DECODER_VPL: decoderName = L"Hardware (Intel VPL)"; break;
case VAVCORE_DECODER_AMF: decoderName = L"Hardware (AMD AMF)"; break;
}
LogMgr::GetInstance().LogInfo(L"Loaded decoder setting: " + decoderName, L"VideoPlayerControl");
}
} else {
m_decoderType = VAVCORE_DECODER_AUTO;
LogMgr::GetInstance().LogInfo(L"Using default decoder: Auto", L"VideoPlayerControl");
}
} catch (...) {
// If settings loading fails, use default
m_decoderType = VAVCORE_DECODER_AUTO;
LogMgr::GetInstance().LogWarning(L"Failed to load decoder settings, using default: Auto", L"VideoPlayerControl");
}
}
void VideoPlayerControl::RefreshDecoderSettings()
{
// Reload decoder settings from storage
LoadDecoderSettings();
// If a video is currently loaded, update the VavCore player with new decoder type
if (m_vavCorePlayer && m_isLoaded) {
vavcore_set_decoder_type(m_vavCorePlayer, m_decoderType);
std::wstring decoderName = L"Unknown";
switch (m_decoderType) {
case VAVCORE_DECODER_AUTO: decoderName = L"Auto"; break;
case VAVCORE_DECODER_DAV1D: decoderName = L"Software (dav1d)"; break;
case VAVCORE_DECODER_MEDIA_FOUNDATION: decoderName = L"Hardware (Media Foundation)"; break;
case VAVCORE_DECODER_NVDEC: decoderName = L"Hardware (NVDEC)"; break;
case VAVCORE_DECODER_VPL: decoderName = L"Hardware (Intel VPL)"; break;
case VAVCORE_DECODER_AMF: decoderName = L"Hardware (AMD AMF)"; break;
}
LogMgr::GetInstance().LogInfo(L"Applied new decoder setting: " + decoderName, L"VideoPlayerControl");
}
}
}

View File

@@ -51,6 +51,7 @@ namespace winrt::Vav2Player::implementation
void Pause();
void Stop();
void Seek(double timeSeconds);
void RefreshDecoderSettings();
// Status Properties
bool IsVideoPlaying();
@@ -120,6 +121,7 @@ namespace winrt::Vav2Player::implementation
void ApplyAspectFitIfReady();
void UpdateStatus(winrt::hstring const& message);
void ResetVideoState();
void LoadDecoderSettings();
};
}

View File

@@ -1,18 +1,17 @@
android player 를 만들어서 av1 디코딩 테스트 필요.
모든 작업이 끝났으면 Vav2Player 의 Setting 화면에 Decoder 를 명시적으로 지정해주는 UI 를 추가해줘.
CLAUDE.md 파일을 확인하여 현재 작업 상황을 점검하고 완료된 항목들을 업데이트해줘.
완료된 사항만 간단하게 적어주고, 불필요한 정보들은 최대한 줄여줘.
VavCoreVideoFrame 에는 color_space 변수가 없다. 차후에 이것을 사용할 기능이 들어가게 될까?
------------
VavCoreVideoFrame 에는 현재 cpu data 만 제공하고 있다.
dx3d surface 에 직접 av1 프레임을 디코딩해주는 SDK 도 있다.
d3d surface 에 직접 av1 프레임을 디코딩해주는 SDK 도 있다.
만약 d3d surface 에 직접 디코딩과 렌더링까지 해준다면, 성능은 더 올라갈 것이다.
각 프레임을 요청할 때, dx3d surface 인자를 제공해주면, surface 에 직접 프레임을 그려줄 수 있는지 조사해서 검토해봐줘.
AMF
@@ -30,3 +29,10 @@ libvpl
nvdec
* header: D:\Project\video-av1\oss\nvidia-video-codec\Interface
* doc: https://docs.nvidia.com/video-technologies/video-codec-sdk/13.0/nvdec-video-decoder-api-prog-guide/index.html
기본 설계 문서를 작성하고, md 파일로 저장해줘.
------------
모든 작업이 끝났으면 Vav2Player 의 Setting 화면에 Decoder 를 명시적으로 지정해주는 UI 를 추가해줘.
Vav2Player 의 Setting 화면에 Decoder 를 명시적으로 지정해주는 UI 를 추가해줘.
Decoder 를 선택해서 고르게 되면, 다음 영상 재생할 때, 해당 디코더로 재생하도록 구현해줘