using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using CineCamUnlimited;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.XR;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(CineCamMod), "CineCam Unlimited", "0.8.0", "NovaVR", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CineCamOverload")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CineCamOverload")]
[assembly: AssemblyTitle("CineCamOverload")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace CineCamUnlimited
{
public enum CameraPreset
{
Custom,
Action,
Smooth,
Handheld,
Tripod,
Drone,
Orbit,
Chase,
Bodycam,
Selfie,
SlowPan,
Dolly
}
public sealed class CineCamMod : MelonMod
{
internal static CineCamMod Instance;
internal readonly CameraManager Cameras = new CameraManager();
internal readonly VideoSettings Video = new VideoSettings();
internal readonly Recorder Recorder = new Recorder();
private Page _root;
public override void OnInitializeMelon()
{
Instance = this;
MelonLogger.Msg("CineCam Unlimited initializing...");
BuildMenu();
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
Cameras.Clear();
Recorder.EmergencyStop();
}
public override void OnUpdate()
{
Cameras.Tick();
Recorder.Tick(Cameras.Active, Video);
}
public override void OnDeinitializeMelon()
{
Recorder.EmergencyStop();
Cameras.Clear();
}
private void BuildMenu()
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_023e: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0323: Unknown result type (might be due to invalid IL or missing references)
//IL_0331: Unknown result type (might be due to invalid IL or missing references)
//IL_0350: Unknown result type (might be due to invalid IL or missing references)
//IL_0384: Unknown result type (might be due to invalid IL or missing references)
//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_0431: Unknown result type (might be due to invalid IL or missing references)
//IL_044a: Unknown result type (might be due to invalid IL or missing references)
//IL_0463: Unknown result type (might be due to invalid IL or missing references)
//IL_047b: Unknown result type (might be due to invalid IL or missing references)
try
{
Color val = default(Color);
((Color)(ref val))..ctor(0.55f, 0.3f, 1f);
Color val2 = default(Color);
((Color)(ref val2))..ctor(0.85f, 0.85f, 0.92f);
Color val3 = default(Color);
((Color)(ref val3))..ctor(0.55f, 0.95f, 0.65f);
Color val4 = default(Color);
((Color)(ref val4))..ctor(1f, 0.38f, 0.38f);
_root = Page.Root.CreatePage("CineCam Unlimited", val, 0, true);
Page obj = _root.CreatePage("Cameras", val, 0, true);
obj.CreateFunction("Spawn Camera", val3, (Action)delegate
{
Notify(Cameras.SpawnNearPlayer());
});
obj.CreateFunction("Next Camera", val2, (Action)delegate
{
Notify(Cameras.SelectNext());
});
obj.CreateFunction("Previous Camera", val2, (Action)delegate
{
Notify(Cameras.SelectPrevious());
});
obj.CreateFunction("Delete Active", val4, (Action)delegate
{
Notify(Cameras.DeleteActive());
});
obj.CreateFunction("Delete All", val4, (Action)delegate
{
Recorder.EmergencyStop();
Cameras.Clear();
Notify("All cameras removed.");
});
obj.CreateFunction("Toggle Monitor", val2, (Action)delegate
{
Notify(Cameras.ToggleMonitor());
});
obj.CreateFunction("Toggle Mirror View", val2, (Action)delegate
{
Notify(Cameras.ToggleMirrorView());
});
Page obj2 = _root.CreatePage("Presets", val, 0, true);
obj2.CreateEnum("Camera Preset", val2, (Enum)CameraPreset.Custom, (Action<Enum>)delegate(Enum value)
{
CameraPreset preset = (CameraPreset)(object)value;
Cameras.ApplyPreset(preset);
Notify("Preset: " + preset);
});
obj2.CreateFunction("Action", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Action);
});
obj2.CreateFunction("Smooth", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Smooth);
});
obj2.CreateFunction("Handheld", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Handheld);
});
obj2.CreateFunction("Tripod", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Tripod);
});
obj2.CreateFunction("Drone", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Drone);
});
obj2.CreateFunction("Selfie", val3, (Action)delegate
{
Cameras.ApplyPreset(CameraPreset.Selfie);
});
Page obj3 = _root.CreatePage("Advanced Tuning", val, 0, true);
obj3.CreateFloat("FOV", val2, 70f, 1f, 30f, 120f, (Action<float>)delegate(float value)
{
Cameras.SetFov(value);
});
obj3.CreateFloat("Position Smooth", val2, 8f, 0.5f, 0f, 30f, (Action<float>)delegate(float value)
{
Cameras.SetPositionSmooth(value);
});
obj3.CreateFloat("Rotation Smooth", val2, 10f, 0.5f, 0f, 30f, (Action<float>)delegate(float value)
{
Cameras.SetRotationSmooth(value);
});
obj3.CreateFloat("Shake", val2, 0f, 0.01f, 0f, 0.35f, (Action<float>)delegate(float value)
{
Cameras.SetShake(value);
});
obj3.CreateFloat("Near Clip", val2, 0.03f, 0.01f, 0.01f, 1f, (Action<float>)delegate(float value)
{
Cameras.SetNearClip(value);
});
obj3.CreateFloat("Far Clip", val2, 1000f, 25f, 50f, 4000f, (Action<float>)delegate(float value)
{
Cameras.SetFarClip(value);
});
Page obj4 = _root.CreatePage("Video", val, 0, true);
obj4.CreateEnum("Resolution", val2, (Enum)ResolutionPreset.Q2Safe, (Action<Enum>)delegate(Enum value)
{
Video.ApplyPreset((ResolutionPreset)(object)value);
});
obj4.CreateFloat("Custom Width", val2, (float)Video.Width, 16f, 320f, 3840f, (Action<float>)delegate(float value)
{
Video.Width = MakeEven((int)value);
});
obj4.CreateFloat("Custom Height", val2, (float)Video.Height, 16f, 180f, 2160f, (Action<float>)delegate(float value)
{
Video.Height = MakeEven((int)value);
});
obj4.CreateFloat("FPS", val2, (float)Video.Fps, 1f, 15f, 120f, (Action<float>)delegate(float value)
{
Video.Fps = Mathf.Clamp((int)value, 15, 120);
});
obj4.CreateFloat("Bitrate Mbps", val2, Video.BitrateMbps, 0.5f, 1f, 80f, (Action<float>)delegate(float value)
{
Video.BitrateMbps = Mathf.Clamp(value, 1f, 80f);
});
Page obj5 = _root.CreatePage("Recording", val, 0, true);
obj5.CreateFunction("QUICK RECORD / STOP", val3, (Action)ToggleRecording);
obj5.CreateFunction("Stop + Save", val4, (Action)delegate
{
Recorder.Stop();
Notify(Recorder.Status);
});
obj5.CreateFunction("Recording Status", val2, (Action)delegate
{
Notify(Recorder.Status);
});
obj5.CreateFunction("Open Camera Folder Info", val2, (Action)delegate
{
Notify("Clips: /sdcard/Movies/CineCamUnlimited/");
});
}
catch (Exception ex)
{
MelonLogger.Error("BoneMenu setup failed: " + ex);
}
}
private void ToggleRecording()
{
if (Recorder.IsRecording)
{
Recorder.Stop();
Notify(Recorder.Status);
}
else if (Cameras.Active == null)
{
Notify("Spawn a camera first.");
}
else
{
Recorder.Start(Cameras.Active, Video);
Notify(Recorder.Status);
}
}
private static int MakeEven(int value)
{
return Math.Max(2, value & -2);
}
internal static void Notify(string message)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
if (string.IsNullOrWhiteSpace(message))
{
return;
}
MelonLogger.Msg(message);
try
{
Notifier.Send(new Notification
{
Title = NotificationText.op_Implicit("CineCam Unlimited"),
Message = NotificationText.op_Implicit(message),
Type = (NotificationType)0,
PopupLength = 3f,
ShowTitleOnPopup = true
});
}
catch
{
}
}
}
public enum ResolutionPreset
{
Q2Safe,
Q3Balanced,
HD720,
HD1080,
Custom
}
public sealed class VideoSettings
{
public int Width = 960;
public int Height = 540;
public int Fps = 30;
public float BitrateMbps = 8f;
public void ApplyPreset(ResolutionPreset preset)
{
switch (preset)
{
case ResolutionPreset.Q2Safe:
Width = 960;
Height = 540;
Fps = 30;
BitrateMbps = 8f;
break;
case ResolutionPreset.Q3Balanced:
Width = 1280;
Height = 720;
Fps = 60;
BitrateMbps = 16f;
break;
case ResolutionPreset.HD720:
Width = 1280;
Height = 720;
Fps = 30;
BitrateMbps = 12f;
break;
case ResolutionPreset.HD1080:
Width = 1920;
Height = 1080;
Fps = 30;
BitrateMbps = 20f;
break;
case ResolutionPreset.Custom:
break;
}
}
}
public sealed class CameraManager
{
private readonly List<CineCamera> _cameras = new List<CineCamera>();
private int _activeIndex = -1;
public CineCamera Active
{
get
{
if (_activeIndex < 0 || _activeIndex >= _cameras.Count)
{
return null;
}
return _cameras[_activeIndex];
}
}
public int Count => _cameras.Count;
public string SpawnNearPlayer()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
Camera main = Camera.main;
if ((Object)(object)main == (Object)null)
{
return "Could not find the player camera.";
}
int num = _cameras.Count + 1;
Vector3 position = ((Component)main).transform.position + ((Component)main).transform.forward * 1.1f + Vector3.up * -0.08f;
Quaternion rotation = ((Component)main).transform.rotation;
CineCamera cineCamera = CineCamera.Create("Camera " + num, position, rotation);
_cameras.Add(cineCamera);
_activeIndex = _cameras.Count - 1;
return $"Spawned {cineCamera.Name}. Cameras: {_cameras.Count}";
}
public string SelectNext()
{
if (_cameras.Count == 0)
{
return "No cameras.";
}
_activeIndex = (_activeIndex + 1) % _cameras.Count;
return "Active: " + Active.Name;
}
public string SelectPrevious()
{
if (_cameras.Count == 0)
{
return "No cameras.";
}
_activeIndex--;
if (_activeIndex < 0)
{
_activeIndex = _cameras.Count - 1;
}
return "Active: " + Active.Name;
}
public string DeleteActive()
{
if (Active == null)
{
return "No active camera.";
}
string name = Active.Name;
Active.Dispose();
_cameras.RemoveAt(_activeIndex);
if (_cameras.Count == 0)
{
_activeIndex = -1;
}
else
{
_activeIndex = Mathf.Clamp(_activeIndex, 0, _cameras.Count - 1);
}
return "Removed " + name;
}
public string ToggleMonitor()
{
if (Active == null)
{
return "No active camera.";
}
Active.MonitorEnabled = !Active.MonitorEnabled;
Active.RefreshMonitor();
return "Live monitor: " + (Active.MonitorEnabled ? "ON" : "OFF");
}
public string ToggleMirrorView()
{
if (Active == null)
{
return "No active camera.";
}
Active.MirrorPreview = !Active.MirrorPreview;
Active.RefreshMonitor();
return "Mirror view: " + (Active.MirrorPreview ? "ON" : "OFF");
}
public void ApplyPreset(CameraPreset preset)
{
Active?.ApplyPreset(preset);
}
public void SetFov(float v)
{
if (Active != null)
{
Active.Fov = v;
}
}
public void SetPositionSmooth(float v)
{
if (Active != null)
{
Active.PositionSmooth = v;
}
}
public void SetRotationSmooth(float v)
{
if (Active != null)
{
Active.RotationSmooth = v;
}
}
public void SetShake(float v)
{
if (Active != null)
{
Active.Shake = v;
}
}
public void SetNearClip(float v)
{
if (Active != null)
{
Active.UnityCamera.nearClipPlane = v;
}
}
public void SetFarClip(float v)
{
if (Active != null)
{
Active.UnityCamera.farClipPlane = v;
}
}
public void Tick()
{
for (int i = 0; i < _cameras.Count; i++)
{
_cameras[i].Tick();
}
}
public void Clear()
{
for (int i = 0; i < _cameras.Count; i++)
{
_cameras[i].Dispose();
}
_cameras.Clear();
_activeIndex = -1;
}
}
public sealed class CineCamera : IDisposable
{
public string Name;
public GameObject Root;
public Camera UnityCamera;
public RenderTexture Preview;
public GameObject Monitor;
public bool MonitorEnabled = true;
public bool MirrorPreview;
public TextMesh MonitorStatusText;
public TextMesh MonitorModeText;
private bool _recording;
private float _recordingStartedAt;
public float Fov = 70f;
public float PositionSmooth = 8f;
public float RotationSmooth = 10f;
public float Shake;
public CameraPreset Preset;
private Vector3 _baseLocalPos;
private Quaternion _baseLocalRot;
private bool _disposed;
private XRNode? _heldBy;
private bool _lastTriggerPressed;
private bool _lastGripPressedLeft;
private bool _lastGripPressedRight;
private Rigidbody _rigidbody;
private Transform _sideGripPoint;
private Transform _topGripPoint;
public static CineCamera Create(string name, Vector3 position, Quaternion rotation)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0312: Unknown result type (might be due to invalid IL or missing references)
//IL_0330: Unknown result type (might be due to invalid IL or missing references)
//IL_0377: Unknown result type (might be due to invalid IL or missing references)
//IL_0396: Unknown result type (might be due to invalid IL or missing references)
//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0406: Expected O, but got Unknown
//IL_0434: Unknown result type (might be due to invalid IL or missing references)
//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
//IL_049f: Unknown result type (might be due to invalid IL or missing references)
//IL_04a9: Expected O, but got Unknown
//IL_051d: Unknown result type (might be due to invalid IL or missing references)
//IL_0541: Unknown result type (might be due to invalid IL or missing references)
//IL_0565: Unknown result type (might be due to invalid IL or missing references)
//IL_0605: Unknown result type (might be due to invalid IL or missing references)
//IL_060c: Expected O, but got Unknown
//IL_063a: Unknown result type (might be due to invalid IL or missing references)
//IL_064b: Unknown result type (might be due to invalid IL or missing references)
//IL_065c: Unknown result type (might be due to invalid IL or missing references)
//IL_0666: Unknown result type (might be due to invalid IL or missing references)
//IL_06b8: Unknown result type (might be due to invalid IL or missing references)
//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
//IL_06de: Expected O, but got Unknown
//IL_070c: Unknown result type (might be due to invalid IL or missing references)
//IL_071d: Unknown result type (might be due to invalid IL or missing references)
//IL_072e: Unknown result type (might be due to invalid IL or missing references)
//IL_0738: Unknown result type (might be due to invalid IL or missing references)
//IL_078a: Unknown result type (might be due to invalid IL or missing references)
//IL_07b0: Unknown result type (might be due to invalid IL or missing references)
//IL_07b5: Unknown result type (might be due to invalid IL or missing references)
//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
//IL_07cb: Unknown result type (might be due to invalid IL or missing references)
//IL_05c2: Unknown result type (might be due to invalid IL or missing references)
//IL_05cc: Expected O, but got Unknown
//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
CineCamera cineCamera = new CineCamera();
cineCamera.Name = name;
cineCamera.Root = new GameObject("CineCam_" + name.Replace(" ", "_"));
cineCamera.Root.transform.position = position;
cineCamera.Root.transform.rotation = rotation;
GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)obj).name = "CameraBody";
obj.transform.SetParent(cineCamera.Root.transform, false);
obj.transform.localScale = new Vector3(0.2f, 0.11f, 0.32f);
Collider component = obj.GetComponent<Collider>();
if ((Object)(object)component != (Object)null)
{
component.isTrigger = false;
}
cineCamera._rigidbody = cineCamera.Root.AddComponent<Rigidbody>();
cineCamera._rigidbody.mass = 0.75f;
cineCamera._rigidbody.interpolation = (RigidbodyInterpolation)1;
cineCamera._rigidbody.collisionDetectionMode = (CollisionDetectionMode)2;
GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)2);
((Object)obj2).name = "Lens";
obj2.transform.SetParent(cineCamera.Root.transform, false);
obj2.transform.localPosition = new Vector3(0f, 0f, 0.19f);
obj2.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
obj2.transform.localScale = new Vector3(0.07f, 0.045f, 0.07f);
Collider component2 = obj2.GetComponent<Collider>();
if ((Object)(object)component2 != (Object)null)
{
Object.Destroy((Object)(object)component2);
}
GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)val).name = "SideGrip";
val.transform.SetParent(cineCamera.Root.transform, false);
val.transform.localPosition = new Vector3(0.145f, -0.015f, -0.025f);
val.transform.localScale = new Vector3(0.055f, 0.115f, 0.18f);
cineCamera._sideGripPoint = val.transform;
GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)val2).name = "TopHandle";
val2.transform.SetParent(cineCamera.Root.transform, false);
val2.transform.localPosition = new Vector3(0f, 0.105f, -0.01f);
val2.transform.localScale = new Vector3(0.13f, 0.035f, 0.18f);
cineCamera._topGripPoint = val2.transform;
GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)obj3).name = "TopHandlePostA";
obj3.transform.SetParent(cineCamera.Root.transform, false);
obj3.transform.localPosition = new Vector3(0f, 0.068f, 0.055f);
obj3.transform.localScale = new Vector3(0.035f, 0.075f, 0.035f);
GameObject obj4 = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)obj4).name = "TopHandlePostB";
obj4.transform.SetParent(cineCamera.Root.transform, false);
obj4.transform.localPosition = new Vector3(0f, 0.068f, -0.075f);
obj4.transform.localScale = new Vector3(0.035f, 0.075f, 0.035f);
GameObject obj5 = GameObject.CreatePrimitive((PrimitiveType)2);
((Object)obj5).name = "RecordButton";
obj5.transform.SetParent(cineCamera.Root.transform, false);
obj5.transform.localPosition = new Vector3(0.178f, 0.025f, 0.055f);
obj5.transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
obj5.transform.localScale = new Vector3(0.018f, 0.01f, 0.018f);
Collider component3 = obj5.GetComponent<Collider>();
if ((Object)(object)component3 != (Object)null)
{
Object.Destroy((Object)(object)component3);
}
Renderer component4 = obj5.GetComponent<Renderer>();
if ((Object)(object)component4 != (Object)null)
{
component4.material.color = Color.red;
}
GameObject val3 = new GameObject("CaptureCamera");
val3.transform.SetParent(cineCamera.Root.transform, false);
val3.transform.localPosition = new Vector3(0f, 0f, 0.17f);
cineCamera.UnityCamera = val3.AddComponent<Camera>();
if ((Object)(object)Camera.main != (Object)null)
{
cineCamera.UnityCamera.CopyFrom(Camera.main);
}
cineCamera.UnityCamera.stereoTargetEye = (StereoTargetEyeMask)0;
((Behaviour)cineCamera.UnityCamera).enabled = false;
cineCamera.UnityCamera.fieldOfView = cineCamera.Fov;
cineCamera.Preview = new RenderTexture(640, 360, 16, (RenderTextureFormat)0);
((Object)cineCamera.Preview).name = name + "_Preview";
cineCamera.Preview.Create();
cineCamera.Monitor = GameObject.CreatePrimitive((PrimitiveType)5);
((Object)cineCamera.Monitor).name = "SelfieMonitor";
cineCamera.Monitor.transform.SetParent(cineCamera.Root.transform, false);
cineCamera.Monitor.transform.localPosition = new Vector3(0f, 0.09f, -0.18f);
cineCamera.Monitor.transform.localRotation = Quaternion.Euler(0f, 180f, 0f);
cineCamera.Monitor.transform.localScale = new Vector3(0.22f, 0.13f, 1f);
Collider component5 = cineCamera.Monitor.GetComponent<Collider>();
if ((Object)(object)component5 != (Object)null)
{
Object.Destroy((Object)(object)component5);
}
MeshRenderer component6 = cineCamera.Monitor.GetComponent<MeshRenderer>();
if ((Object)(object)component6 != (Object)null)
{
Shader val4 = Shader.Find("Unlit/Texture") ?? Shader.Find("Sprites/Default");
((Renderer)component6).material = new Material(val4);
((Renderer)component6).material.mainTexture = (Texture)(object)cineCamera.Preview;
((Renderer)component6).material.mainTextureScale = Vector2.one;
((Renderer)component6).material.mainTextureOffset = Vector2.zero;
}
GameObject val5 = new GameObject("MonitorRECStatus");
val5.transform.SetParent(cineCamera.Monitor.transform, false);
val5.transform.localPosition = new Vector3(-0.43f, 0.33f, -0.01f);
val5.transform.localRotation = Quaternion.identity;
val5.transform.localScale = Vector3.one * 0.06f;
cineCamera.MonitorStatusText = val5.AddComponent<TextMesh>();
cineCamera.MonitorStatusText.anchor = (TextAnchor)0;
cineCamera.MonitorStatusText.alignment = (TextAlignment)0;
cineCamera.MonitorStatusText.fontSize = 48;
cineCamera.MonitorStatusText.characterSize = 0.18f;
cineCamera.MonitorStatusText.color = Color.white;
cineCamera.MonitorStatusText.text = "STBY 00:00:00";
GameObject val6 = new GameObject("MonitorViewMode");
val6.transform.SetParent(cineCamera.Monitor.transform, false);
val6.transform.localPosition = new Vector3(0.43f, 0.33f, -0.01f);
val6.transform.localRotation = Quaternion.identity;
val6.transform.localScale = Vector3.one * 0.06f;
cineCamera.MonitorModeText = val6.AddComponent<TextMesh>();
cineCamera.MonitorModeText.anchor = (TextAnchor)2;
cineCamera.MonitorModeText.alignment = (TextAlignment)2;
cineCamera.MonitorModeText.fontSize = 48;
cineCamera.MonitorModeText.characterSize = 0.18f;
cineCamera.MonitorModeText.color = Color.white;
cineCamera.MonitorModeText.text = "VIEW";
cineCamera._baseLocalPos = ((Component)cineCamera.UnityCamera).transform.localPosition;
cineCamera._baseLocalRot = ((Component)cineCamera.UnityCamera).transform.localRotation;
return cineCamera;
}
public void ApplyPreset(CameraPreset preset)
{
Preset = preset;
switch (preset)
{
case CameraPreset.Action:
Fov = 82f;
PositionSmooth = 4f;
RotationSmooth = 5f;
Shake = 0.015f;
break;
case CameraPreset.Smooth:
Fov = 65f;
PositionSmooth = 14f;
RotationSmooth = 16f;
Shake = 0f;
break;
case CameraPreset.Handheld:
Fov = 72f;
PositionSmooth = 7f;
RotationSmooth = 8f;
Shake = 0.012f;
break;
case CameraPreset.Tripod:
Fov = 55f;
PositionSmooth = 30f;
RotationSmooth = 30f;
Shake = 0f;
break;
case CameraPreset.Drone:
Fov = 75f;
PositionSmooth = 10f;
RotationSmooth = 12f;
Shake = 0.003f;
break;
case CameraPreset.Orbit:
Fov = 62f;
PositionSmooth = 12f;
RotationSmooth = 15f;
Shake = 0f;
break;
case CameraPreset.Chase:
Fov = 78f;
PositionSmooth = 6f;
RotationSmooth = 9f;
Shake = 0.006f;
break;
case CameraPreset.Bodycam:
Fov = 95f;
PositionSmooth = 2f;
RotationSmooth = 3f;
Shake = 0.022f;
break;
case CameraPreset.Selfie:
Fov = 74f;
PositionSmooth = 8f;
RotationSmooth = 10f;
Shake = 0.004f;
MonitorEnabled = true;
MirrorPreview = true;
break;
case CameraPreset.SlowPan:
Fov = 58f;
PositionSmooth = 18f;
RotationSmooth = 22f;
Shake = 0f;
break;
case CameraPreset.Dolly:
Fov = 52f;
PositionSmooth = 16f;
RotationSmooth = 18f;
Shake = 0f;
break;
}
RefreshMonitor();
}
public void Tick()
{
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
if (!_disposed && !((Object)(object)UnityCamera == (Object)null))
{
TickPhysicalControls();
UnityCamera.fieldOfView = Fov;
if (Shake > 0.0001f)
{
float num = Time.unscaledTime * 3.7f;
Vector3 val = new Vector3(Mathf.PerlinNoise(num, 1.1f) - 0.5f, Mathf.PerlinNoise(2.2f, num) - 0.5f, 0f) * Shake;
Vector3 val2 = new Vector3(Mathf.PerlinNoise(num, 5.5f) - 0.5f, Mathf.PerlinNoise(7.7f, num) - 0.5f, Mathf.PerlinNoise(num, 9.9f) - 0.5f) * (Shake * 45f);
((Component)UnityCamera).transform.localPosition = _baseLocalPos + val;
((Component)UnityCamera).transform.localRotation = _baseLocalRot * Quaternion.Euler(val2);
}
else
{
((Component)UnityCamera).transform.localPosition = _baseLocalPos;
((Component)UnityCamera).transform.localRotation = _baseLocalRot;
}
if (MonitorEnabled && (Object)(object)Preview != (Object)null)
{
RenderTexture targetTexture = UnityCamera.targetTexture;
UnityCamera.targetTexture = Preview;
UnityCamera.Render();
UnityCamera.targetTexture = targetTexture;
}
UpdateMonitorOverlay();
}
}
private void TickPhysicalControls()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Invalid comparison between Unknown and I4
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Invalid comparison between Unknown and I4
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
InputDevice deviceAtXRNode = InputDevices.GetDeviceAtXRNode((XRNode)4);
InputDevice deviceAtXRNode2 = InputDevices.GetDeviceAtXRNode((XRNode)5);
bool flag = ReadButton(deviceAtXRNode, CommonUsages.gripButton);
bool flag2 = ReadButton(deviceAtXRNode2, CommonUsages.gripButton);
if (!_heldBy.HasValue)
{
TryBeginHold((XRNode)4, deviceAtXRNode, flag, _lastGripPressedLeft);
if (!_heldBy.HasValue)
{
TryBeginHold((XRNode)5, deviceAtXRNode2, flag2, _lastGripPressedRight);
}
}
else
{
XRNode value = _heldBy.Value;
InputDevice device = (((int)value == 4) ? deviceAtXRNode : deviceAtXRNode2);
if (!(((int)value == 4) ? flag : flag2))
{
_heldBy = null;
_lastTriggerPressed = false;
if ((Object)(object)_rigidbody != (Object)null)
{
_rigidbody.isKinematic = false;
}
}
else
{
Vector3 val = default(Vector3);
Quaternion val2 = default(Quaternion);
if (((InputDevice)(ref device)).TryGetFeatureValue(CommonUsages.devicePosition, ref val) && ((InputDevice)(ref device)).TryGetFeatureValue(CommonUsages.deviceRotation, ref val2))
{
if ((Object)(object)_rigidbody != (Object)null)
{
_rigidbody.isKinematic = true;
}
Root.transform.position = val + val2 * new Vector3(0f, -0.035f, 0.08f);
Root.transform.rotation = val2;
}
bool flag3 = ReadButton(device, CommonUsages.triggerButton);
if (flag3 && !_lastTriggerPressed)
{
CineCamMod instance = CineCamMod.Instance;
if (instance != null)
{
if (instance.Recorder.IsRecording)
{
instance.Recorder.Stop();
CineCamMod.Notify(instance.Recorder.Status);
}
else
{
instance.Recorder.Start(this, instance.Video);
CineCamMod.Notify(instance.Recorder.Status);
}
}
}
_lastTriggerPressed = flag3;
}
}
_lastGripPressedLeft = flag;
_lastGripPressedRight = flag2;
}
private void TryBeginHold(XRNode node, InputDevice device, bool grip, bool previousGrip)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = default(Vector3);
if (!grip || previousGrip || !((InputDevice)(ref device)).isValid || !((InputDevice)(ref device)).TryGetFeatureValue(CommonUsages.devicePosition, ref val))
{
return;
}
float num = (((Object)(object)_sideGripPoint != (Object)null) ? Vector3.Distance(val, _sideGripPoint.position) : 999f);
float num2 = (((Object)(object)_topGripPoint != (Object)null) ? Vector3.Distance(val, _topGripPoint.position) : 999f);
if (!(Mathf.Min(num, num2) > 0.18f))
{
_heldBy = node;
_lastTriggerPressed = ReadButton(device, CommonUsages.triggerButton);
if ((Object)(object)_rigidbody != (Object)null)
{
_rigidbody.velocity = Vector3.zero;
_rigidbody.angularVelocity = Vector3.zero;
_rigidbody.isKinematic = true;
}
}
}
private static bool ReadButton(InputDevice device, InputFeatureUsage<bool> usage)
{
bool flag = default(bool);
return ((InputDevice)(ref device)).isValid && ((InputDevice)(ref device)).TryGetFeatureValue(usage, ref flag) && flag;
}
public void SetRecordingState(bool recording)
{
_recording = recording;
if (recording)
{
_recordingStartedAt = Time.unscaledTime;
}
UpdateMonitorOverlay();
}
private void UpdateMonitorOverlay()
{
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)MonitorStatusText != (Object)null)
{
int num = Mathf.FloorToInt(_recording ? Mathf.Max(0f, Time.unscaledTime - _recordingStartedAt) : 0f);
int value = num / 3600;
int value2 = num % 3600 / 60;
int value3 = num % 60;
MonitorStatusText.color = (_recording ? Color.red : Color.white);
MonitorStatusText.text = (_recording ? "● REC " : "STBY ") + $"{value:00}:{value2:00}:{value3:00}";
}
if ((Object)(object)MonitorModeText != (Object)null)
{
MonitorModeText.text = (MirrorPreview ? "MIRROR" : "VIEW");
}
}
public void RefreshMonitor()
{
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Monitor != (Object)null)
{
Monitor.SetActive(MonitorEnabled);
}
MeshRenderer val = (((Object)(object)Monitor != (Object)null) ? Monitor.GetComponent<MeshRenderer>() : null);
if ((Object)(object)val != (Object)null && (Object)(object)((Renderer)val).material != (Object)null)
{
((Renderer)val).material.mainTextureScale = (Vector2)(MirrorPreview ? new Vector2(-1f, 1f) : Vector2.one);
((Renderer)val).material.mainTextureOffset = (Vector2)(MirrorPreview ? new Vector2(1f, 0f) : Vector2.zero);
}
UpdateMonitorOverlay();
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
if ((Object)(object)Preview != (Object)null)
{
Preview.Release();
Object.Destroy((Object)(object)Preview);
}
if ((Object)(object)Root != (Object)null)
{
Object.Destroy((Object)(object)Root);
}
}
}
}
public sealed class Recorder
{
private CineCamera _bound;
private VideoSettings _settings;
private RenderTexture _capture;
private Texture2D _readback;
private float _nextFrame;
private long _frameIndex;
private QuestVideoEncoder _encoder;
public bool IsRecording { get; private set; }
public string Status { get; private set; } = "Idle";
public void Start(CineCamera camera, VideoSettings settings)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
if (IsRecording || camera == null)
{
return;
}
try
{
_bound = camera;
_settings = settings;
Directory.CreateDirectory("/sdcard/Movies/CineCamUnlimited/");
string text = "CineCam_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".mp4";
string path = "/sdcard/Movies/CineCamUnlimited/" + text;
_capture = new RenderTexture(settings.Width, settings.Height, 0, (RenderTextureFormat)0);
_capture.Create();
_readback = new Texture2D(settings.Width, settings.Height, (TextureFormat)4, false, false);
_encoder = new QuestVideoEncoder();
_encoder.Start(path, settings.Width, settings.Height, settings.Fps, (int)(settings.BitrateMbps * 1000000f));
_frameIndex = 0L;
_nextFrame = Time.unscaledTime;
IsRecording = true;
_bound.SetRecordingState(recording: true);
Status = $"REC {settings.Width}x{settings.Height} {settings.Fps}fps {settings.BitrateMbps:0.#}Mbps";
}
catch (Exception ex)
{
Status = "Start failed: " + ex.Message;
EmergencyStop();
}
}
public void Tick(CineCamera active, VideoSettings settings)
{
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
if (!IsRecording || _bound == null || _encoder == null)
{
return;
}
float num = 1f / (float)Mathf.Max(1, _settings.Fps);
if (Time.unscaledTime < _nextFrame)
{
return;
}
_nextFrame += num;
if (Time.unscaledTime - _nextFrame > num * 3f)
{
_nextFrame = Time.unscaledTime + num;
}
try
{
Camera unityCamera = _bound.UnityCamera;
RenderTexture targetTexture = unityCamera.targetTexture;
RenderTexture active2 = RenderTexture.active;
unityCamera.targetTexture = _capture;
unityCamera.Render();
RenderTexture.active = _capture;
_readback.ReadPixels(new Rect(0f, 0f, (float)_settings.Width, (float)_settings.Height), 0, 0, false);
_readback.Apply(false, false);
byte[] rgba = Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)_readback.GetRawTextureData());
long ptsUs = _frameIndex * 1000000 / Math.Max(1, _settings.Fps);
_encoder.PushRgba(rgba, ptsUs);
_frameIndex++;
unityCamera.targetTexture = targetTexture;
RenderTexture.active = active2;
Status = $"REC {(float)_frameIndex / (float)_settings.Fps:0.0}s | {_settings.Width}x{_settings.Height}";
}
catch (Exception ex)
{
Status = "Recording error: " + ex.Message;
EmergencyStop();
}
}
public void Stop()
{
if (IsRecording)
{
try
{
_encoder?.Stop();
}
catch (Exception ex)
{
Status = "Finalize error: " + ex.Message;
}
Cleanup();
if (!Status.StartsWith("Finalize error"))
{
Status = "Saved recording.";
}
}
}
public void EmergencyStop()
{
try
{
_encoder?.Abort();
}
catch
{
}
Cleanup();
if (Status == null || Status == "Idle")
{
Status = "Stopped.";
}
}
private void Cleanup()
{
if (_bound != null)
{
_bound.SetRecordingState(recording: false);
}
IsRecording = false;
_bound = null;
_settings = null;
_encoder = null;
if ((Object)(object)_capture != (Object)null)
{
_capture.Release();
Object.Destroy((Object)(object)_capture);
_capture = null;
}
if ((Object)(object)_readback != (Object)null)
{
Object.Destroy((Object)(object)_readback);
_readback = null;
}
}
}
public sealed class QuestVideoEncoder
{
private const string MimeAvc = "video/avc";
private const int ConfigureFlagEncode = 1;
private const int ColorFormatYuv420SemiPlanar = 21;
private const int BufferFlagCodecConfig = 2;
private const int BufferFlagEndOfStream = 4;
private const int InfoTryAgainLater = -1;
private const int InfoOutputFormatChanged = -2;
private AndroidJavaObject _codec;
private AndroidJavaObject _muxer;
private AndroidJavaObject _bufferInfo;
private bool _codecStarted;
private bool _muxerStarted;
private bool _started;
private int _trackIndex = -1;
private int _width;
private int _height;
private long _lastPtsUs;
private byte[] _nv12;
public void Start(string path, int width, int height, int fps, int bitrate)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Expected O, but got Unknown
//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
//IL_02ab: Expected O, but got Unknown
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Expected O, but got Unknown
if ((int)Application.platform != 11)
{
throw new PlatformNotSupportedException("CineCam recording requires Android/Quest. Runtime platform: " + ((object)Application.platform/*cast due to .constrained prefix*/).ToString());
}
if ((width & 1) != 0 || (height & 1) != 0)
{
throw new ArgumentException("Video width and height must be even for YUV420 encoding.");
}
_width = width;
_height = height;
_lastPtsUs = 0L;
_nv12 = new byte[width * height * 3 / 2];
try
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
AndroidJavaClass val = new AndroidJavaClass("android.media.MediaFormat");
AndroidJavaObject val2 = null;
try
{
val2 = ((AndroidJavaObject)val).CallStatic<AndroidJavaObject>("createVideoFormat", (Object[])(object)new Object[3]
{
Object.op_Implicit("video/avc"),
Object.op_Implicit(width),
Object.op_Implicit(height)
});
}
finally
{
try
{
((AndroidJavaObject)val).Dispose();
}
catch
{
}
}
if (val2 == null)
{
throw new Exception("MediaFormat.createVideoFormat returned null.");
}
try
{
val2.Call("setInteger", (Object[])(object)new Object[2]
{
Object.op_Implicit("color-format"),
Object.op_Implicit(21)
});
val2.Call("setInteger", (Object[])(object)new Object[2]
{
Object.op_Implicit("bitrate"),
Object.op_Implicit(bitrate)
});
val2.Call("setInteger", (Object[])(object)new Object[2]
{
Object.op_Implicit("frame-rate"),
Object.op_Implicit(fps)
});
val2.Call("setInteger", (Object[])(object)new Object[2]
{
Object.op_Implicit("i-frame-interval"),
Object.op_Implicit(1)
});
AndroidJavaClass val3 = new AndroidJavaClass("android.media.MediaCodec");
try
{
_codec = ((AndroidJavaObject)val3).CallStatic<AndroidJavaObject>("createEncoderByType", (Object[])(object)new Object[1] { Object.op_Implicit("video/avc") });
}
finally
{
try
{
((AndroidJavaObject)val3).Dispose();
}
catch
{
}
}
if (_codec == null)
{
throw new Exception("MediaCodec.createEncoderByType(video/avc) returned null.");
}
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.configure().");
}
jvalue[] array = (jvalue[])(object)new jvalue[4];
array[0].l = val2.GetRawObject();
array[1].l = IntPtr.Zero;
array[2].l = IntPtr.Zero;
array[3].i = 1;
AndroidJNI.CallVoidMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
_codec.Call("start", (Il2CppReferenceArray<Object>)null);
_codecStarted = true;
}
finally
{
try
{
val2.Dispose();
}
catch
{
}
}
_muxer = new AndroidJavaObject("android.media.MediaMuxer", (Object[])(object)new Object[2]
{
Object.op_Implicit(path),
Object.op_Implicit(0)
});
_bufferInfo = new AndroidJavaObject("android.media.MediaCodec$BufferInfo", (Il2CppReferenceArray<Object>)null);
if (_muxer == null || _bufferInfo == null)
{
throw new Exception("Could not create MediaMuxer or MediaCodec.BufferInfo.");
}
_trackIndex = -1;
_muxerStarted = false;
_started = true;
}
catch (Exception ex)
{
Abort();
throw new Exception("Direct Quest MediaCodec encoder failed to start: " + ex.Message);
}
}
public void PushRgba(byte[] rgba, long ptsUs)
{
if (!_started || !_codecStarted || _codec == null || rgba == null)
{
return;
}
int num = _width * _height * 4;
if (rgba.Length < num)
{
throw new ArgumentException("RGBA frame is smaller than expected.");
}
RgbaToNv12Flipped(rgba, _nv12, _width, _height);
_lastPtsUs = ptsUs;
int num2 = DequeueInputBuffer(10000L);
if (num2 >= 0)
{
IntPtr codecBuffer = GetCodecBuffer("getInputBuffer", num2);
if (codecBuffer == IntPtr.Zero)
{
throw new Exception("MediaCodec.getInputBuffer returned null.");
}
try
{
PutBytesIntoByteBuffer(codecBuffer, _nv12);
QueueInputBuffer(num2, _nv12.Length, ptsUs, 0);
}
finally
{
AndroidJNI.DeleteLocalRef(codecBuffer);
}
}
DrainEncoder(endOfStream: false);
}
public void Stop()
{
if (!_started)
{
ReleaseAll();
return;
}
try
{
int num = -1;
for (int i = 0; i < 50; i++)
{
if (num >= 0)
{
break;
}
num = DequeueInputBuffer(10000L);
}
if (num >= 0)
{
QueueInputBuffer(num, 0, _lastPtsUs + 1, 4);
}
DrainEncoder(endOfStream: true);
}
finally
{
ReleaseAll();
}
}
public void Abort()
{
ReleaseAll();
}
private int DequeueInputBuffer(long timeoutUs)
{
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "dequeueInputBuffer", "(J)I");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.dequeueInputBuffer().");
}
jvalue[] array = (jvalue[])(object)new jvalue[1];
array[0].j = timeoutUs;
return AndroidJNI.CallIntMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private IntPtr GetCodecBuffer(string methodName, int index)
{
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), methodName, "(I)Ljava/nio/ByteBuffer;");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec." + methodName + "().");
}
jvalue[] array = (jvalue[])(object)new jvalue[1];
array[0].i = index;
return AndroidJNI.CallObjectMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private void QueueInputBuffer(int index, int size, long ptsUs, int flags)
{
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "queueInputBuffer", "(IIIJI)V");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.queueInputBuffer().");
}
jvalue[] array = (jvalue[])(object)new jvalue[5];
array[0].i = index;
array[1].i = 0;
array[2].i = size;
array[3].j = ptsUs;
array[4].i = flags;
AndroidJNI.CallVoidMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private void DrainEncoder(bool endOfStream)
{
if (_codec == null || _bufferInfo == null)
{
return;
}
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.dequeueOutputBuffer().");
}
int num = (endOfStream ? 400 : 32);
for (int i = 0; i < num; i++)
{
jvalue[] array = (jvalue[])(object)new jvalue[2];
array[0].l = _bufferInfo.GetRawObject();
array[1].j = (endOfStream ? 10000 : 0);
int num2 = AndroidJNI.CallIntMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
if (num2 == -1)
{
if (!endOfStream)
{
break;
}
}
else if (num2 == -2)
{
if (_muxerStarted)
{
throw new Exception("MediaCodec output format changed twice.");
}
IntPtr codecOutputFormat = GetCodecOutputFormat();
try
{
_trackIndex = AddMuxerTrack(codecOutputFormat);
_muxer.Call("start", (Il2CppReferenceArray<Object>)null);
_muxerStarted = true;
}
finally
{
if (codecOutputFormat != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(codecOutputFormat);
}
}
}
else
{
if (num2 < 0)
{
continue;
}
int num3 = _bufferInfo.Get<int>("offset");
int num4 = _bufferInfo.Get<int>("size");
int num5 = _bufferInfo.Get<int>("flags");
if ((num5 & 2) != 0)
{
num4 = 0;
}
if (num4 > 0)
{
if (!_muxerStarted)
{
throw new Exception("Encoded video arrived before MediaMuxer started.");
}
IntPtr codecBuffer = GetCodecBuffer("getOutputBuffer", num2);
if (codecBuffer == IntPtr.Zero)
{
throw new Exception("MediaCodec.getOutputBuffer returned null.");
}
try
{
SetByteBufferPositionLimit(codecBuffer, num3, num3 + num4);
WriteMuxerSample(codecBuffer);
}
finally
{
AndroidJNI.DeleteLocalRef(codecBuffer);
}
}
ReleaseOutputBuffer(num2);
if ((num5 & 4) != 0)
{
break;
}
}
}
}
private IntPtr GetCodecOutputFormat()
{
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "getOutputFormat", "()Landroid/media/MediaFormat;");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.getOutputFormat().");
}
return AndroidJNI.CallObjectMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit((jvalue[])(object)new jvalue[0]));
}
private int AddMuxerTrack(IntPtr mediaFormat)
{
if (mediaFormat == IntPtr.Zero)
{
throw new Exception("Output MediaFormat is null.");
}
IntPtr methodID = AndroidJNI.GetMethodID(_muxer.GetRawClass(), "addTrack", "(Landroid/media/MediaFormat;)I");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaMuxer.addTrack().");
}
jvalue[] array = (jvalue[])(object)new jvalue[1];
array[0].l = mediaFormat;
return AndroidJNI.CallIntMethod(_muxer.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private void WriteMuxerSample(IntPtr byteBuffer)
{
IntPtr methodID = AndroidJNI.GetMethodID(_muxer.GetRawClass(), "writeSampleData", "(ILjava/nio/ByteBuffer;Landroid/media/MediaCodec$BufferInfo;)V");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaMuxer.writeSampleData().");
}
jvalue[] array = (jvalue[])(object)new jvalue[3];
array[0].i = _trackIndex;
array[1].l = byteBuffer;
array[2].l = _bufferInfo.GetRawObject();
AndroidJNI.CallVoidMethod(_muxer.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private void ReleaseOutputBuffer(int index)
{
IntPtr methodID = AndroidJNI.GetMethodID(_codec.GetRawClass(), "releaseOutputBuffer", "(IZ)V");
if (methodID == IntPtr.Zero)
{
throw new Exception("Could not resolve MediaCodec.releaseOutputBuffer().");
}
jvalue[] array = (jvalue[])(object)new jvalue[2];
array[0].i = index;
array[1].z = false;
AndroidJNI.CallVoidMethod(_codec.GetRawObject(), methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
}
private static void PutBytesIntoByteBuffer(IntPtr byteBuffer, byte[] bytes)
{
IntPtr objectClass = AndroidJNI.GetObjectClass(byteBuffer);
IntPtr intPtr = IntPtr.Zero;
try
{
IntPtr methodID = AndroidJNI.GetMethodID(objectClass, "clear", "()Ljava/nio/Buffer;");
if (methodID != IntPtr.Zero)
{
IntPtr intPtr2 = AndroidJNI.CallObjectMethod(byteBuffer, methodID, Il2CppStructArray<jvalue>.op_Implicit((jvalue[])(object)new jvalue[0]));
if (intPtr2 != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(intPtr2);
}
}
sbyte[] array = new sbyte[bytes.Length];
Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length);
intPtr = AndroidJNI.ToSByteArray(Il2CppStructArray<sbyte>.op_Implicit(array));
IntPtr methodID2 = AndroidJNI.GetMethodID(objectClass, "put", "([B)Ljava/nio/ByteBuffer;");
if (methodID2 == IntPtr.Zero)
{
throw new Exception("Could not resolve ByteBuffer.put(byte[]).");
}
jvalue[] array2 = (jvalue[])(object)new jvalue[1];
array2[0].l = intPtr;
IntPtr intPtr3 = AndroidJNI.CallObjectMethod(byteBuffer, methodID2, Il2CppStructArray<jvalue>.op_Implicit(array2));
if (intPtr3 != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(intPtr3);
}
}
finally
{
if (intPtr != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(intPtr);
}
if (objectClass != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(objectClass);
}
}
}
private static void SetByteBufferPositionLimit(IntPtr byteBuffer, int position, int limit)
{
IntPtr objectClass = AndroidJNI.GetObjectClass(byteBuffer);
try
{
IntPtr methodID = AndroidJNI.GetMethodID(objectClass, "position", "(I)Ljava/nio/Buffer;");
IntPtr methodID2 = AndroidJNI.GetMethodID(objectClass, "limit", "(I)Ljava/nio/Buffer;");
if (methodID == IntPtr.Zero || methodID2 == IntPtr.Zero)
{
throw new Exception("Could not resolve ByteBuffer position/limit methods.");
}
jvalue[] array = (jvalue[])(object)new jvalue[1];
array[0].i = position;
IntPtr intPtr = AndroidJNI.CallObjectMethod(byteBuffer, methodID, Il2CppStructArray<jvalue>.op_Implicit(array));
if (intPtr != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(intPtr);
}
jvalue[] array2 = (jvalue[])(object)new jvalue[1];
array2[0].i = limit;
IntPtr intPtr2 = AndroidJNI.CallObjectMethod(byteBuffer, methodID2, Il2CppStructArray<jvalue>.op_Implicit(array2));
if (intPtr2 != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(intPtr2);
}
}
finally
{
if (objectClass != IntPtr.Zero)
{
AndroidJNI.DeleteLocalRef(objectClass);
}
}
}
private void ReleaseAll()
{
_started = false;
if (_codec != null)
{
try
{
if (_codecStarted)
{
_codec.Call("stop", (Il2CppReferenceArray<Object>)null);
}
}
catch
{
}
try
{
_codec.Call("release", (Il2CppReferenceArray<Object>)null);
}
catch
{
}
try
{
_codec.Dispose();
}
catch
{
}
}
_codec = null;
_codecStarted = false;
if (_muxer != null)
{
try
{
if (_muxerStarted)
{
_muxer.Call("stop", (Il2CppReferenceArray<Object>)null);
}
}
catch
{
}
try
{
_muxer.Call("release", (Il2CppReferenceArray<Object>)null);
}
catch
{
}
try
{
_muxer.Dispose();
}
catch
{
}
}
_muxer = null;
_muxerStarted = false;
_trackIndex = -1;
if (_bufferInfo != null)
{
try
{
_bufferInfo.Dispose();
}
catch
{
}
_bufferInfo = null;
}
_nv12 = null;
}
private static void RgbaToNv12Flipped(byte[] rgba, byte[] nv12, int width, int height)
{
int num = width * height;
for (int i = 0; i < height; i++)
{
int num2 = (height - 1 - i) * width * 4;
int num3 = i * width;
for (int j = 0; j < width; j++)
{
int num4 = num2 + j * 4;
int num5 = rgba[num4];
int num6 = rgba[num4 + 1];
int num7 = rgba[num4 + 2];
int value = (66 * num5 + 129 * num6 + 25 * num7 + 128 >> 8) + 16;
nv12[num3 + j] = (byte)ClampByte(value);
}
}
int num8 = num;
for (int k = 0; k < height; k += 2)
{
int y = height - 1 - k;
int y2 = Math.Max(0, height - 2 - k);
for (int l = 0; l < width; l += 2)
{
int r = 0;
int g = 0;
int b = 0;
AddRgb(rgba, width, y, l, ref r, ref g, ref b);
AddRgb(rgba, width, y, Math.Min(l + 1, width - 1), ref r, ref g, ref b);
AddRgb(rgba, width, y2, l, ref r, ref g, ref b);
AddRgb(rgba, width, y2, Math.Min(l + 1, width - 1), ref r, ref g, ref b);
int num9 = r >> 2;
int num10 = g >> 2;
int num11 = b >> 2;
int value2 = (-38 * num9 - 74 * num10 + 112 * num11 + 128 >> 8) + 128;
int value3 = (112 * num9 - 94 * num10 - 18 * num11 + 128 >> 8) + 128;
nv12[num8++] = (byte)ClampByte(value2);
nv12[num8++] = (byte)ClampByte(value3);
}
}
}
private static void AddRgb(byte[] rgba, int width, int y, int x, ref int r, ref int g, ref int b)
{
int num = (y * width + x) * 4;
r += rgba[num];
g += rgba[num + 1];
b += rgba[num + 2];
}
private static int ClampByte(int value)
{
if (value < 0)
{
return 0;
}
if (value > 255)
{
return 255;
}
return value;
}
}
}