--- 文件: VideoStandard.cs ---
// VideoStandard.cs
namespace VideoProcessingPlugin
{
    public enum VideoStandard
    {
        PAL,
        NTSC,
        SECAM
    }
}


--- 文件: WriteableBitmapFactory.cs ---
// WriteableBitmapFactory.cs
using System.Windows.Media.Imaging;

namespace VideoProcessingPlugin
{
    public static class WriteableBitmapFactory
    {
        public static WriteableBitmap CreateWriteableBitmap(BitmapSource source)
        {
            return new WriteableBitmap(source);
        }
    }
}


--- 文件: VideoProcessingControl.xaml ---
<!-- VideoProcessingControl.xaml -->
<UserControl x:Class="VideoProcessingPlugin.VideoProcessingControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:VideoProcessingPlugin"
             Height="300" Width="400">
    <StackPanel Margin="10">
        <CheckBox Content="启用 WriteableBitmap" IsChecked="{Binding EnableWriteableBitmap}" Margin="5"/>
        <CheckBox Content="启用模块" IsChecked="{Binding ModuleEnabled}" Margin="5"/>
        <StackPanel Orientation="Horizontal" Margin="5">
            <TextBlock Text="阈值:" VerticalAlignment="Center" Width="100"/>
            <Slider Minimum="0" Maximum="255" Value="{Binding Threshold}" Width="200"/>
            <TextBlock Text="{Binding Threshold}" Width="50" VerticalAlignment="Center"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="5">
            <TextBlock Text="视频制式:" VerticalAlignment="Center" Width="100"/>
            <ComboBox SelectedItem="{Binding VideoStandard, Mode=TwoWay}" Width="200"
                      ItemsSource="{Binding VideoStandards}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </StackPanel>
    </StackPanel>
</UserControl>


--- 文件: VideoProcessingControl.xaml.cs ---
// VideoProcessingControl.xaml.cs
using System.Windows.Controls;

namespace VideoProcessingPlugin
{
    public partial class VideoProcessingControl : UserControl
    {
        public VideoProcessingControl()
        {
            InitializeComponent();
        }
    }
}


--- 文件: VideoProcessingPlugin.cs ---
// VideoProcessingPlugin.cs
using SharedInterfaces;
using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Threading.Tasks;

namespace VideoProcessingPlugin
{
    public class VideoProcessingPlugin : IPluginWithUI
    {
        public string PluginName => "视频处理插件";

        private bool _isEnabled = true;
        public bool IsEnabled
        {
            get => _isEnabled;
            set
            {
                if (_isEnabled != value)
                {
                    _isEnabled = value;
                    // 您可以在这里添加额外的逻辑，例如启用/禁用处理
                }
            }
        }

        public IDictionary<string, object> Parameters { get; private set; }

        private VideoProcessingViewModel _viewModel;
        private UserControl _control;

        public VideoProcessingPlugin()
        {
            Parameters = new Dictionary<string, object>();

            // 初始化默认参数
            Parameters["EnableWriteableBitmap"] = true;
            Parameters["Threshold"] = 7.5;
            Parameters["VideoStandard"] = VideoStandard.PAL;
            Parameters["ModuleEnabled"] = true;
            // 根据需要添加更多参数

            // 现在创建 ViewModel
            _viewModel = new VideoProcessingViewModel(this);
        }

        public void Initialize()
        {
            // 初始化逻辑，例如加载资源等
        }

        public BitmapSource ProcessFrame(BitmapSource frame)
        {
            if (!IsEnabled)
                return frame;

            bool enableWriteableBitmap = true;
            if (Parameters.ContainsKey("EnableWriteableBitmap"))
                enableWriteableBitmap = (bool)Parameters["EnableWriteableBitmap"];

            if (!enableWriteableBitmap)
                return frame;

            double threshold = 7.5;
            if (Parameters.ContainsKey("Threshold"))
                threshold = (double)Parameters["Threshold"];

            VideoStandard standard = VideoStandard.PAL;
            if (Parameters.ContainsKey("VideoStandard"))
                standard = (VideoStandard)Parameters["VideoStandard"];

            bool moduleEnabled = true;
            if (Parameters.ContainsKey("ModuleEnabled"))
                moduleEnabled = (bool)Parameters["ModuleEnabled"];

            if (!moduleEnabled)
                return frame;

            try
            {
                // 异步处理帧
                Task<BitmapSource> processingTask = _viewModel.ProcessFrameAsync(frame, threshold, standard);
                processingTask.Wait(); // 同步等待完成，您也可以根据需要调整为异步

                BitmapSource processedFrame = processingTask.Result;
                return processedFrame;
            }
            catch (AggregateException ae)
            {
                // 处理异常
                foreach (var ex in ae.InnerExceptions)
                {
                    Console.WriteLine($"Error processing frame: {ex.Message}");
                }
                return frame;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error processing frame: {ex.Message}");
                return frame;
            }
        }

        public UserControl GetControl()
        {
            if (_control == null)
            {
                _control = new VideoProcessingControl
                {
                    DataContext = _viewModel
                };
            }
            return _control;
        }
    }
}


--- 文件: VideoProcessingViewModel.cs ---
// VideoProcessingViewModel.cs
using SharedInterfaces;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
using System.Linq;

namespace VideoProcessingPlugin
{
    public class VideoProcessingViewModel : INotifyPropertyChanged
    {
        private readonly IPluginWithUI _plugin;

        private bool _enableWriteableBitmap;
        private double _threshold;
        private VideoStandard _videoStandard;
        private bool _moduleEnabled;

        // 滑动窗口实例
        private ShiftWindow _shiftWindow;

        public bool EnableWriteableBitmap
        {
            get => _enableWriteableBitmap;
            set
            {
                if (_enableWriteableBitmap != value)
                {
                    _enableWriteableBitmap = value;
                    OnPropertyChanged(nameof(EnableWriteableBitmap));
                    _plugin.Parameters["EnableWriteableBitmap"] = value;
                }
            }
        }

        public double Threshold
        {
            get => _threshold;
            set
            {
                if (_threshold != value)
                {
                    _threshold = value;
                    OnPropertyChanged(nameof(Threshold));
                    _plugin.Parameters["Threshold"] = value;
                }
            }
        }

        public VideoStandard VideoStandard
        {
            get => _videoStandard;
            set
            {
                if (_videoStandard != value)
                {
                    _videoStandard = value;
                    OnPropertyChanged(nameof(VideoStandard));
                    _plugin.Parameters["VideoStandard"] = value;
                }
            }
        }

        public bool ModuleEnabled
        {
            get => _moduleEnabled;
            set
            {
                if (_moduleEnabled != value)
                {
                    _moduleEnabled = value;
                    OnPropertyChanged(nameof(ModuleEnabled));
                    _plugin.Parameters["ModuleEnabled"] = value;
                }
            }
        }

        public IEnumerable<VideoStandard> VideoStandards => Enum.GetValues(typeof(VideoStandard)).Cast<VideoStandard>();

        public VideoProcessingViewModel(IPluginWithUI plugin)
        {
            _plugin = plugin;

            // 初始化参数
            if (_plugin.Parameters.ContainsKey("EnableWriteableBitmap"))
                _enableWriteableBitmap = (bool)_plugin.Parameters["EnableWriteableBitmap"];
            else
                _enableWriteableBitmap = true; // 默认值

            if (_plugin.Parameters.ContainsKey("Threshold"))
                _threshold = (double)_plugin.Parameters["Threshold"];
            else
                _threshold = 7.5; // 默认值

            if (_plugin.Parameters.ContainsKey("VideoStandard"))
                _videoStandard = (VideoStandard)_plugin.Parameters["VideoStandard"];
            else
                _videoStandard = VideoStandard.PAL; // 默认值

            if (_plugin.Parameters.ContainsKey("ModuleEnabled"))
                _moduleEnabled = (bool)_plugin.Parameters["ModuleEnabled"];
            else
                _moduleEnabled = true; // 默认值

            // 初始化滑动窗口，假设行长度为1920
            _shiftWindow = new ShiftWindow(1920);
        }

        /// <summary>
        /// 异步处理视频帧
        /// </summary>
        /// <param name="inputFrame">输入帧</param>
        /// <param name="threshold">阈值</param>
        /// <param name="standard">视频制式</param>
        /// <returns>处理后的帧</returns>
        public async Task<BitmapSource> ProcessFrameAsync(BitmapSource inputFrame, double threshold, VideoStandard standard)
        {
            // Ensure the inputFrame is frozen to allow cross-thread access
            BitmapSource frozenFrame = null;
            if (inputFrame.CanFreeze)
            {
                frozenFrame = inputFrame.Clone();
                frozenFrame.Freeze();
            }
            else
            {
                frozenFrame = inputFrame;
            }

            return await Task.Run(() => ProcessFrame(frozenFrame, threshold, standard));
        }

        /// <summary>
        /// 处理视频帧
        /// </summary>
        /// <param name="inputFrame">输入帧</param>
        /// <param name="threshold">阈值</param>
        /// <param name="standard">视频制式</param>
        /// <returns>处理后的帧</returns>
        private BitmapSource ProcessFrame(BitmapSource inputFrame, double threshold, VideoStandard standard)
        {
            if (inputFrame == null)
                return null;

            // 获取像素数据
            int width = inputFrame.PixelWidth;
            int height = inputFrame.PixelHeight;
            int stride = (width * inputFrame.Format.BitsPerPixel + 7) / 8;
            byte[] pixels = new byte[height * stride];
            inputFrame.CopyPixels(pixels, stride, 0);

            // 根据视频制式调整阈值
            double actualThreshold = GetThreshold(standard, threshold);

            for (int y = 0; y < height; y++)
            {
                byte[] line = new byte[width * 4]; // Assuming BGRA format
                Array.Copy(pixels, y * stride, line, 0, width * 4);

                // 逐行处理
                ShiftWindow_A_ProcessLine(line, actualThreshold);

                // 添加到滑动窗口
                _shiftWindow.AddLine(line);

                // 将处理后的行复制回像素数组
                Array.Copy(line, 0, pixels, y * stride, width * 4);
            }

            // 创建新的 BitmapSource
            BitmapSource processedFrame = BitmapSource.Create(
                width,
                height,
                inputFrame.DpiX,
                inputFrame.DpiY,
                inputFrame.Format,
                inputFrame.Palette,
                pixels,
                stride
            );

            // Freeze the processed frame to make it cross-thread accessible
            processedFrame.Freeze();

            return processedFrame;
        }

        /// <summary>
        /// 根据视频制式获取实际阈值
        /// </summary>
        /// <param name="standard">视频制式</param>
        /// <param name="baseThreshold">基础阈值</param>
        /// <returns>实际阈值</returns>
        private double GetThreshold(VideoStandard standard, double baseThreshold)
        {
            switch (standard)
            {
                case VideoStandard.PAL:
                    return 7.5;
                case VideoStandard.NTSC:
                    return 7.0;
                case VideoStandard.SECAM:
                    return 8.0;
                default:
                    return baseThreshold;
            }
        }

        /// <summary>
        /// 逐行处理像素，应用阈值检测
        /// </summary>
        /// <param name="line">像素行（BGRA格式）</param>
        /// <param name="threshold">阈值</param>
        private void ShiftWindow_A_ProcessLine(byte[] line, double threshold)
        {
            for (int x = 0; x < line.Length; x += 4) // 假设BGRA格式
            {
                byte b = line[x];
                byte g = line[x + 1];
                byte r = line[x + 2];
                // byte a = line[x + 3];

                // 计算RGB均方根电平
                double rms = Math.Sqrt((r * r + g * g + b * b) / 3.0);

                // 阈值检测
                if (rms < threshold || rms > 200) // 200是示例上限阈值，实际根据需求调整
                {
                    // 消隐像素
                    line[x + 3] = 0; // 设置透明度为0
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}



--- 文件: PluginParameterViewModel.cs ---
using System.ComponentModel;
using SharedInterfaces;

namespace WpfMediaPlayer.ViewModels
{
    public class PluginParameterViewModel : INotifyPropertyChanged
    {
        private double _value;

        public string Name { get; set; }
        public string DisplayName { get; set; }
        public double Value
        {
            get => _value;
            set
            {
                if (_value != value)
                {
                    _value = value;
                    OnPropertyChanged(nameof(Value));
                    // 更新插件的参数
                    if (Plugin != null)
                    {
                        Plugin.Parameters[Name] = value;
                    }
                }
            }
        }
        public double Minimum { get; set; }
        public double Maximum { get; set; }

        public IPluginWithUI Plugin { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


--- 文件: PluginViewModel.cs ---
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using SharedInterfaces;
using System.Windows.Controls;

namespace WpfMediaPlayer.ViewModels
{
    public class PluginViewModel : INotifyPropertyChanged
    {
        private bool _isEnabled;

        public string PluginName => Plugin.PluginName;

        public bool IsEnabled
        {
            get => _isEnabled;
            set
            {
                if (_isEnabled != value)
                {
                    _isEnabled = value;
                    Plugin.IsEnabled = value;
                    OnPropertyChanged(nameof(IsEnabled));
                }
            }
        }

        public ObservableCollection<PluginParameterViewModel> Parameters { get; set; } = new ObservableCollection<PluginParameterViewModel>();

        public IPluginBase Plugin { get; set; }

        public UserControl Control
        {
            get
            {
                if (Plugin is IPluginWithUI pluginWithUI)
                {
                    return pluginWithUI.GetControl();
                }
                return null;
            }
        }

        public PluginViewModel(IPluginBase plugin)
        {
            Plugin = plugin;
            IsEnabled = plugin.IsEnabled;

            if (plugin is IPluginWithUI pluginWithUI)
            {
                foreach (var param in pluginWithUI.Parameters)
                {
                    Parameters.Add(new PluginParameterViewModel
                    {
                        Name = param.Key,
                        DisplayName = param.Key, // 可以根据需要更改显示名称
                        Value = Convert.ToDouble(param.Value),
                        Minimum = 0, // 根据插件定义设置
                        Maximum = 2, // 根据插件定义设置
                        Plugin = pluginWithUI
                    });
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


--- 文件: PluginManager.cs ---
using SharedInterfaces;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Controls;
using WpfMediaPlayer.ViewModels;

namespace WpfMediaPlayer
{
    public class PluginManager
    {
        public ObservableCollection<IPluginBase> IPlugins { get; private set; } = new ObservableCollection<IPluginBase>();
        public ObservableCollection<IPluginWithUI> IPluginsWithUI { get; private set; } = new ObservableCollection<IPluginWithUI>();
        public ObservableCollection<PluginViewModel> PluginViewModels { get; private set; } = new ObservableCollection<PluginViewModel>();

        /// <summary>
        /// 加载指定路径中的所有插件DLL
        /// </summary>
        /// <param name="pluginsPath">插件文件夹路径</param>
        public void LoadPlugins(string pluginsPath)
        {
            if (!Directory.Exists(pluginsPath))
                return;

            var dllFiles = Directory.GetFiles(pluginsPath, "*.dll");
            foreach (var dll in dllFiles)
            {
                try
                {
                    Assembly assembly = Assembly.LoadFrom(dll);
                    var types = assembly.GetTypes();

                    foreach (var type in types)
                    {
                        if (typeof(IPluginWithUI).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                        {
                            // 插件实现了IPluginWithUI
                            IPluginWithUI pluginWithUI = (IPluginWithUI)Activator.CreateInstance(type);
                            pluginWithUI.Initialize();
                            IPlugins.Add(pluginWithUI);
                            IPluginsWithUI.Add(pluginWithUI);
                            PluginViewModels.Add(new PluginViewModel(pluginWithUI));
                            Console.WriteLine($"Loaded IPluginWithUI: {pluginWithUI.PluginName}");
                        }
                        else if (typeof(IPluginBase).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                        {
                            // 插件仅实现了IPluginBase
                            IPluginBase pluginBase = (IPluginBase)Activator.CreateInstance(type);
                            pluginBase.Initialize();
                            IPlugins.Add(pluginBase);
                            PluginViewModels.Add(new PluginViewModel(pluginBase));
                            Console.WriteLine($"Loaded IPluginBase: {pluginBase.PluginName}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Failed to load plugin from {dll}: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 卸载所有插件
        /// </summary>
        public void UnloadPlugins()
        {
            // 卸载IPluginWithUI插件
            foreach (var pluginWithUI in IPluginsWithUI)
            {
                pluginWithUI.GetControl()?.Dispatcher.Invoke(() => pluginWithUI.GetControl().ClearValue(UserControl.ContentProperty));
            }
            IPluginsWithUI.Clear();

            // 卸载IPluginBase插件
            IPlugins.Clear();
            PluginViewModels.Clear();
        }

        /// <summary>
        /// 添加一个IPluginBase插件
        /// </summary>
        /// <param name="plugin">插件实例</param>
        public void AddIPlugin(IPluginBase plugin)
        {
            if (plugin != null)
            {
                plugin.Initialize();
                IPlugins.Add(plugin);
                PluginViewModels.Add(new PluginViewModel(plugin));
                Console.WriteLine($"Loaded IPluginBase: {plugin.PluginName}");
            }
        }

        /// <summary>
        /// 添加一个IPluginWithUI插件
        /// </summary>
        /// <param name="plugin">插件实例</param>
        public void AddIPluginWithUI(IPluginWithUI plugin)
        {
            if (plugin != null)
            {
                plugin.Initialize();
                IPlugins.Add(plugin);
                IPluginsWithUI.Add(plugin);
                PluginViewModels.Add(new PluginViewModel(plugin));
                Console.WriteLine($"Loaded IPluginWithUI: {plugin.PluginName}");
            }
        }
    }
}

--- 文件: IPluginbase.cs ---
// SharedInterfaces/IPluginBase.cs
using System.Windows.Media.Imaging;

namespace SharedInterfaces
{
    public interface IPluginBase
    {
        /// <summary>
        /// 插件名称
        /// </summary>
        string PluginName { get; }

        /// <summary>
        /// 插件是否启用
        /// </summary>
        bool IsEnabled { get; set; }

        /// <summary>
        /// 初始化插件
        /// </summary>
        void Initialize();

        /// <summary>
        /// 处理视频帧数据，并返回处理后的帧
        /// </summary>
        /// <param name="frame">当前视频帧</param>
        /// <returns>处理后的 BitmapSource 视频帧</returns>
        BitmapSource ProcessFrame(BitmapSource frame);
    }
}


--- 文件: IPluginWithUI.cs ---
// SharedInterfaces/IPluginWithUI.cs
using System.Collections.Generic;
using System.Windows.Controls;

namespace SharedInterfaces
{
    public interface IPluginWithUI : IPluginBase
    {
        /// <summary>
        /// 获取插件的 UserControl 界面
        /// </summary>
        /// <returns>UserControl 用于显示</returns>
        UserControl GetControl();

        /// <summary>
        /// 获取插件的参数字典
        /// </summary>
        IDictionary<string, object> Parameters { get; }
    }
}


--- 文件: PluginParameter.cs ---
// SharedInterfaces/PluginParameter.cs
using System.ComponentModel;

namespace SharedInterfaces
{
    public class PluginParameter : INotifyPropertyChanged
    {
        private string name;
        private double value;
        private double min;
        private double max;

        public string Name
        {
            get => name;
            set { name = value; OnPropertyChanged(nameof(Name)); }
        }

        public double Value
        {
            get => value;
            set { this.value = value; OnPropertyChanged(nameof(Value)); }
        }

        public double Min
        {
            get => min;
            set { min = value; OnPropertyChanged(nameof(Min)); }
        }

        public double Max
        {
            get => max;
            set { max = value; OnPropertyChanged(nameof(Max)); }
        }

        public PluginParameter(string name, double value, double min, double max)
        {
            Name = name;
            Value = value;
            Min = min;
            Max = max;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


--- 文件: IComponent.cs ---
// SharedInterfaces/IComponent.cs
using System.Windows.Controls;

namespace SharedInterfaces
{
    public interface IComponent
    {
        /// <summary>
        /// 组件的名称
        /// </summary>
        string ComponentName { get; }

        /// <summary>
        /// 初始化组件
        /// </summary>
        void Initialize();

        /// <summary>
        /// 获取组件的 UserControl 界面
        /// </summary>
        /// <returns>UserControl用于显示</returns>
        UserControl GetControl();

        /// <summary>
        /// 释放组件资源
        /// </summary>
        void Unload();
    }
}