2025-09-15 14:45:54 +08:00

144 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using Yztob.AiSports.Sensors.Things;
namespace Wpf_AiSportsMicrospace
{
public class RTSPPreview : UserControl, IDisposable
{
private Image _imageControl;
private WriteableBitmap _bitmap;
private bool _isPlaying = false;
public RTSPPreview()
{
_imageControl = new Image();
this.Content = _imageControl;
this.Loaded += RTSPPreview_Loaded;
}
private void RTSPPreview_Loaded(object sender, RoutedEventArgs e)
{
if (Adaptive)
{
_imageControl.Stretch = Stretch.Uniform;
}
else
{
_imageControl.Stretch = Stretch.Fill;
}
}
#region
[Browsable(true)]
[DefaultValue(true)]
[Description("是否自应用大小,保持同比缩放。")]
public bool Adaptive { get; set; } = true;
public string Host { get; set; }
public uint Port { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Action<VideoFrame> OnExtracted { get; set; }
public Action<VideoFrameWithBuffer> OnFrameProcessing { get; set; }
public bool IsPlaying => _isPlaying;
public float OffsetX { get; private set; }
public float OffsetY { get; private set; }
public float ScaleRatio { get; private set; }
#endregion
#region //
public void Play()
{
_isPlaying = true;
// TODO: RTSP 播放初始化
// 可使用 FFmpeg.AutoGen 或 LibVLCSharp
}
public void Stop()
{
_isPlaying = false;
// TODO: 停止播放
}
public bool SaveFrameToJpeg(string path)
{
if (_bitmap == null) return false;
try
{
BitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(_bitmap));
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
encoder.Save(fs);
}
return true;
}
catch
{
return false;
}
}
#endregion
#region
public void UpdateFrame(byte[] pixelData, int width, int height)
{
// 假设 pixelData 为 BGRA32
if (_bitmap == null || _bitmap.PixelWidth != width || _bitmap.PixelHeight != height)
{
_bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
_imageControl.Source = _bitmap;
}
_bitmap.Lock();
_bitmap.WritePixels(new Int32Rect(0, 0, width, height), pixelData, width * 4, 0);
_bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
_bitmap.Unlock();
OnFrameProcessing?.Invoke(new VideoFrameWithBuffer
{
Width = width,
Height = height,
Buffer = pixelData
});
}
#endregion
public void Dispose()
{
Stop();
_bitmap = null;
}
}
// 数据类示例
public class VideoFrameWithBuffer
{
public int Width;
public int Height;
public byte[] Buffer;
}
}