NewN_UAVPlane/Assets/Plugins/RenderHeads/AVProMovieCapture/Runtime/Scripts/Internal/NativePlugin.cs

496 lines
14 KiB
C#

using UnityEngine;
using System;
using System.Text;
using System.Runtime.InteropServices;
#if UNITY_IOS || UNITY_TVOS || ENABLE_IL2CPP
using AOT;
#endif
//-----------------------------------------------------------------------------
// Copyright 2012-2021 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProMovieCapture
{
public enum AudioCaptureSource
{
None = 0,
Unity = 1,
Microphone = 2,
Manual = 3,
}
public enum StereoPacking
{
None,
TopBottom,
LeftRight,
}
public enum StopMode
{
None,
FramesEncoded,
SecondsEncoded,
SecondsElapsed,
}
public enum StartTriggerMode
{
Manual,
OnStart,
}
public enum StartDelayMode
{
None,
RealSeconds,
GameSeconds,
Manual,
}
public enum ImageSequenceFormat
{
PNG,
JPEG, // Apple platforms only
TIFF, // Apple platforms only
HEIF, // Apple platforms only
}
public enum OutputTarget
{
VideoFile,
ImageSequence,
NamedPipe,
}
public partial class NativePlugin
{
#if UNITY_IOS && !UNITY_EDITOR
const string PluginName = "__Internal";
#else
const string PluginName = "AVProMovieCapture";
#endif
public enum Platform
{
Unknown = -2,
Current = -1,
First = 0,
Windows = 0,
macOS = 1,
iOS = 2,
Count = 3,
}
public static string[] PlatformNames = { "Windows", "macOS", "iOS" };
// The Apple platforms have a fixed set of known codecs
public static readonly string[] VideoCodecNamesMacOS = { "H264", "HEVC", "MJPEG", "ProRes 4:2:2", "ProRes 4:4:4:4" };
public static readonly string[] AudioCodecNamesMacOS = { "AAC", "FLAC", "Apple Lossless", "Linear PCM", "Uncompresssed" };
public static readonly string[] VideoCodecNamesIOS = { "H264", "HEVC", "MJPEG" };
public static readonly string[] AudioCodecNamesIOS = { "AAC", "FLAC", "Apple Lossless", "Linear PCM", "Uncompresssed" };
public enum PixelFormat
{
RGBA32,
BGRA32, // Note: This is the native format for Unity textures with red and blue swapped.
YCbCr422_YUY2,
YCbCr422_UYVY,
YCbCr422_HDYC,
}
public const string ScriptVersion = "4.6.3";
#if UNITY_EDITOR_OSX || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IOS))
public const string ExpectedPluginVersion = "4.6.3";
#else
public const string ExpectedPluginVersion = "4.6.2";
#endif
public const int MaxRenderWidth = 16384;
public const int MaxRenderHeight = 16384;
#region RenderEventFunctions
// Used by GL.IssuePluginEvent
private const int PluginID = 0xFA30000;
public enum PluginEvent
{
CaptureFrameBuffer = 0,
FreeResources = 1,
}
private static System.IntPtr _renderEventFunction = System.IntPtr.Zero;
private static System.IntPtr _freeEventFunction = System.IntPtr.Zero;
public static void RenderThreadEvent(PluginEvent renderEvent, int handle)
{
if (renderEvent == PluginEvent.CaptureFrameBuffer)
{
GL.IssuePluginEvent(RenderCaptureEventFunction, PluginID | (int)renderEvent | handle);
}
else if (renderEvent == PluginEvent.FreeResources)
{
int eventId = PluginID | (int)renderEvent;
GL.IssuePluginEvent(RenderFreeEventFunction, eventId);
}
}
private static System.IntPtr RenderCaptureEventFunction
{
get
{
if (_renderEventFunction == System.IntPtr.Zero)
{
_renderEventFunction = GetRenderEventFunc();
}
Debug.Assert(_renderEventFunction != System.IntPtr.Zero);
return _renderEventFunction;
}
}
private static System.IntPtr RenderFreeEventFunction
{
get
{
if (_freeEventFunction == System.IntPtr.Zero)
{
_freeEventFunction = GetFreeResourcesEventFunc();
}
Debug.Assert(_freeEventFunction != System.IntPtr.Zero);
return _freeEventFunction;
}
}
[DllImport(PluginName)]
private static extern System.IntPtr GetRenderEventFunc();
[DllImport(PluginName)]
private static extern System.IntPtr GetFreeResourcesEventFunc();
#endregion
#if UNITY_EDITOR_OSX || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IOS))
internal class Logger
{
private enum LogFlag : int {
Error = 1 << 0,
Warning = 1 << 1,
Info = 1 << 2,
Debug = 1 << 3,
Verbose = 1 << 4,
};
private enum LogLevel : int
{
Off = 0,
Error = LogFlag.Error,
Warning = Error | LogFlag.Warning,
Info = Warning | LogFlag.Info,
Debug = Info | LogFlag.Debug,
Verbose = Debug | LogFlag.Verbose,
All = -1,
};
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
#endif
private delegate void DebugLogCallbackDelegate(LogLevel level, [In, MarshalAs(UnmanagedType.LPWStr)] string str);
#if UNITY_IOS || UNITY_TVOS || ENABLE_IL2CPP
[MonoPInvokeCallback(typeof(DebugLogCallbackDelegate))]
#endif
private static void DebugLogCallback(LogLevel level, string str)
{
if (level == LogLevel.Error)
{
Debug.LogError(str);
}
else if (level == LogLevel.Warning)
{
Debug.LogWarning(str);
}
else
{
Debug.Log(str);
}
}
private DebugLogCallbackDelegate _callbackDelegate = new DebugLogCallbackDelegate(DebugLogCallback);
internal Logger()
{
IntPtr func = Marshal.GetFunctionPointerForDelegate(_callbackDelegate);
NativePlugin.SetLogFunction(func);
}
~Logger()
{
NativePlugin.SetLogFunction(IntPtr.Zero);
}
}
internal static Logger _logger;
private static void SetupDebugLogCallback()
{
_logger = new Logger();
}
#if !UNITY_EDITOR_OSX && UNITY_IOS
[DllImport(PluginName)]
public static extern void MCPluginBootstrap();
#endif
static NativePlugin()
{
#if UNITY_EDITOR_OSX
SetupDebugLogCallback();
#endif
#if !UNITY_EDITOR_OSX && UNITY_IOS
NativePlugin.MCPluginBootstrap();
#endif
}
#endif
//////////////////////////////////////////////////////////////////////////
// Global Init/Deinit
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool Init();
[DllImport(PluginName)]
public static extern void Deinit();
[DllImport(PluginName)]
public static extern void SetMicrophoneRecordingHint([MarshalAs(UnmanagedType.U1)] bool enabled);
public static string GetPluginVersionString()
{
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(GetPluginVersion());
}
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool IsTrialVersion();
//////////////////////////////////////////////////////////////////////////
// Video Codecs
[DllImport(PluginName)]
public static extern int GetVideoCodecCount();
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool IsConfigureVideoCodecSupported(int codecIndex);
[DllImport(PluginName)]
public static extern MediaApi GetVideoCodecMediaApi(int codecIndex);
[DllImport(PluginName)]
public static extern void ConfigureVideoCodec(int codecIndex);
public static string GetVideoCodecName(int codecIndex)
{
string result = "Invalid";
StringBuilder nameBuffer = new StringBuilder(256);
if (GetVideoCodecName(codecIndex, nameBuffer, nameBuffer.Capacity))
{
result = nameBuffer.ToString();
}
return result;
}
//////////////////////////////////////////////////////////////////////////
// Audio Codecs
[DllImport(PluginName)]
public static extern int GetAudioCodecCount();
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool IsConfigureAudioCodecSupported(int codecIndex);
[DllImport(PluginName)]
public static extern MediaApi GetAudioCodecMediaApi(int codecIndex);
[DllImport(PluginName)]
public static extern void ConfigureAudioCodec(int codecIndex);
public static string GetAudioCodecName(int codecIndex)
{
string result = "Invalid";
StringBuilder nameBuffer = new StringBuilder(256);
if (GetAudioCodecName(codecIndex, nameBuffer, nameBuffer.Capacity))
{
result = nameBuffer.ToString();
}
return result;
}
//////////////////////////////////////////////////////////////////////////
// Audio Devices
[DllImport(PluginName)]
public static extern int GetAudioInputDeviceCount();
public static string GetAudioInputDeviceName(int index)
{
string result = "Invalid";
StringBuilder nameBuffer = new StringBuilder(256);
if (GetAudioInputDeviceName(index, nameBuffer, nameBuffer.Capacity))
{
result = nameBuffer.ToString();
}
return result;
}
#if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
[DllImport(PluginName)]
public static extern MediaApi GetAudioInputDeviceMediaApi(int index);
#else
public static MediaApi GetAudioInputDeviceMediaApi(int index)
{
#if UNITY_EDITOR_OSX || (!UNITY_EDITOR && (UNITY_STANDALONE_OSX || UNITY_IOS))
return MediaApi.AVFoundation;
#else
return MediaApi.Unknown;
#endif
}
#endif
//////////////////////////////////////////////////////////////////////////
// Container Files
public static string[] GetContainerFileExtensions(int videoCodecIndex, int audioCodecIndex = -1)
{
string[] result = new string[0];
StringBuilder extensionsBuffer = new StringBuilder(256);
if (GetContainerFileExtensions(videoCodecIndex, audioCodecIndex, extensionsBuffer, extensionsBuffer.Capacity))
{
result = extensionsBuffer.ToString().Split(new char[] {','});
}
return result;
}
//////////////////////////////////////////////////////////////////////////
// Create the Recorder
[DllImport(PluginName)]
public static extern int CreateRecorderVideo([MarshalAs(UnmanagedType.LPWStr)] string filename, uint width, uint height, float frameRate, int format,
[MarshalAs(UnmanagedType.U1)] bool isRealTime, [MarshalAs(UnmanagedType.U1)] bool isTopDown, int videoCodecIndex,
AudioCaptureSource audioSource, int audioSampleRate, int audioChannelCount, int audioInputDeviceIndex, int audioCodecIndex,
[MarshalAs(UnmanagedType.U1)] bool forceGpuFlush, VideoEncoderHints hints);
[DllImport(PluginName)]
public static extern int CreateRecorderImages([MarshalAs(UnmanagedType.LPWStr)] string filename, uint width, uint height, float frameRate, int format,
[MarshalAs(UnmanagedType.U1)] bool isRealTime, [MarshalAs(UnmanagedType.U1)] bool isTopDown, int imageFormatType, [MarshalAs(UnmanagedType.U1)] bool forceGpuFlush, int startFrame, ImageEncoderHints hints);
[DllImport(PluginName)]
public static extern int CreateRecorderPipe([MarshalAs(UnmanagedType.LPWStr)] string filename, uint width, uint height, float frameRate, int format,
[MarshalAs(UnmanagedType.U1)] bool isTopDown, [MarshalAs(UnmanagedType.U1)] bool supportAlpha, [MarshalAs(UnmanagedType.U1)] bool forceGpuFlush);
//////////////////////////////////////////////////////////////////////////
// Update recorder
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool Start(int handle);
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool IsNewFrameDue(int handle);
[DllImport(PluginName)]
public static extern int SetEncodedFrameLimit(int handle, uint encodedFrameLimit);
[DllImport(PluginName)]
public static extern void EncodeFrame(int handle, System.IntPtr data);
[DllImport(PluginName)]
public static extern void EncodeAudio(int handle, System.IntPtr data, uint length);
[DllImport(PluginName)]
public static extern void EncodeFrameWithAudio(int handle, System.IntPtr videoData, System.IntPtr audioData, uint audioLength);
[DllImport(PluginName)]
public static extern void Pause(int handle);
[DllImport(PluginName)]
public static extern void Stop(int handle, [MarshalAs(UnmanagedType.U1)] bool skipPendingFrames);
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool IsFileWritingComplete(int handle);
[DllImport(PluginName)]
public static extern void SetTexturePointer(int handle, System.IntPtr texture);
#if false
[DllImport(PluginName)]
public static extern void SetColourBuffer(int handle, System.IntPtr buffer);
#endif
//////////////////////////////////////////////////////////////////////////
// Destroy recorder
[DllImport(PluginName)]
public static extern void FreeRecorder(int handle);
//////////////////////////////////////////////////////////////////////////
// Debugging
[DllImport(PluginName)]
public static extern uint GetNumDroppedFrames(int handle);
[DllImport(PluginName)]
public static extern uint GetNumDroppedEncoderFrames(int handle);
[DllImport(PluginName)]
public static extern uint GetNumEncodedFrames(int handle);
[DllImport(PluginName)]
public static extern uint GetEncodedSeconds(int handle);
[DllImport(PluginName)]
public static extern uint GetFileSize(int handle);
//////////////////////////////////////////////////////////////////////////
// Private internal functions
[DllImport(PluginName)]
private static extern System.IntPtr GetPluginVersion();
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool GetVideoCodecName(int index, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int nameBufferLength);
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool GetAudioCodecName(int index, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int nameBufferLength);
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool GetAudioInputDeviceName(int index, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int nameBufferLength);
[DllImport(PluginName)]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool GetContainerFileExtensions(int videoCodecIndex, int audioCodecIndex, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder extensions, int extensionsBufferLength);
//////////////////////////////////////////////////////////////////////////
// Logging
[DllImport(PluginName)]
public static extern void SetLogFunction(System.IntPtr fn);
//////////////////////////////////////////////////////////////////////////
// Error reporting
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ErrorHandlerDelegate(int handle, int domain, int code, [In, MarshalAs(UnmanagedType.LPWStr)] string message);
[DllImport(PluginName)]
public static extern void SetErrorHandler(int handle, System.IntPtr handler);
}
}