//----------------------------------------------------------------------------- // Copyright 2015-2024 RenderHeads Ltd. All rights reserved. //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using UnityEngine; namespace RenderHeads.Media.AVProVideo { public enum VideoRange { SDR, HLG, PQ } public enum CodecType: uint { ac_3 = 0x61632d33, alac = 0x616c6163, avc1 = 0x61766331, avc3 = 0x61766333, dvh1 = 0x64766831, dvhe = 0x64766865, ec_3 = 0x65632d33, fLaC = 0x664c6143, hev1 = 0x68657631, hvc1 = 0x68766331, mjpg = 0x6d6a7067, mp4a = 0x6d703461, stpp = 0x73747070, wvtt = 0x77767474, unknown = 0 } public class Variant { private int m_iId = -1; private int m_iWidth = 0; private int m_iHeight = 0; private int m_iPeakDataRate = 0; private int m_iAverageDataRate = 0; private CodecType m_VideoCodecType = CodecType.unknown; private float m_fFrameRate = 0; private VideoRange m_eVideoRange; private CodecType m_AudioCodecType = CodecType.unknown; public Variant( int iId, int iWidth, int iHeight, int iPeakDataRate, int iAverageDataRate = 0, CodecType videoCodecType = CodecType.unknown, float fFrameRate = 0, VideoRange eVideoRange = VideoRange.SDR, CodecType audioCodecType = CodecType.unknown ) { m_iId = iId; m_iWidth = iWidth; m_iHeight = iHeight; m_iPeakDataRate = iPeakDataRate; m_iAverageDataRate = iAverageDataRate; m_VideoCodecType = videoCodecType; m_fFrameRate = fFrameRate; m_eVideoRange = eVideoRange; m_AudioCodecType = audioCodecType; } public int Id { get { return m_iId; } } public int Width { get { return m_iWidth; } } public int Height { get { return m_iHeight; } } public int PeakDataRate { get { return m_iPeakDataRate; } } public int AverageDataRate { get { return m_iAverageDataRate; } } public float FrameRate { get { return m_fFrameRate; } } public VideoRange VideoRange { get { return m_eVideoRange; } } public CodecType VideoCodecType { get { return m_VideoCodecType; } } public string VideoCodecName { get { switch (m_VideoCodecType) { case CodecType.avc1: case CodecType.avc3: return "H264"; case CodecType.dvh1: case CodecType.dvhe: return "Dolby Vision"; case CodecType.hev1: case CodecType.hvc1: return "HEVC"; case CodecType.mjpg: return "MJPEG"; default: return ""; } } } public CodecType AudioCodecType { get { return m_AudioCodecType; } } public string AudioCodecName { get { switch (m_AudioCodecType) { case CodecType.ac_3: return "AC-3"; case CodecType.alac: return "Apple Lossless"; case CodecType.ec_3: return "EC-3"; case CodecType.fLaC: return "FLAC"; case CodecType.mp4a: // Could be something else but this is most likely, requires passing audio subtype return "AAC"; default: return ""; } } } private static Variant s_Auto = new Variant(-1, 0, 0, 0); public static Variant Auto { get { return s_Auto; } } } public interface IVariants: IEnumerable { int Count { get; } Variant Current { get; } Variant this[int index] { get; } Variant GetSelectedVariant(); void SelectVariant(Variant variant); } public partial class BaseMediaPlayer : IVariants { protected List<Variant> _variants = new List<Variant>(); public int Count { get { return _variants.Count; } } public Variant Current { get { return GetSelectedVariant(); } } public Variant this[int index] { get { return _variants[index]; } } public virtual IEnumerator GetEnumerator() { return _variants.GetEnumerator(); } public virtual Variant GetSelectedVariant() { return Variant.Auto; } public virtual void SelectVariant(Variant variant) { } protected virtual void UpdateVariants() { _variants.Clear(); int count = InternalGetVariantCount(); for (int i = 0; i < count; ++i) { Variant variant = InternalGetVariantAtIndex(i); if (variant != null) { _variants.Add(variant); } } // Sort the list by codec, then peak bitrate _variants.Sort( (x, y) => { int iReturn = x.VideoCodecType.CompareTo( y.VideoCodecType ); if( iReturn == 0 ) { iReturn = x.PeakDataRate.CompareTo( y.PeakDataRate ); } return iReturn; } ); } internal virtual int InternalGetVariantCount() { return 0; } internal virtual Variant InternalGetVariantAtIndex(int index) { return null; } } }