Third step of the tutorial with the ability to perform outgoing calls. Audio / video + controles (mic, speaker, cameras) are availables. Dev only.
111 lines
2.6 KiB
C#
111 lines
2.6 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using Windows.UI.Core;
|
|
using Windows.UI.Xaml.Controls;
|
|
using EGLNativeWindowType = System.IntPtr;
|
|
using OpenGlFunctions = System.IntPtr;
|
|
|
|
namespace _02_outgoing_call.Service
|
|
{
|
|
class VideoService
|
|
{
|
|
private static readonly VideoService instance = new VideoService();
|
|
|
|
public static VideoService Instance
|
|
{
|
|
get
|
|
{
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
private CoreService CoreService { get; } = CoreService.Instance;
|
|
private bool AlearadyStartedOnce { get; set; }
|
|
private bool AlearadyStartedOncePreview { get; set; }
|
|
private Timer Timer { get; set; }
|
|
|
|
public struct ContextInfo
|
|
{
|
|
public EGLNativeWindowType window;
|
|
public OpenGlFunctions functions;
|
|
}
|
|
|
|
public void StartVideoStream(SwapChainPanel main, SwapChainPanel preview, CoreDispatcher dispatcher)
|
|
{
|
|
CreateRenderSurface(preview, true);
|
|
CreateRenderSurface(main, false);
|
|
|
|
Timer = new Timer(OnTimedEvent, dispatcher, 40, 40);
|
|
}
|
|
|
|
private async void OnTimedEvent(object state)
|
|
{
|
|
await ((CoreDispatcher)state).RunIdleAsync((args) =>
|
|
{
|
|
CoreService.Core.PreviewOglRender();
|
|
if (CoreService.Core.CurrentCall != null)
|
|
CoreService.Core.CurrentCall.OglRender();
|
|
});
|
|
}
|
|
|
|
public void StopVideoStream()
|
|
{
|
|
AlearadyStartedOnce = true;
|
|
if (Timer != null)
|
|
{
|
|
Timer.Dispose();
|
|
}
|
|
}
|
|
|
|
public void CreateRenderSurface(SwapChainPanel panel, bool isPreview)
|
|
{// Need to convert C# object into C++. Warning to memory leak
|
|
IntPtr oldData;// Used to release memory after assignation
|
|
ContextInfo c;
|
|
|
|
if (panel != null)
|
|
{
|
|
c.window = Marshal.GetIUnknownForObject(panel);
|
|
}
|
|
else
|
|
{
|
|
c.window = IntPtr.Zero;
|
|
}
|
|
c.functions = IntPtr.Zero;
|
|
|
|
IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(c));
|
|
Marshal.StructureToPtr(c, pnt, false);
|
|
|
|
if (isPreview)
|
|
{
|
|
oldData = CoreService.Core.NativePreviewWindowId;
|
|
CoreService.Core.NativePreviewWindowId = pnt;
|
|
if (AlearadyStartedOncePreview)
|
|
{
|
|
CleanMemory(oldData);
|
|
}
|
|
AlearadyStartedOncePreview = true;
|
|
}
|
|
else
|
|
{
|
|
if (CoreService.Core.CurrentCall != null)
|
|
{
|
|
oldData = CoreService.Core.CurrentCall.NativeVideoWindowId;
|
|
CoreService.Core.CurrentCall.NativeVideoWindowId = pnt;
|
|
if (AlearadyStartedOnce)
|
|
{
|
|
CleanMemory(oldData);
|
|
}
|
|
AlearadyStartedOnce = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CleanMemory(IntPtr context)
|
|
{
|
|
if (context != IntPtr.Zero)
|
|
Marshal.FreeHGlobal(context);
|
|
}
|
|
}
|
|
}
|