使ç¨WPFæ¥å¯¹å为IPCæå头è¿è¡äºæ¬¡å¼åï¼æ¬æå®ç°äºç»å½IPCæå头åèªå¨é¢è§æå头è§é¢å¾å以åéç¨WriteableBitmapæ¥æå¨å¤çæå头åè°çè§é¢æµå¹¶æµç çå±ç¤ºå¨Imageæ§ä»¶éã
使ç¨C#对å为IPCæå头äºæ¬¡å¼åï¼äºï¼è¯·è®¿é®ï¼https://www.cnblogs.com/wdw984/p/13572644.html
å¼åç¯å¢ï¼
æä½ç³»ç»ï¼Win10 x64ä¸ä¸ç2004
å¼åå·¥å ·ï¼VS2019 16.7.2
ç®æ å¹³å°ï¼x86ï¼å 为è¦æä½å åï¼æ以è¦æå¼å 许éå®å ¨ä»£ç ï¼é¡¹ç®å±æ§==ãçæ==ãå¾éå 许ä¸å®å ¨ä»£ç ï¼
é¦å å»ä¸è½½IPC SDKï¼ç¹å»ä¸è½½ï¼éè¦å为ææè´¦æ·ãï¼
æ°å»ºä¸ä¸ªWPFç项ç®ï¼Frameworkçæ¬ä¸º4.7
æä¸è½½çsdkå缩å ä¸çwindows\output32ç®å½ä¸çHWPuSDK.dllålibç®å½ä¸çæææ件ï¼é½å¤å¶å°é¡¹ç®çbin/debugç®å½ä¸ï¼åçæçexeå级ï¼ï¼å为çè¿ä¸ªSDK对64ä½æ¯æä¸å¥½ï¼ä½¿ç¨64ä½éå°ä¸å°é®é¢ï¼æç»è¿æ¯å éç¨32ä½çDLLã
项ç®ä¸å¯¹å¾åçæå¨å¤çï¼ç»è¿å¯¹æ¯ï¼å¨Emgu CVåOpenCVSharp4ä¸éç¨äºOpenCVSharp4ï¼ä¸ªäººæè§OpenCVSharp4使ç¨èµ·æ¥æ´ç®æ´æ¹ä¾¿ã
项ç®ä¸å¯¹è§é¢æµçåè°æå¨å¤çå±ç¤ºï¼éç¨WriteableBitmapï¼åèåæ¯ å¤§ç¥çãWPF é«æ§è½ä½å¾æ¸²æ WriteableBitmap åå ¶é«æ§è½ç¨æ³ç¤ºä¾ãï¼ï¼æ¬æ¥æ³éç¨D3Dè¿ç§æ¾å¡å éçæ¹æ³ï¼æ å¥æ²¡ææ¾å°ç¸å ³æç« åèµæï¼å¦æåªä½å¤§ç¥æèµæï¼è¿æåç¥ä¸ä¸ã谢谢ï¼
项ç®ä¸å¼ç¨äºä»¥ä¸ç»ä»¶
å¨æ¬æ¬¡å¼åä¸ï¼æ们å å®ç°èªå¨é¢è§æå头è§é¢åæå¨å¯¹æå头è§é¢æµè¿è¡å¤çã
å 为SDKèªå¨ææ¾éè¦ä¼ å ¥ä¸ä¸ªæ§ä»¶çå¥æï¼èWPFä¸çªä½ä¸æææ§ä»¶çå¥æé½æ¯çªä½æ¬èº«ï¼æ以æ们è¿éè¦ä½¿ç¨WindowsFromHostæ¥ä½¿ç¨Winformçä¸äºæ§ä»¶æ¥å®ç°ææ¾å¥æçä¼ å ¥ã
项ç®ä¸å¼ç¨WindowsFromsIntegeration
å¨é¡¹ç®çMainWindow.xamlä¸æ·»å ä¸ä¸ªæé®ã两个RadioButtonãä¸ä¸ªWinformçPictureBoxåä¸ä¸ªWPFçImageæ§ä»¶ã大è´å¸å±å¦ä¸ï¼ 详ç»çxaml代ç ï¼<Window x:Class="HuaWeiCamera.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Loaded="MainWindow_OnLoaded"
Title="MainWindow" Height="800" Width="1200" Closed="MainWindow_OnClosed">
<Grid Margin="0,0,2,0">
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<WrapPanel VerticalAlignment="Center">
<StackPanel Margin="30,5,0,0" VerticalAlignment="Center">
<Button Content="é¢è§æå头" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Height="30" Click="ButtonView_OnClick" />
<WrapPanel Margin="0,5,0,0">
<RadioButton Content="èªå¨å¤ç" VerticalAlignment="Center" IsChecked="True" GroupName="PlayMode" x:Name="RadioButtonAuto" />
<RadioButton Content="æå¨å¤ç" VerticalAlignment="Center" GroupName="PlayMode" x:Name="RadioButtonManual" Margin="10,0,0,0" />
</WrapPanel>
</StackPanel>
<Button x:Name="ButtonSaveOne" Content="ææä¸å¼ " HorizontalAlignment="Left" VerticalAlignment="Center" Margin="30,0,0,0" Width="75" Height="30" IsEnabled="False" Click="ButtonSave_OnClick" />
<Button Content="人è¸ææ" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="30,0,0,0" Width="75" Height="30" />
</WrapPanel>
<WrapPanel Grid.Row="1">
<WindowsFormsHost HorizontalAlignment="Center" Width="1200" Height="700" VerticalAlignment="Center" x:Name="FormsHostVideo">
<wf:PictureBox x:Name="ImagePlay"></wf:PictureBox>
</WindowsFormsHost>
<Image VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="CanvaVideo" Stretch="Fill" Source="{Binding Path=VideoWriteableBitmap}" />
</WrapPanel>
</Grid>
</Window>
å¨App.csä¸å®ä¹ä¸æ¥å¿è®°å½ç±»
public partial class App : Application
{
public static NLog.Logger NewNLog;
private void App_OnStartup(object sender, StartupEventArgs e)
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
NewNLog = NLog.LogManager.GetLogger("HuaWeiCameraLoger");
}
}
æ ¹æ®å为çãSDC 8.0.1 SDKå¼åæåãï¼æ们è¦å®ç°æå头é¢è§ï¼éè¦å å®ä¹ä»¥ä¸å 个structåenumï¼
sturctï¼PU_REAL_PLAY_INFO_Sï¼è§é¢å®æ¶é¢è§ç»æä½ï¼ãPU_TIME_Sï¼æ¶é´ç»æä½ï¼
enumï¼PU_PROTOCOL_TYPEï¼ä¼ è¾å议类åï¼ãPU_STREAM_TYPEï¼ç æµç±»åï¼ãPU_VIDEO_TYPEï¼æ°æ®æµç±»åï¼ãPU_MEDIA_CRYPTO_TYPEï¼å å¯ç±»åï¼ãPU_MEDIA_CALLBACK_TYPEï¼åè°ç±»åï¼
using System;
using System.Runtime.InteropServices;
using HuaWeiCamera.Enums;
using HuaWeiCamera.Enums.Media;
using HuaWeiCamera.Enums.Video;
namespace HuaWeiCamera.Struct
{
/// <summary>
/// è§é¢å®æ¶é¢è§ç»æä½,http://www.cnblogs.com/wdw984
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct PU_REAL_PLAY_INFO_S
{
/// <summary>
/// 设å¤ééå·ï¼ä¸è¬ä¸º101ã
/// </summary>
public uint ulChannelId;
/// <summary>
/// ææ¾çªå£å¥æ,为IntPtr.Zero表示ç¨æ·èªå·±å¤çè§é¢æ°æ®æµï¼ä¸èªå¨ææ¾è§é¢æµ
/// </summary>
public IntPtr hPlayWnd;
/// <summary>
/// ç æµç±»å,主ç æµãåç
/// </summary>
public PU_STREAM_TYPE enStreamType;
/// <summary>
/// æµç±»åï¼è§é¢æµãé³é¢æµãå¤åæµãå½ åæµãå
æ°æ®
/// </summary>
public PU_VIDEO_TYPE enVideoType;
/// <summary>
/// ä¼ è¾å议类åï¼UDP,TCP
/// </summary>
public PU_PROTOCOL_TYPE enProtocolType;
/// <summary>
/// åè°ç±»åï¼0:RTP解å¯1:RTPä¸è§£å¯ 2:Frame 3:YUV
/// </summary>
public PU_MEDIA_CALLBACK_TYPE enMediaCallbackType;
/// <summary>
/// 请æ±ç«¯IPï¼ç¬¬ä¸æ¹å¹³å°å¯ä»¥ä¸å¡«ï¼SDKä¼ èªå¨è·å
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string szLocalIp;
/// <summary>
/// æ¯å¦ä¿æ´»
/// </summary>
public bool bKeepLive;
/// <summary>
/// 请æ±é¢å½ãå½åå¼å§æ¶é´ï¼æ¬å°æ¶ é´ï¼ã
/// </summary>
public PU_TIME_S stStartTime;
/// <summary>
/// 请æ±é¢å½ãå½åç»ææ¶é´ï¼æ¬å°æ¶ é´ï¼ã
/// </summary>
public PU_TIME_S stEndTime;
/// <summary>
/// å å¯ç±»åï¼åªæ¯æAESå å¯ã
/// </summary>
public PU_MEDIA_CRYPTO_TYPE enMediaCryptoType;
/// <summary>
/// å å¯å¯é¥
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 44)]
public string szMediaCrypto;
/// <summary>
/// szReserved[0-15]表示ç»æIPå°å
/// szReserved[16-19]表示ç»æ端å£
/// szReserved[22]表示æºè½åææ°æ®æå
æ ¼å¼ 0:XML,1:å
æ°æ®
/// szReserved[23]表示å
æ°æ®è¯·æ±ç±»åï¼åå¼åèæ举 PU_METADATA_REQUEST_TYPE_Eå®ä¹
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] szReserved;
}
}
namespace HuaWeiCamera.Enums
{
/// <summary>
/// è§é¢æµç±»å,http://www.cnblogs.com/wdw984
/// </summary>
public enum PU_STREAM_TYPE
{
/// <summary>
/// è§é¢ä¸»ç æµ
/// </summary>
PU_VIDEO_MAIN_STREAM=0,
/// <summary>
/// è§é¢åç æµ
/// </summary>
PU_VIDEO_SUB_STREAM1,
/// <summary>
/// è§é¢åç æµ2ï¼VWareC01 ä¸æ¯æï¼
/// </summary>
PU_VIDEO_SUB_STREAM2,
/// <summary>
/// è§é¢åç æµ3ï¼VWareC01 ä¸æ¯æï¼
/// </summary>
PU_VIDEO_SUB_STREAM3,
/// <summary>
/// è§é¢åç æµ4
/// </summary>
PU_VIDEO_SUB_STREAM4,
/// <summary>
/// è§é¢åç æµ5
/// </summary>
PU_VIDEO_SUB_STREAM5,
/// <summary>
/// é¢çå¼
/// </summary>
PU_VIDEO_STREAM_MAX
}
}
namespace HuaWeiCamera.Enums.Video
{
/// <summary>
/// ç æµç±»å,http://www.cnblogs.com/wdw984
/// </summary>
public enum PU_VIDEO_TYPE
{
/// <summary>
/// è§é¢æµ
/// </summary>
PU_VIDEO_TYPE_VIDEO = 0,
/// <summary>
/// é³é¢æµ
/// </summary>
PU_VIDEO_TYPE_AUDIO,
/// <summary>
/// å¤åæµ
/// </summary>
PU_VIDEO_TYPE_MUX,
/// <summary>
/// å½åæµ
/// </summary>
PU_VIDEO_TYPE_RECORD,
/// <summary>
/// å
æ°æ®æµ
/// </summary>
PU_VIDEO_TYPE_META,
/// <summary>
/// è§é¢+å
æ°æ®æµ
/// </summary>
PU_VIDEO_TYPE_VIDEO_META,
/// <summary>
/// é¢çå¼
/// </summary>
PU_VIDEO_TYPE_MAX
}
}
namespace HuaWeiCamera.Enums
{
/// <summary>
/// æ°æ®ä¼ è¾ç±»å,http://www.cnblogs.com/wdw984
/// </summary>
public enum PU_PROTOCOL_TYPE
{
/// <summary>
/// UDP
/// </summary>
PU_PROTOCOL_TYPE_UDP = 0,
/// <summary>
/// TCP
/// </summary>
PU_PROTOCOL_TYPE_TCP,
/// <summary>
/// ç»ææ¹å¼
/// </summary>
PU_PROTOCOL_TYPE_MULTICAST,
/// <summary>
/// é¢çå¼
/// </summary>
PU_PROTOCOL_TYPE_MAX
}
}
namespace HuaWeiCamera.Enums.Media
{
/// <summary>
/// åªä½åè°ç±»å,http://www.cnblogs.com/wdw984
/// </summary>
public enum PU_MEDIA_CALLBACK_TYPE
{
/// <summary>
/// RTPå
æ¹å¼
/// </summary>
PU_MEDIA_CALLBACK_TYPE_RTP = 0,
/// <summary>
/// RTPå
å½¢å¼ï¼ä¸è§£å¯
/// </summary>
PU_MEDIA_CALLBACK_TYPE_RTP_CRYPTO,
/// <summary>
/// 帧åè°æ¹å¼
/// </summary>
PU_MEDIA_CALLBACK_TYPE_FRAME,
/// <summary>
/// YUVæ¹å¼ï¼Linuxä¸æ¯æ
/// </summary>
PU_MEDIA_CALLBACK_TYPE_YUV,
/// <summary>
/// æRTPå
åè°ç»æ§ä»¶æ¹å¤çæ¹å¼ï¼Linuxä¸æ¯æ
/// </summary>
PU_MEDIA_CALLBACK_TYPE_FOR_STORAGE,
/// <summary>
/// æºè½å
æ°æ®æ¹å¼
/// </summary>
PU_MEDIA_CALLBACK_TYPE_META_FRAME,
/// <summary>
/// é¢çå¼
/// </summary>
PU_MEDIA_CALLBACK_TYPE_MAX
}
}
using System.Runtime.InteropServices;
namespace HuaWeiCamera.Struct
{
/// <summary>
/// æ¶é´ç»æä½ï¼http://www.cnblogs.com/wdw984
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct PU_TIME_S
{
/// <summary>
/// å¹´
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
public string szYear;
/// <summary>
/// æ
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string szMonth;
/// <summary>
/// æ¥
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string szDay;
/// <summary>
/// æ¶
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string szHour;
/// <summary>
/// å
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string szMinute;
/// <summary>
/// ç§
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string szSecond;
}
}
å®ä¹ä¸ä¸ªéæç±»ï¼ç¨æ¥å®ç°è°ç¨SDKåæå头交äºï¼HuaWeiSDKHelperï¼
using System;
using System.Runtime.InteropServices;
using HuaWeiCamera.Enums;
using HuaWeiCamera.Enums.SnapShot;
using HuaWeiCamera.Struct;
namespace HuaWeiCamera.Class
{
/// <summary>
/// å为HoloSens SDCäºæ¬¡å¼å使ç¨ï¼http://www.cnblogs.com/wdw984
/// </summary>
public static class HuaWeiSdkHelper
{
private const string SdkPath= "HWPuSDK.dll";
#region åå§ååç»å½
/// <summary>
/// åå§å设å¤
/// </summary>
/// <param name="ulLinkMode">0èªå¨ 1æå¨ 3æ··å模å¼</param>
/// <param name="szLocalIp">æ¬å°IP</param>
/// <param name="ulLocalPort">æ¬å°ç«¯å£</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_Init", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool IVS_Pu_Init(uint ulLinkMode, string szLocalIp, uint ulLocalPort);
/// <summary>
/// è¿ç¨ç»å½è®¾å¤
/// </summary>
/// <param name="szLoginIp">设å¤IP</param>
/// <param name="ulLoginPort">设å¤ç«¯å£ 6060</param>
/// <param name="szUserName">ç»å½å ApiAdmin</param>
/// <param name="szPasswd">ç»å½å¯ç HuaWei123</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_Login", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
public static extern uint IVS_PU_Login(string szLoginIp, uint ulLoginPort, string szUserName, string szPasswd);
/// <summary>
/// åå§ååç»å½è®¾å¤
/// </summary>
/// <param name="sdcIp">SDC设å¤IP</param>
/// <param name="sdcPort">SDC设å¤ç«¯å£</param>
/// <param name="sdcUser">SDCç»å½ç¨æ·å</param>
/// <param name="sdcPwd">SDCç»å½å¯ç </param>
/// <param name="errMsg">失败æ¶çé误信æ¯</param>
/// <param name="ulIdentifyId">ç»å½æååè¿åç»å½å¥æ</param>
public static void InitAndLogin(string sdcIp,uint sdcPort,string sdcUser,string sdcPwd,out uint ulIdentifyId,out string errMsg)
{
ulIdentifyId = 0;
errMsg = "";
//è¦å¼å¯TLSçæ
åµæ¶ï¼åå§åè°ç¨IVS_PU_InitExæ¥å£ï¼ç»å½è°ç¨IVS_PU_Login æ¥å£æ¶ç«¯å£å·è®¾ç½®ä¸º6061
if (!IVS_Pu_Init(1, "192.168.2.144", 6060))
{
errMsg=($"设å¤åå§å失败ï¼{GetLastErrorInfo()}");
return;
}
ulIdentifyId = IVS_PU_Login(sdcIp, sdcPort, sdcUser, sdcPwd);
if (ulIdentifyId == 0)
{
errMsg=$"设å¤ç»å½å¤±è´¥ï¼{GetLastErrorInfo()}";
}
}
#endregion
#region é¢è§ç¸å
³
/// <summary>
/// å®æ¶é¢è§
/// </summary>
/// <param name="ulIdentifyId">ç»å½æååè¿åçç¨æ·ç¼å·</param>
/// <param name="pstRealPlayInfo">ææ¾ç»æä½</param>
/// <param name="fRealDataCallBack">åè°å®ç°ææ¾</param>
/// <param name="pUsrData">ä¼ å
¥ç æµæ°æ® åè°å½æ°ä½ä¸ºåæ°</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_RealPlay")]
public static extern uint IVS_PU_RealPlay(uint ulIdentifyID, PU_REAL_PLAY_INFO_S[] pstRealPlayInfo, PfRealDataCallBack fRealDataCallBack, ref IntPtr pUsrData);
public delegate void PfRealDataCallBack(IntPtr szBuffer, int lSize, IntPtr pUsrData);
/// <summary>
/// åæ¢å®æ¶é¢è§
/// </summary>
/// <param name="ulIdentifyId">ç»å½æååè¿åçç¨æ·ç¼å·</param>
/// <param name="ulRealHandle">å®æ¶ææ¾å¥æ</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_StopRealPlay", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
public static extern uint IVS_PU_StopRealPlay(uint ulIdentifyId, uint ulRealHandle);
#endregion
#region é误信æ¯ç¸å
³
/// <summary>
/// è·åæåä¸æ¬¡é误代ç
/// </summary>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_GetLastError", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
private static extern int IVS_PU_GetLastError();
/// <summary>
/// æ ¹æ®é误代ç è¿åé误信æ¯
/// </summary>
/// <param name="ulErrorNo">é误ç¼å·</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_GetErrorMsg", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr IVS_PU_GetErrorMsg(int ulErrorNo);
/// <summary>
/// è¿åæåä¸æ¬¡é误ç åé误信æ¯
/// </summary>
/// <returns></returns>
public static string GetLastErrorInfo()
{
var lastErrorCode = IVS_PU_GetLastError();
var lastErrorMsg = Marshal.PtrToStringAnsi(IVS_PU_GetErrorMsg(lastErrorCode));
return $"é误ç ï¼{IVS_PU_GetLastError()}ï¼é误信æ¯ï¼{lastErrorMsg}";
}
#endregion
#region éåºç»å½
/// <summary>
/// éåºç»å½
/// </summary>
/// <param name="ulIdentifyId">ç»å½æååè¿åçå¥æç¼å·</param>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_Logout", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool IVS_PU_Logout(uint ulIdentifyId);
/// <summary>
/// å注å设å¤ï¼éåºæ¶è¿è¡è®¾å¤éæ¾
/// </summary>
/// <returns></returns>
[DllImport(SdkPath, EntryPoint = "IVS_PU_Cleanup", CharSet = CharSet.Ansi, SetLastError = true, PreserveSig = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool IVS_PU_Cleanup();
#endregion
}
}
å®ä¹ä¸ä¸ªç»§æ¿äºINotifyPropertyChangedçModelï¼ç¨æ¥å®ç°å·æ°Imageæ§ä»¶
public class VideoYuvModelView : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private WriteableBitmap bitmapImage { get; set; }
public WriteableBitmap VideoWriteableBitmap
{
get => bitmapImage;
set
{
bitmapImage = value;
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("VideoBitmapImage"));
}
}
}
å¨MainWindow.csä¸æ们éè¦å®ä¹ä¸äºåéï¼
private uint _ulIdentifyId;//ç»å½æå头åè¿åçç¼å·
private uint _ulRealHandleId;//è°ç¨é¢è§SDKè¿åçç»æå¼
private static bool _isSave;//æ¯å¦ä¿åå½å帧为å¾ç
private static bool _isExit;//æ¯å¦éåº
private static HuaWeiSdkHelper.PfRealDataCallBack _fedRealPlayCallbackWithYUV;//æå¨å¤çæå头åè°æ¶çå§æäºä»¶
private const uint ByteLength = 1920 * 1080 * 4;//ä½å¾ç大å°
private static readonly VideoYuvModelView VideoYuvModelView = new VideoYuvModelView();//Imageçæ°æ®æºï¼ç¨æ¥æå¨å¤çè§é¢æ¶åå±ç¤ºå¾å
private IntPtr _videoPlayHandle = IntPtr.Zero;//èªå¨é¢è§æ¶çæ§ä»¶å¥æ
[DllImport("kernel32.dll")]
private static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);//ç¨æ¥å¤å¶å
åä¸çæ°æ®
å¨çªä½åå§ååå è½½äºä»¶ä¸ï¼æ们æ¥åå§åä¸äºæ°æ®çç»å®
public MainWindow()
{
InitializeComponent();
VideoYuvModelView.VideoWriteableBitmap = new WriteableBitmap(1920, 1800, 96.0, 96.0, PixelFormats.Bgr32, null);//å 为æå头è¿åçå¾ç大å°æ¶1920*1080ï¼æ以è¿éå®ä¹ç大å°è¦åè¿åçå¾ç大å°ä¸è´
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
CanvaVideo.DataContext = VideoYuvModelView;//æå¨å¤çæ¶ï¼Imageæ§ä»¶æ°æ®æº
_videoPlayHandle = ImagePlay.Handle;//èªå¨å¤çæ¶ï¼ä½¿ç¨Winformçæ§ä»¶å¥æ
}
é¢è§æå头æé®äºä»¶ï¼ä¸é´æ ¹æ®éä¸çèªå¨å¤çåæå¨å¤çæ¥åå«ååºä¸åçç¸åº
#region è§é¢é¢è§ï¼èªå¨åæå¨å¤çè§é¢æµï¼
private void ButtonView_OnClick(object sender, RoutedEventArgs e)
{
if (0 == _ulIdentifyId)
{
//è¿ééè¿ç½ç»ç»å½å°æå头ï¼å
·ä½ç«¯å£ãç¨æ·åãå¯ç 请åèå¼åæå
HuaWeiSdkHelper.InitAndLogin("192.168.2.250", 6060, "ApiAdmin", "HuaWei123", out _ulIdentifyId, out string errMsg);
if (0 == _ulIdentifyId)
{
MessageBox.Show(errMsg);
return;
}
}
var prpInfos = new PU_REAL_PLAY_INFO_S[1];
var clientInfo = new PU_REAL_PLAY_INFO_S
{
ulChannelId = 101,
hPlayWnd = _videoPlayHandle,
enProtocolType = PU_PROTOCOL_TYPE.PU_PROTOCOL_TYPE_TCP,
enStreamType = PU_STREAM_TYPE.PU_VIDEO_MAIN_STREAM,
enVideoType = PU_VIDEO_TYPE.PU_VIDEO_TYPE_VIDEO,
enMediaCryptoType = PU_MEDIA_CRYPTO_TYPE.PU_MEDIA_CRYPTO_NONE,
enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE.PU_MEDIA_CALLBACK_TYPE_RTP,
szReserved = new byte[32],
bKeepLive = true
};
IntPtr pUsrData = (IntPtr)_ulIdentifyId;
if (RadioButtonManual.IsChecked == true)
{
//æå¨å¤çè§é¢é¢è§
FormsHostVideo.Visibility = Visibility.Collapsed;
CanvaVideo.Visibility = Visibility.Visible;
clientInfo.hPlayWnd = IntPtr.Zero;
clientInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE.PU_MEDIA_CALLBACK_TYPE_YUV;
prpInfos[0] = clientInfo;
_fedRealPlayCallbackWithYUV = FedRealPlayCallbackWithYUV; //æå¨å¤çåè°
_ulRealHandleId = HuaWeiSdkHelper.IVS_PU_RealPlay(_ulIdentifyId, prpInfos, _fedRealPlayCallbackWithYUV, ref pUsrData);
if (0 == _ulRealHandleId)
{
MessageBox.Show(HuaWeiSdkHelper.GetLastErrorInfo());
}
ButtonSaveOne.IsEnabled = true;//ç¹å» ææä¸å¼ æé®ï¼ä¼æ_isSaveåé设置为trueï¼ä»èå¨åè°äºä»¶ä¸å¯ä»¥ä¿åå½å帧为å¾ç
}
else
{
ButtonSaveOne.IsEnabled = false;
CanvaVideo.Visibility = Visibility.Collapsed;
FormsHostVideo.Visibility = Visibility.Visible;
prpInfos[0] = clientInfo;
//ä¼ å
¥å¥æï¼èªå¨é¢è§
_ulRealHandleId = HuaWeiSdkHelper.IVS_PU_RealPlay(_ulIdentifyId, prpInfos, null, ref pUsrData);
if (0 == _ulRealHandleId)
{
MessageBox.Show(HuaWeiSdkHelper.GetLastErrorInfo());
}
}
}
#region æå¨è§£æYUVæ°æ®å¹¶å±ç¤ºå¨çé¢ä¸
private static void FedRealPlayCallbackWithYUV(IntPtr szBuffer, int lSize, IntPtr pUsrData)
{
if (_isExit) return;
try
{
Span<byte> nativeSpan;
unsafe
{
nativeSpan = new Span<byte>(szBuffer.ToPointer(), lSize);
}
if (nativeSpan.Length > 0)
{
#region å¤çè§é¢æµYUVå¾å
Mat yuvImg = new Mat(1080 * 3 / 2, 1920, MatType.CV_8UC1);
Mat rgbImg = new Mat(1080, 1920, MatType.CV_8UC1);
Marshal.Copy(nativeSpan.ToArray(), 0, yuvImg.Data, nativeSpan.Length);
Cv2.CvtColor(yuvImg, rgbImg, ColorConversionCodes.YUV2RGBA_I420);
Application.Current.Dispatcher?.InvokeAsync(() =>
{
VideoYuvModelView.VideoWriteableBitmap.Lock();
unsafe
{
CopyMemory(VideoYuvModelView.VideoWriteableBitmap.BackBuffer, new IntPtr(rgbImg.DataPointer), ByteLength);
}
VideoYuvModelView.VideoWriteableBitmap.AddDirtyRect(new Int32Rect(0, 0, 1920, 1080));
VideoYuvModelView.VideoWriteableBitmap.Unlock();
});
if (_isSave)
{
Cv2.ImWrite(Path.Combine($"{AppDomain.CurrentDomain.BaseDirectory}", "jpg",$"{Guid.NewGuid()}.jpg"), rgbImg);
_isSave = false;
}
#endregion
}
}
catch (Exception e)
{
App.NewNLog.Error($"解æè§é¢æµåºéï¼{e}");
}
}
#endregion
#endregion
å¨ç¨åºå ³éçæ¶åè¿è¡èµæºéæ¾ã
private void MainWindow_OnClosed(object sender, EventArgs e)
{
_isExit = true;if (_ulRealHandleId > 0)
{
HuaWeiSdkHelper.IVS_PU_StopRealPlay(_ulIdentifyId, _ulRealHandleId);//åæ¢é¢è§
}
if (_ulIdentifyId > 0)
{
HuaWeiSdkHelper.IVS_PU_Logout(_ulIdentifyId);//éåºç»å½
}
HuaWeiSdkHelper.IVS_PU_Cleanup();//SDKèµæºéæ¾
}
å ·ä½ææå¦ä¸ï¼
1ãèªå¨é¢è§
2ãæå¨å¤ç
ä½æ¯è¿éçYUVåè°å¡«å å°WriteableBitmapéå°ä¸ªé®é¢ï¼å°±æ¯æ æ³å¡«æ»¡WriteableBitmapï¼æWriteableBitmapä¸çæ°æ®ä¿åä¸æ¥ä¹æ¯åé¢è§çææä¸æ ·ï¼ä¼°è®¡æ¯å¡«å çç®æ³ä¸å¯¹ï¼ï¼åªè½å¡«å ä¸é¨åï¼è¿éæ¶åå°æ¬äººçç¥è¯ç²åºï¼ææ¶æ²¡æ³è§£å³æã
3ãä¸å¸§å¾åä¿å为æ¬å°å¾ç
Â
è³æ¤æ们使ç¨C#åæ¥å®ç°äºå为IPCæå头çé¢è§åæ°æ®æµå¤çï¼ä¹å¯ä»¥æå¤çç±»åæ¢æè§é¢æµï¼ç¶ååæ¬å°è§é¢æ件ï¼å 为é»è®¤æ¶h265ç¼ç æ ¼å¼ï¼ææ¾æ¶ä½¿ç¨PotPlayerææ¾å¨æ¥ææ¾ï¼ï¼ç®æ¯å ¥é¨äºã
ä¸ä¸ç« æ们å°å®ç°è°ç¨SDKæ¥å®ç°äººè¸èªå¨ææææã