144 lines
3.7 KiB
C#
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;
|
|
}
|
|
}
|