// Copyright (c) 2021 homuler // // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. using System; using System.Collections; using UnityEngine; using UnityEngine.Experimental.Rendering; namespace Mediapipe.Unity { public abstract class ImageSource : MonoBehaviour { [Serializable] public struct ResolutionStruct { public int width; public int height; public double frameRate; public ResolutionStruct(int width, int height, double frameRate) { this.width = width; this.height = height; this.frameRate = frameRate; } public ResolutionStruct(Resolution resolution) { width = resolution.width; height = resolution.height; frameRate = resolution.refreshRate; } public Resolution ToResolution() { return new Resolution() { width = width, height = height, refreshRate = (int)frameRate }; } public override string ToString() { var aspectRatio = $"{width}x{height}"; var frameRateStr = frameRate.ToString("#.##"); return frameRate > 0 ? $"{aspectRatio} ({frameRateStr}Hz)" : aspectRatio; } } public ResolutionStruct resolution { get; protected set; } /// /// To call this method, the image source must be prepared. /// /// /// that is compatible with the current texture. /// public TextureFormat textureFormat => isPrepared ? TextureFormatFor(GetCurrentTexture()) : throw new InvalidOperationException("ImageSource is not prepared"); public virtual int textureWidth => resolution.width; public virtual int textureHeight => resolution.height; /// /// If does not support frame rate, it returns zero. /// public virtual double frameRate => resolution.frameRate; public float focalLengthPx { get; } = 2.0f; // TODO: calculate at runtime public virtual bool isHorizontallyFlipped { get; set; } = false; public virtual bool isVerticallyFlipped { get; } = false; public virtual bool isFrontFacing { get; } = false; public virtual RotationAngle rotation { get; } = RotationAngle.Rotation0; public abstract string sourceName { get; } public abstract string[] sourceCandidateNames { get; } public abstract ResolutionStruct[] availableResolutions { get; } /// /// Once finishes successfully, it will become true. /// /// /// Returns if the image source is prepared. /// public abstract bool isPrepared { get; } public abstract bool isPlaying { get; } /// /// Choose the source from . /// /// /// You need to call for the change to take effect. /// /// The index of public abstract void SelectSource(int sourceId); /// /// Choose the resolution from . /// /// /// You need to call for the change to take effect. /// /// The index of public void SelectResolution(int resolutionId) { var resolutions = availableResolutions; if (resolutionId < 0 || resolutionId >= resolutions.Length) { throw new ArgumentException($"Invalid resolution ID: {resolutionId}"); } resolution = resolutions[resolutionId]; } /// /// Prepare image source. /// If is true, it will reset the image source. /// /// /// When it finishes successfully, will return true. /// /// public abstract IEnumerator Play(); /// /// Resume image source. /// If is true, it will do nothing. /// /// /// The image source has not been played. /// public abstract IEnumerator Resume(); /// /// Pause image source. /// If is false, it will do nothing. /// public abstract void Pause(); /// /// Stop image source. /// /// /// When it finishes successfully, will return false. /// public abstract void Stop(); /// /// To call this method, the image source must be prepared. /// /// /// that contains the current image. /// public abstract Texture GetCurrentTexture(); protected static TextureFormat TextureFormatFor(Texture texture) { return GraphicsFormatUtility.GetTextureFormat(texture.graphicsFormat); } } }