观看DEMO完成
This commit is contained in:
parent
29a889e9e0
commit
5cd68752b1
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,9 @@
|
|||
<Application x:Class="ClientDemo.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ClientDemo"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace ClientDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{5C83270B-1086-494D-BCAF-0E773CC598AB}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>ClientDemo</RootNamespace>
|
||||
<AssemblyName>ClientDemo</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'x64'">
|
||||
<HintPath>SDK\CSharp\Win64\lib\ManageLiteAV.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'AnyCPU'">
|
||||
<HintPath>SDK\CSharp\Win64\lib\ManageLiteAV.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ManageLiteAV" Condition="'$(Platform)' == 'x86'">
|
||||
<HintPath>SDK\CSharp\Win32\lib\ManageLiteAV.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="zlib.net, Version=1.0.3.0, Culture=neutral, PublicKeyToken=47d7877cb3620160">
|
||||
<HintPath>..\packages\zlib.net.1.0.4.0\lib\zlib.net.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="TLSSigAPIv2.cs" />
|
||||
<Compile Include="TRTCCloudCallback.cs" />
|
||||
<Compile Include="TXLiteAVVideoView.cs" />
|
||||
<Compile Include="Util.cs" />
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="TRTC_SDK\Win32\lib\liteav.lib" />
|
||||
<None Include="TRTC_SDK\Win64\lib\liteav.lib" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-file-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-file-l2-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-localization-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-processthreads-l1-1-1.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-synch-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-timezone-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-core-xstate-l2-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-convert-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-environment-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-filesystem-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-heap-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-locale-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-math-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-runtime-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-stdio-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-string-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-time-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\api-ms-win-crt-utility-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\liteav.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\LiteAvAudioHook.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\LiteAvAudioHookService.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\ManageLiteAV.dll" />
|
||||
<Resource Include="TRTC_SDK\Win32\lib\ManageLiteAV.xml" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\msvcp140.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\TRAE.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\ucrtbase.dll" />
|
||||
<Content Include="TRTC_SDK\Win32\lib\vcruntime140.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-file-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-file-l2-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-localization-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-processthreads-l1-1-1.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-synch-l1-2-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-timezone-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-core-xstate-l2-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-convert-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-environment-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-filesystem-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-heap-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-locale-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-math-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-runtime-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-stdio-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-string-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-time-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\api-ms-win-crt-utility-l1-1-0.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\liteav.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\LiteAvAudioHook.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\LiteAvAudioHookService.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\ManageLiteAV.dll" />
|
||||
<Resource Include="TRTC_SDK\Win64\lib\ManageLiteAV.xml" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\msvcp140.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\TRAE.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\ucrtbase.dll" />
|
||||
<Content Include="TRTC_SDK\Win64\lib\vcruntime140.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>set Platform=Win64
|
||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||
if $(PlatformName)==x86 (
|
||||
set Platform=Win32
|
||||
)
|
||||
copy /Y "$(ProjectDir)TRTC_SDK\!Platform!\lib\*.dll" "$(ProjectDir)$(OutDir)"
|
||||
ENDLOCAL</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<Window x:Class="ClientDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:ClientDemo"
|
||||
mc:Ignorable="d"
|
||||
Title="预览" Height="600" Width="1000">
|
||||
<Grid x:Name="Wrap">
|
||||
<Canvas>
|
||||
<Grid x:Name="sub" Width="{Binding ElementName=Wrap,Path=ActualWidth}" Height="{Binding ElementName=Wrap,Path=ActualHeight}" Canvas.Top="0" Canvas.Left="0"></Grid>
|
||||
<Grid x:Name="main" Width="150" Height="150" Canvas.Right="20" Canvas.Bottom="20"></Grid>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
</Window>
|
|
@ -0,0 +1,130 @@
|
|||
using JianGongYun.TRTC.Components;
|
||||
using JianGongYun.TRTC.Utils;
|
||||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ClientDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
const uint SDKAppID = 1400463444;
|
||||
const string SDKAppKEY = "6ee2586282eb8ab5bff3f917b44500c4ffd9bbd3d820258b1fa8cdd470cfd1ee";
|
||||
/// <summary>
|
||||
/// TRTC实例
|
||||
/// </summary>
|
||||
public static ITRTCCloud lTRTCCloud;
|
||||
/// <summary>
|
||||
/// 设备管理器
|
||||
/// </summary>
|
||||
public static ITXDeviceManager lTXDeviceManager;
|
||||
public static TRTCCloudCallback TRTCCloudCallback = new TRTCCloudCallback();
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
lTRTCCloud = ITRTCCloud.getTRTCShareInstance();//创建TRTC实例
|
||||
Console.WriteLine(lTRTCCloud.getSDKVersion());
|
||||
lTRTCCloud.addCallback(TRTCCloudCallback);//注册回调
|
||||
|
||||
var roomPars = new TRTCParams
|
||||
{
|
||||
sdkAppId = SDKAppID,
|
||||
userId = "666",
|
||||
userSig = GenTestUserSig("666"),
|
||||
roomId = 0,//使用strRoomId
|
||||
strRoomId = "53245345",
|
||||
role = TRTCRoleType.TRTCRoleAudience
|
||||
};
|
||||
lTRTCCloud.enterRoom(ref roomPars, TRTCAppScene.TRTCAppSceneLIVE);//创建房间
|
||||
|
||||
StartVideo();
|
||||
}
|
||||
|
||||
public void StartVideo()
|
||||
{
|
||||
lTRTCCloud.startRemoteView("53245345", TRTCVideoStreamType.TRTCVideoStreamTypeBig, IntPtr.Zero);
|
||||
AddCustomVideoView(main, "53245345", TRTCVideoStreamType.TRTCVideoStreamTypeBig, false);
|
||||
lTRTCCloud.startRemoteView("53245345", TRTCVideoStreamType.TRTCVideoStreamTypeSub, IntPtr.Zero);
|
||||
AddCustomVideoView(sub, "53245345", TRTCVideoStreamType.TRTCVideoStreamTypeSub, false);
|
||||
}
|
||||
public void StopVideo()
|
||||
{
|
||||
lTRTCCloud.stopRemoteView("53245345", TRTCVideoStreamType.TRTCVideoStreamTypeBig);
|
||||
RemoveCustomVideoView(main, "666", TRTCVideoStreamType.TRTCVideoStreamTypeBig, false);
|
||||
lTRTCCloud.stopRemoteView("53245345", TRTCVideoStreamType.TRTCVideoStreamTypeSub);
|
||||
RemoveCustomVideoView(sub, "666", TRTCVideoStreamType.TRTCVideoStreamTypeSub, false);
|
||||
}
|
||||
private static void RemoveCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
|
||||
{
|
||||
TXLiteAVVideoView videoView = null;
|
||||
string key = string.Format("{0}_{1}", userId, streamType);
|
||||
if (VideoViews.TryGetValue(key, out videoView))
|
||||
{
|
||||
videoView.RemoveEngine(lTRTCCloud);
|
||||
parent.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
parent.Children.Remove(videoView);
|
||||
}));
|
||||
VideoViews.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 视频画面
|
||||
/// </summary>
|
||||
public static Dictionary<string, TXLiteAVVideoView> VideoViews = new Dictionary<string, TXLiteAVVideoView>();
|
||||
/// <summary>
|
||||
/// 添加自定义渲染 View 并绑定渲染回调
|
||||
/// </summary>
|
||||
private static TXLiteAVVideoView AddCustomVideoView(Panel parent, string userId, TRTCVideoStreamType streamType, bool local = false)
|
||||
{
|
||||
TXLiteAVVideoView videoView = new TXLiteAVVideoView();
|
||||
videoView.RegEngine(userId, streamType, lTRTCCloud, local);
|
||||
videoView.SetRenderMode(streamType == TRTCVideoStreamType.TRTCVideoStreamTypeBig ? TRTCVideoFillMode.TRTCVideoFillMode_Fill : TRTCVideoFillMode.TRTCVideoFillMode_Fit);
|
||||
videoView.SetBinding(TXLiteAVVideoView.WidthProperty, new Binding("ActualWidth") { Source = parent });
|
||||
videoView.SetBinding(TXLiteAVVideoView.HeightProperty, new Binding("ActualHeight") { Source = parent });
|
||||
parent.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
parent.Children.Add(videoView);
|
||||
}));
|
||||
string key = string.Format("{0}_{1}", userId, streamType);
|
||||
VideoViews.Add(key, videoView);
|
||||
return videoView;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
StopVideo();
|
||||
lTRTCCloud.exitRoom();
|
||||
lTRTCCloud.removeCallback(TRTCCloudCallback);//注册回调
|
||||
ITRTCCloud.destroyTRTCShareInstance();//销毁TRTC实例
|
||||
lTRTCCloud.Dispose();
|
||||
lTRTCCloud = null;
|
||||
base.OnClosing(e);
|
||||
}
|
||||
public static string GenTestUserSig(string userId)
|
||||
{
|
||||
if (SDKAppID == 0 || string.IsNullOrEmpty(SDKAppKEY)) return null;
|
||||
TLSSigAPIv2 api = new TLSSigAPIv2((int)SDKAppID, SDKAppKEY);
|
||||
// 统一转换为UTF8,SDK内部是用UTF8编码。
|
||||
return api.GenSig(Util.UTF16To8(userId));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("ClientDemo")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ClientDemo")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//若要开始生成可本地化的应用程序,请设置
|
||||
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||
//例如,如果您在源文件中使用的是美国英语,
|
||||
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,63 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ClientDemo.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClientDemo.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -0,0 +1,26 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ClientDemo.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -0,0 +1,123 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using zlib;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public class TLSSigAPIv2
|
||||
{
|
||||
private readonly int sdkappid;
|
||||
private readonly string key;
|
||||
|
||||
public TLSSigAPIv2(int sdkappid, string key)
|
||||
{
|
||||
this.sdkappid = sdkappid;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
private static byte[] CompressBytes(byte[] sourceByte)
|
||||
{
|
||||
MemoryStream inputStream = new MemoryStream(sourceByte);
|
||||
Stream outStream = CompressStream(inputStream);
|
||||
byte[] outPutByteArray = new byte[outStream.Length];
|
||||
outStream.Position = 0;
|
||||
outStream.Read(outPutByteArray, 0, outPutByteArray.Length);
|
||||
return outPutByteArray;
|
||||
}
|
||||
|
||||
private static Stream CompressStream(Stream sourceStream)
|
||||
{
|
||||
MemoryStream streamOut = new MemoryStream();
|
||||
ZOutputStream streamZOut = new ZOutputStream(streamOut, zlibConst.Z_DEFAULT_COMPRESSION);
|
||||
CopyStream(sourceStream, streamZOut);
|
||||
streamZOut.finish();
|
||||
return streamOut;
|
||||
}
|
||||
|
||||
public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
|
||||
{
|
||||
byte[] buffer = new byte[2000];
|
||||
int len;
|
||||
while ((len = input.Read(buffer, 0, 2000)) > 0)
|
||||
{
|
||||
output.Write(buffer, 0, len);
|
||||
}
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
private string HMACSHA256(string identifier, long currTime, int expire, string base64UserBuf, bool userBufEnabled)
|
||||
{
|
||||
string rawContentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
||||
+ "TLS.sdkappid:" + sdkappid + "\n"
|
||||
+ "TLS.time:" + currTime + "\n"
|
||||
+ "TLS.expire:" + expire + "\n";
|
||||
if (true == userBufEnabled)
|
||||
{
|
||||
rawContentToBeSigned += "TLS.userbuf:" + base64UserBuf + "\n";
|
||||
}
|
||||
using (HMACSHA256 hmac = new HMACSHA256())
|
||||
{
|
||||
UTF8Encoding encoding = new UTF8Encoding();
|
||||
Byte[] textBytes = encoding.GetBytes(rawContentToBeSigned);
|
||||
Byte[] keyBytes = encoding.GetBytes(key);
|
||||
Byte[] hashBytes;
|
||||
using (HMACSHA256 hash = new HMACSHA256(keyBytes))
|
||||
hashBytes = hash.ComputeHash(textBytes);
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private string GenSig(string identifier, int expire, byte[] userbuf, bool userBufEnabled)
|
||||
{
|
||||
DateTime epoch = new DateTime(1970, 1, 1); // unix 时间戳
|
||||
Int64 currTime = (Int64)(DateTime.UtcNow - epoch).TotalMilliseconds / 1000;
|
||||
|
||||
string base64UserBuf;
|
||||
string jsonData;
|
||||
if (true == userBufEnabled)
|
||||
{
|
||||
base64UserBuf = Convert.ToBase64String(userbuf);
|
||||
string base64sig = HMACSHA256(identifier, currTime, expire, base64UserBuf, userBufEnabled);
|
||||
var jsonObj = new JObject();
|
||||
jsonObj["TLS.ver"] = "2.0";
|
||||
jsonObj["TLS.identifier"] = identifier;
|
||||
jsonObj["TLS.sdkappid"] = sdkappid;
|
||||
jsonObj["TLS.expire"] = expire;
|
||||
jsonObj["TLS.time"] = currTime;
|
||||
jsonObj["TLS.sig"] = base64sig;
|
||||
jsonObj["TLS.userbuf"] = base64UserBuf;
|
||||
jsonData = JsonConvert.SerializeObject(jsonObj);
|
||||
}
|
||||
else
|
||||
{
|
||||
string base64sig = HMACSHA256(identifier, currTime, expire, "", false);
|
||||
var jsonObj = new JObject();
|
||||
jsonObj["TLS.ver"] = "2.0";
|
||||
jsonObj["TLS.identifier"] = identifier;
|
||||
jsonObj["TLS.sdkappid"] = sdkappid;
|
||||
jsonObj["TLS.expire"] = expire;
|
||||
jsonObj["TLS.time"] = currTime;
|
||||
jsonObj["TLS.sig"] = base64sig;
|
||||
jsonData = JsonConvert.SerializeObject(jsonObj);
|
||||
}
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(jsonData);
|
||||
return Convert.ToBase64String(CompressBytes(buffer))
|
||||
.Replace('+', '*').Replace('/', '-').Replace('=', '_');
|
||||
}
|
||||
|
||||
public string GenSig(string identifier, int expire = 180 * 86400)
|
||||
{
|
||||
return GenSig(identifier, expire, null, false);
|
||||
}
|
||||
|
||||
public string GenSigWithUserBuf(string identifier, int expire, byte[] userbuf)
|
||||
{
|
||||
return GenSig(identifier, expire, userbuf, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public class TRTCCloudCallback : ITRTCCloudCallback
|
||||
{
|
||||
public void onAudioDeviceCaptureVolumeChanged(uint volume, bool muted)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onAudioDevicePlayoutVolumeChanged(uint volume, bool muted)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onAudioEffectFinished(int effectId, int code)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onCameraDidReady()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onConnectionLost()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onConnectionRecovery()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onConnectOtherRoom(string userId, TXLiteAVError errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onDeviceChange(string deviceId, TRTCDeviceType type, TRTCDeviceState state)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onDisconnectOtherRoom(TXLiteAVError errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onEnterRoom(int result)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onError(TXLiteAVError errCode, string errMsg, IntPtr arg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onExitRoom(int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onFirstAudioFrame(string userId)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onFirstVideoFrame(string userId, TRTCVideoStreamType streamType, int width, int height)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onMicDidReady()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onMissCustomCmdMsg(string userId, int cmdId, int errCode, int missed)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onNetworkQuality(TRTCQualityInfo localQuality, TRTCQualityInfo[] remoteQuality, uint remoteQualityCount)
|
||||
{
|
||||
//StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onPlayBGMBegin(TXLiteAVError errCode)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onPlayBGMComplete(TXLiteAVError errCode)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onPlayBGMProgress(uint progressMS, uint durationMS)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onRecvCustomCmdMsg(string userId, int cmdID, uint seq, byte[] msg, uint msgSize)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onRecvSEIMsg(string userId, byte[] message, uint msgSize)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onRemoteUserEnterRoom(string userId)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onRemoteUserLeaveRoom(string userId, int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onScreenCaptureCovered()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onScreenCapturePaused(int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onScreenCaptureResumed(int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onScreenCaptureStarted()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onScreenCaptureStoped(int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSendFirstLocalAudioFrame()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSendFirstLocalVideoFrame(TRTCVideoStreamType streamType)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSetMixTranscodingConfig(int errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSpeedTest(TRTCSpeedTestResult currentResult, uint finishedCount, uint totalCount)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onStartPublishCDNStream(int errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onStartPublishing(int errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onStatistics(TRTCStatistics statis)
|
||||
{
|
||||
//StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onStopPublishCDNStream(int errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onStopPublishing(int errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSwitchRole(TXLiteAVError errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onSwitchRoom(TXLiteAVError errCode, string errMsg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onTestMicVolume(uint volume)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onTestSpeakerVolume(uint volume)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onTryToReconnect()
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserAudioAvailable(string userId, bool available)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserEnter(string userId)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserExit(string userId, int reason)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserSubStreamAvailable(string userId, bool available)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserVideoAvailable(string userId, bool available)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onUserVoiceVolume(TRTCVolumeInfo[] userVolumes, uint userVolumesCount, uint totalVolume)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
|
||||
public void onWarning(TXLiteAVWarning warningCode, string warningMsg, IntPtr arg)
|
||||
{
|
||||
StackTrace trace = new StackTrace(true);StackFrame frame = trace.GetFrame(1);var method = frame.GetMethod();Console.WriteLine(method.Name);
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,492 @@
|
|||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace JianGongYun.TRTC.Components
|
||||
{
|
||||
public class TXLiteAVVideoView : Canvas, IDisposable
|
||||
{
|
||||
private bool mOccupy = false; // view 是否已被占用
|
||||
private bool mLocalView = false; // 是否为本地画面
|
||||
private bool mPause = false;
|
||||
private bool mFirstFrame = false;
|
||||
|
||||
private string mUserId;
|
||||
private TRTCVideoStreamType mStreamType;
|
||||
private TRTCVideoFillMode mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit; // 0:填充,1:适应
|
||||
|
||||
private volatile FrameBufferInfo mArgbFrame = new FrameBufferInfo(); // 帧缓存
|
||||
|
||||
// 位图缓存,防止GC频繁
|
||||
private WriteableBitmap mWriteableBitmap;
|
||||
private Int32Rect mInt32Rect;
|
||||
private Pen mPen;
|
||||
|
||||
public TXLiteAVVideoView()
|
||||
{
|
||||
mPen = new Pen { Brush = Brushes.DarkGray, Thickness = 1 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 View 绑定参数
|
||||
/// </summary>
|
||||
/// <param name="userId">需要渲染画面的 userId,如果是本地画面,则传空字符串。</param>
|
||||
/// <param name="type">渲染类型</param>
|
||||
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
|
||||
/// <param name="local">渲染本地画面,SDK 返回的 userId 为""</param>
|
||||
/// <returns>true:绑定成功,false:绑定失败</returns>
|
||||
public bool RegEngine(string userId, TRTCVideoStreamType type, ITRTCCloud engine, bool local = false)
|
||||
{
|
||||
if (mOccupy) return false;
|
||||
mLocalView = local;
|
||||
mUserId = userId;
|
||||
mStreamType = type;
|
||||
int count = TXLiteAVVideoViewManager.GetInstance().Count;
|
||||
if (engine != null)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
|
||||
}
|
||||
if (!mLocalView)
|
||||
{
|
||||
engine.setRemoteVideoRenderCallback(userId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Buffer, TXLiteAVVideoViewManager.GetInstance());
|
||||
}
|
||||
}
|
||||
if (mLocalView)
|
||||
TXLiteAVVideoViewManager.GetInstance().AddView("", type, this);
|
||||
else
|
||||
TXLiteAVVideoViewManager.GetInstance().AddView(userId, type, this);
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mOccupy = true;
|
||||
this.InvalidateVisual();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除 View 绑定参数
|
||||
/// </summary>
|
||||
/// <param name="engine">TRTCCloud 实例,用户注册视频数据回调。</param>
|
||||
public void RemoveEngine(ITRTCCloud engine)
|
||||
{
|
||||
if (mLocalView)
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveView("", mStreamType, this);
|
||||
else
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveView(mUserId, mStreamType, this);
|
||||
int count = TXLiteAVVideoViewManager.GetInstance().Count;
|
||||
if (engine != null)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
engine.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
|
||||
}
|
||||
if (!mLocalView && !TXLiteAVVideoViewManager.GetInstance().HasUserId(mUserId))
|
||||
{
|
||||
engine.setRemoteVideoRenderCallback(mUserId, TRTCVideoPixelFormat.TRTCVideoPixelFormat_Unknown,
|
||||
TRTCVideoBufferType.TRTCVideoBufferType_Unknown, null);
|
||||
}
|
||||
}
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mUserId = "";
|
||||
mOccupy = false;
|
||||
mLocalView = false;
|
||||
mFirstFrame = false;
|
||||
mRenderMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit;
|
||||
//this.OnViewRemove?.Invoke();
|
||||
this.InvalidateVisual();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 View 的渲染模式
|
||||
/// </summary>
|
||||
/// <param name="mode">渲染模式</param>
|
||||
public void SetRenderMode(TRTCVideoFillMode mode)
|
||||
{
|
||||
mRenderMode = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断 View 是否被占用
|
||||
/// </summary>
|
||||
/// <returns>true:当前 View 已被占用,false:当前 View 未被占用</returns>
|
||||
public bool IsViewOccupy()
|
||||
{
|
||||
return mOccupy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停渲染,显示默认图片
|
||||
/// </summary>
|
||||
/// <param name="pause">是否暂停</param>
|
||||
public void SetPause(bool pause)
|
||||
{
|
||||
if (mPause != pause)
|
||||
{
|
||||
mPause = pause;
|
||||
if (mPause)
|
||||
{
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x20, 0x20, 0x20));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0x00, 0x00));
|
||||
// 避免刷新最后一帧数据
|
||||
lock (mArgbFrame)
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
}
|
||||
this.InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有映射信息
|
||||
/// </summary>
|
||||
public static void RemoveAllRegEngine()
|
||||
{
|
||||
TXLiteAVVideoViewManager.GetInstance().RemoveAllView();
|
||||
}
|
||||
|
||||
public bool AppendVideoFrame(byte[] data, int width, int height, TRTCVideoPixelFormat videoFormat, TRTCVideoRotation rotation)
|
||||
{
|
||||
if (!mFirstFrame)
|
||||
mFirstFrame = true;
|
||||
|
||||
OnRenderVideoFrameHandler?.Invoke(data, width, height);
|
||||
|
||||
if (mPause)
|
||||
return false;
|
||||
if (data == null || data.Length <= 0)
|
||||
return false;
|
||||
// data 数据有误
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32 && width * height * 4 != data.Length)
|
||||
return false;
|
||||
// 暂时不支持其他 YUV 类型
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420 && width * height * 3 / 2 != data.Length)
|
||||
return false;
|
||||
|
||||
// 目前只实现了 BGRA32 的数据类型,如需其他类型请重写,并设置回调的数据类型
|
||||
if (videoFormat == TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32)
|
||||
{
|
||||
lock (mArgbFrame)
|
||||
{
|
||||
if (mArgbFrame.data == null || mArgbFrame.width != width || mArgbFrame.height != height)
|
||||
{
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mArgbFrame.width = width;
|
||||
mArgbFrame.height = height;
|
||||
mArgbFrame.data = new byte[data.Length];
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, mArgbFrame.data, 0, (int)data.Length);
|
||||
mArgbFrame.newFrame = true;
|
||||
mArgbFrame.rotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
// 回到主线程刷新当前画面
|
||||
this.Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
this.InvalidateVisual();
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext dc)
|
||||
{
|
||||
bool needDrawFrame = true;
|
||||
if (mPause)
|
||||
needDrawFrame = false;
|
||||
if (mArgbFrame.data == null)
|
||||
needDrawFrame = false;
|
||||
if (!needDrawFrame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (mArgbFrame)
|
||||
{
|
||||
if (mArgbFrame.data == null)
|
||||
return;
|
||||
if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fill)
|
||||
{
|
||||
RenderFillMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
|
||||
}
|
||||
else if (mRenderMode == TRTCVideoFillMode.TRTCVideoFillMode_Fit)
|
||||
{
|
||||
RenderFitMode(dc, mArgbFrame.data, mArgbFrame.width, mArgbFrame.height, (int)mArgbFrame.rotation * 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public event Action<WriteableBitmap> OnRenderVideoFrameHandler;
|
||||
/// <summary>
|
||||
/// 渲染回调byte[] data,int width, int height
|
||||
/// </summary>
|
||||
public event Action<byte[], int, int> OnRenderVideoFrameHandler;
|
||||
//public event Action OnViewRemove;
|
||||
|
||||
private void RenderFillMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
|
||||
{
|
||||
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
|
||||
PixelFormat pixelFormat = PixelFormats.Pbgra32;
|
||||
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
|
||||
int stride = bytesPerPixel * width;
|
||||
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
|
||||
{
|
||||
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
|
||||
mInt32Rect = new Int32Rect(0, 0, width, height);
|
||||
}
|
||||
mWriteableBitmap.Lock();
|
||||
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
|
||||
mWriteableBitmap.AddDirtyRect(mInt32Rect);
|
||||
mWriteableBitmap.Unlock();
|
||||
|
||||
ImageBrush brush = new ImageBrush(mWriteableBitmap);
|
||||
if (rotation > 0)
|
||||
{
|
||||
Matrix transform = Matrix.Identity;
|
||||
double scale = (double)viewWidth / (double)viewHeight;
|
||||
if (rotation == 90 || rotation == 270)
|
||||
transform.ScaleAt(scale, scale, 0.5, 0.5);
|
||||
transform.RotateAt(rotation, 0.5, 0.5);
|
||||
brush.RelativeTransform = new MatrixTransform(transform);
|
||||
}
|
||||
brush.Stretch = Stretch.UniformToFill;
|
||||
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
|
||||
dc.DrawRectangle(brush, mPen, rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void RenderFitMode(DrawingContext dc, byte[] data, int width, int height, int rotation)
|
||||
{
|
||||
int viewWidth = (int)this.ActualWidth, viewHeight = (int)this.ActualHeight;
|
||||
PixelFormat pixelFormat = PixelFormats.Pbgra32;
|
||||
int bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
|
||||
int stride = bytesPerPixel * width;
|
||||
if (mWriteableBitmap == null || mWriteableBitmap.PixelWidth != width || mWriteableBitmap.PixelHeight != height)
|
||||
{
|
||||
mWriteableBitmap = new WriteableBitmap(width, height, 96, 96, pixelFormat, null);
|
||||
mInt32Rect = new Int32Rect(0, 0, width, height);
|
||||
}
|
||||
mWriteableBitmap.Lock();
|
||||
Marshal.Copy(data, 0, mWriteableBitmap.BackBuffer, data.Length);
|
||||
mWriteableBitmap.AddDirtyRect(mInt32Rect);
|
||||
mWriteableBitmap.Unlock();
|
||||
|
||||
//OnRenderVideoFrameHandler?.Invoke(mWriteableBitmap);
|
||||
|
||||
ImageBrush brush = new ImageBrush(mWriteableBitmap);
|
||||
if (rotation > 0)
|
||||
{
|
||||
Matrix transform = Matrix.Identity;
|
||||
double scale = (double)viewHeight / (double)viewWidth;
|
||||
if (rotation == 90 || rotation == 270)
|
||||
transform.ScaleAt(1, scale, 0.5, 0.5);
|
||||
transform.RotateAt(rotation, 0.5, 0.5);
|
||||
brush.RelativeTransform = new MatrixTransform(transform);
|
||||
}
|
||||
brush.Stretch = Stretch.Uniform;
|
||||
Rect rect = new Rect(0, 0, viewWidth, viewHeight);
|
||||
dc.DrawRectangle(brush, mPen, rect);
|
||||
}
|
||||
|
||||
private void ReleaseBuffer(FrameBufferInfo info)
|
||||
{
|
||||
if (info.data != null)
|
||||
info.data = null;
|
||||
info.width = 0;
|
||||
info.height = 0;
|
||||
info.newFrame = false;
|
||||
info.rotation = TRTCVideoRotation.TRTCVideoRotation0;
|
||||
}
|
||||
|
||||
#region Dispose
|
||||
private bool disposed = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed) return;
|
||||
if (disposing)
|
||||
{
|
||||
ReleaseBuffer(mArgbFrame);
|
||||
mWriteableBitmap = null;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
~TXLiteAVVideoView()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class TXLiteAVVideoViewManager : ITRTCVideoRenderCallback
|
||||
{
|
||||
private volatile Dictionary<string, TXLiteAVVideoView> mMapViews;
|
||||
|
||||
public static TXLiteAVVideoViewManager sInstance;
|
||||
|
||||
private static Object mLocker = new Object();
|
||||
|
||||
public static TXLiteAVVideoViewManager GetInstance()
|
||||
{
|
||||
if (sInstance == null)
|
||||
{
|
||||
lock (mLocker)
|
||||
{
|
||||
if (sInstance == null)
|
||||
sInstance = new TXLiteAVVideoViewManager();
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private TXLiteAVVideoViewManager()
|
||||
{
|
||||
mMapViews = new Dictionary<string, TXLiteAVVideoView>();
|
||||
}
|
||||
|
||||
private string GetKey(string userId, TRTCVideoStreamType type)
|
||||
{
|
||||
return String.Format("{0}_{1}", userId, type);
|
||||
}
|
||||
|
||||
// 主要用于判断当前 user 是否还有存在流画面,存在则不移除监听。
|
||||
public bool HasUserId(string userId)
|
||||
{
|
||||
bool exit = false;
|
||||
lock (mMapViews)
|
||||
{
|
||||
exit = mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig)) ||
|
||||
mMapViews.ContainsKey(GetKey(userId, TRTCVideoStreamType.TRTCVideoStreamTypeSub));
|
||||
}
|
||||
return exit;
|
||||
}
|
||||
|
||||
public void AddView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
|
||||
{
|
||||
lock (mMapViews)
|
||||
{
|
||||
bool find = false;
|
||||
foreach (var item in mMapViews)
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, type)))
|
||||
{
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find)
|
||||
{
|
||||
mMapViews.Add(GetKey(userId, type), view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveView(string userId, TRTCVideoStreamType type, TXLiteAVVideoView view)
|
||||
{
|
||||
lock (mMapViews)
|
||||
{
|
||||
foreach (var item in mMapViews.ToList())
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, type)))
|
||||
{
|
||||
if (item.Value != null)
|
||||
{
|
||||
item.Value.Dispose();
|
||||
}
|
||||
mMapViews.Remove(item.Key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAllView()
|
||||
{
|
||||
lock (mMapViews)
|
||||
mMapViews.Clear();
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (mMapViews)
|
||||
return mMapViews.Count;
|
||||
}
|
||||
}
|
||||
|
||||
//public event Action<string, TRTCVideoStreamType, TRTCVideoFrame> OnRenderVideoFrameHandler;
|
||||
/// <summary>
|
||||
/// 自定义渲染回调,只能存在一个回调
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="streamType"></param>
|
||||
/// <param name="frame"></param>
|
||||
public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame)
|
||||
{
|
||||
//OnRenderVideoFrameHandler?.Invoke(userId, streamType, frame);
|
||||
// 大小视频是占一个视频位,底层支持动态切换。
|
||||
if (streamType == TRTCVideoStreamType.TRTCVideoStreamTypeSmall)
|
||||
streamType = TRTCVideoStreamType.TRTCVideoStreamTypeBig;
|
||||
TXLiteAVVideoView view = null;
|
||||
lock (mMapViews)
|
||||
{
|
||||
foreach (var item in mMapViews)
|
||||
{
|
||||
if (item.Key.Equals(GetKey(userId, streamType)) && item.Value != null)
|
||||
{
|
||||
view = item.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (view != null)
|
||||
view.AppendVideoFrame(frame.data, (int)frame.width, (int)frame.height, frame.videoFormat, frame.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
class FrameBufferInfo
|
||||
{
|
||||
public byte[] data { get; set; }
|
||||
|
||||
public int width { get; set; }
|
||||
|
||||
public int height { get; set; }
|
||||
|
||||
public bool newFrame { get; set; }
|
||||
|
||||
public TRTCVideoRotation rotation { get; set; }
|
||||
|
||||
public FrameBufferInfo()
|
||||
{
|
||||
rotation = TRTCVideoRotation.TRTCVideoRotation0;
|
||||
newFrame = false;
|
||||
width = 0;
|
||||
height = 0;
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
using ManageLiteAV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace JianGongYun.TRTC.Utils
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
public static string UTF16To8(string str)
|
||||
{
|
||||
byte[] utf16Bytes = Encoding.Unicode.GetBytes(str);
|
||||
byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
|
||||
return Encoding.UTF8.GetString(utf8Bytes);
|
||||
}
|
||||
|
||||
public static bool IsSys64bit()
|
||||
{
|
||||
return IntPtr.Size == 8;
|
||||
}
|
||||
|
||||
public static string GetRandomString(int iLength)
|
||||
{
|
||||
string buffer = "0123456789";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Random r = new Random(iLength);
|
||||
int range = buffer.Length;
|
||||
for (int i = 0; i < iLength; i++)
|
||||
{
|
||||
sb.Append(buffer.Substring(r.Next(range), 1));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string MD5(string str)
|
||||
{
|
||||
MD5 md5 = System.Security.Cryptography.MD5.Create();
|
||||
byte[] byteOld = Encoding.UTF8.GetBytes(str);
|
||||
byte[] byteNew = md5.ComputeHash(byteOld);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (byte b in byteNew)
|
||||
{
|
||||
// 将字节转换成16进制表示的字符串
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static bool IsTestEnv()
|
||||
{
|
||||
string path = Environment.CurrentDirectory + "\\ShowTestEnv.txt";
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public static string ConvertMSToTime(int lCurMS, int lDurationMS)
|
||||
{
|
||||
string strTime = "00:00/00:00";
|
||||
|
||||
int nTotalDurationSecond = lDurationMS / 1000;
|
||||
int nDurationMinute = nTotalDurationSecond / 60;
|
||||
int nDurationSecond = nTotalDurationSecond % 60;
|
||||
|
||||
int nTotalCurSecond = lCurMS / 1000;
|
||||
int nCurMinute = nTotalCurSecond / 60;
|
||||
int nCurSecond = nTotalCurSecond % 60;
|
||||
|
||||
string format = "{0:00}:{1:00}/{2:00}:{3:00}";
|
||||
|
||||
strTime = string.Format(format, nCurMinute, nCurSecond, nDurationMinute, nDurationSecond);
|
||||
|
||||
return strTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 把trtc的图片buffer复制给wpf的writeableBitmap
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public static WriteableBitmap ToWriteableBitmap(this TRTCImageBuffer data)
|
||||
{
|
||||
var writeableBitmap = new WriteableBitmap((int)data.width, (int)data.height, 96, 96, PixelFormats.Pbgra32, null);
|
||||
writeableBitmap.Lock();
|
||||
Marshal.Copy(data.buffer, 0, writeableBitmap.BackBuffer, (int)data.length);
|
||||
writeableBitmap.AddDirtyRect(new System.Windows.Int32Rect(0, 0, (int)data.width, (int)data.height));
|
||||
writeableBitmap.Unlock();
|
||||
return writeableBitmap;
|
||||
}
|
||||
|
||||
public static string TimeStr() => DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net40" />
|
||||
<package id="zlib.net" version="1.0.4.0" targetFramework="net40" />
|
||||
</packages>
|
|
@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30717.126
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JianGongYun", "JianGongYun\JianGongYun.csproj", "{0B346099-B101-4426-800A-6FB1D4308F34}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientDemo", "ClientDemo\ClientDemo.csproj", "{5C83270B-1086-494D-BCAF-0E773CC598AB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -27,6 +29,18 @@ Global
|
|||
{0B346099-B101-4426-800A-6FB1D4308F34}.Release|x64.Build.0 = Release|x64
|
||||
{0B346099-B101-4426-800A-6FB1D4308F34}.Release|x86.ActiveCfg = Release|x86
|
||||
{0B346099-B101-4426-800A-6FB1D4308F34}.Release|x86.Build.0 = Release|x86
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5C83270B-1086-494D-BCAF-0E773CC598AB}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -247,6 +247,7 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
{
|
||||
//Console.WriteLine("get LiveScreens");
|
||||
_LiveScreens.Clear();
|
||||
LiveClassroom.lTRTCCloud.removeAllExcludedShareWindow();
|
||||
//Console.WriteLine("get LiveScreens Clear");
|
||||
var temp = LiveClassroom.lTRTCCloud.getScreenCaptureSources(ref thumbSize, ref iconSize);
|
||||
var count = temp.getCount();
|
||||
|
@ -256,6 +257,7 @@ namespace JianGongYun.TRTC.ViewModels
|
|||
var info = temp.getSourceInfo(i);
|
||||
if (string.IsNullOrWhiteSpace(info.sourceName) || excluded.Contains(info.sourceName))
|
||||
{
|
||||
LiveClassroom.lTRTCCloud.addExcludedShareWindow(info.sourceId);
|
||||
continue;
|
||||
}
|
||||
//var icon = Util.ToWriteableBitmap(ref info.iconBGRA);
|
||||
|
|
Loading…
Reference in New Issue