// 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);
}
}
}