123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- #if UNITY_EDITOR
- using System;
- using System.Linq;
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEngine;
- using System.Reflection;
- namespace Unity.RenderStreaming.Editor
- {
- [CustomPropertyDrawer(typeof(CodecAttribute))]
- class CodecDrawer : PropertyDrawer
- {
- interface Codec
- {
- string name { get; }
- string mimeType { get; }
- string sdpFmtpLine { get; }
- int channelCount { get; }
- int sampleRate { get; }
- string optionTitle { get; }
- int order { get; }
- }
- class AudioCodec : Codec
- {
- public string name { get { return codec_.name; } }
- public string mimeType { get { return codec_.mimeType; } }
- public string sdpFmtpLine { get { return codec_.sdpFmtpLine; } }
- public int channelCount { get { return codec_.channelCount; } }
- public int sampleRate { get { return codec_.sampleRate; } }
- public string optionTitle
- {
- get
- {
- return $"{codec_.channelCount} channel";
- }
- }
- public int order { get { return codec_.channelCount; } }
- public AudioCodec(AudioCodecInfo codec)
- {
- codec_ = codec;
- }
- AudioCodecInfo codec_;
- }
- class VideoCodec : Codec
- {
- public string name { get { return codec_.name; } }
- public string mimeType { get { return codec_.mimeType; } }
- public string sdpFmtpLine { get { return codec_.sdpFmtpLine; } }
- public string optionTitle
- {
- get
- {
- switch(codec_)
- {
- case H264CodecInfo h264Codec:
- return $"{h264Codec.profile} Profile, Level {h264Codec.level.ToString().Insert(1, ".")}";
- case VP9CodecInfo vp9codec:
- return $"Profile {(int)vp9codec.profile}";
- case AV1CodecInfo av1codec:
- return $"Profile {(int)av1codec.profile}";
- }
- return null;
- }
- }
- public int channelCount { get { throw new NotSupportedException(); } }
- public int sampleRate { get { throw new NotSupportedException(); } }
- public int order
- {
- get
- {
- switch (codec_)
- {
- case H264CodecInfo h264Codec:
- return (int)h264Codec.profile;
- case VP9CodecInfo vp9codec:
- return (int)vp9codec.profile;
- case AV1CodecInfo av1codec:
- return (int)av1codec.profile;
- }
- return 0;
- }
- }
- public VideoCodec(VideoCodecInfo codec)
- {
- codec_ = codec;
- }
- VideoCodecInfo codec_;
- }
- SerializedProperty propertyMimeType;
- SerializedProperty propertySdpFmtpLine;
- SerializedProperty propertyChannelCount;
- SerializedProperty propertySampleRate;
- IEnumerable<Codec> codecs;
- string[] codecNames = new string[] { "Default" };
- string[] codecOptions = new string[] {};
- IEnumerable<Codec> selectedCodecs;
- GUIContent codecLabel;
- int selectCodecIndex = 0;
- int selectCodecOptionIndex = 0;
- bool hasCodecOptions = false;
- bool cache = false;
- bool changed = false;
- static readonly GUIContent s_audioCodecLabel =
- EditorGUIUtility.TrTextContent("Audio Codec", "Audio encoding codec.");
- static readonly GUIContent s_videoCodecLabel =
- EditorGUIUtility.TrTextContent("Video Codec", "Video encoding codec.");
- static IEnumerable<Codec> GetAvailableCodecs(UnityEngine.Object target)
- {
- if(target is VideoStreamSender)
- {
- return VideoStreamSender.GetAvailableCodecs().Select(codec => new VideoCodec(codec));
- }
- else if (target is VideoStreamReceiver)
- {
- return VideoStreamReceiver.GetAvailableCodecs().Select(codec => new VideoCodec(codec));
- }
- else if (target is AudioStreamSender)
- {
- return AudioStreamSender.GetAvailableCodecs().Select(codec => new AudioCodec(codec));
- }
- else if (target is AudioStreamReceiver)
- {
- return AudioStreamReceiver.GetAvailableCodecs().Select(codec => new AudioCodec(codec));
- }
- throw new ArgumentException();
- }
- static GUIContent GetCodecLabel(UnityEngine.Object target)
- {
- if (target is VideoStreamSender || target is VideoStreamReceiver)
- {
- return s_videoCodecLabel;
- }
- else if (target is AudioStreamSender || target is AudioStreamReceiver)
- {
- return s_audioCodecLabel;
- }
- throw new ArgumentException();
- }
- int FindOptionIndex(IEnumerable<Codec> codecs)
- {
- return Array.FindIndex(codecs.ToArray(), codec =>
- {
- if (codec is VideoCodec)
- return codec.sdpFmtpLine == propertySdpFmtpLine.stringValue;
- else
- return
- codec.sdpFmtpLine == propertySdpFmtpLine.stringValue &&
- codec.channelCount == propertyChannelCount.intValue &&
- codec.sampleRate == propertySampleRate.intValue;
- });
- }
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- if (!cache)
- {
- propertyMimeType = property.FindPropertyInChildren("m_MimeType");
- propertySdpFmtpLine = property.FindPropertyInChildren("m_SdpFmtpLine");
- propertyChannelCount = property.FindPropertyInChildren("m_ChannelCount");
- propertySampleRate = property.FindPropertyInChildren("m_SampleRate");
- codecs = GetAvailableCodecs(property.serializedObject.targetObject);
- codecNames = codecNames.Concat(codecs.Select(codec => codec.name)).Distinct().ToArray();
- var mimeType = propertyMimeType.stringValue;
- var codecName = mimeType.GetCodecName();
- selectedCodecs = codecs.Where(codec => codec.name == codecName).OrderBy(codec => codec.order);
- codecOptions = selectedCodecs.Select(codec => codec.optionTitle).ToArray();
- if (!selectedCodecs.Any())
- selectCodecIndex = 0;
- else
- selectCodecIndex = Array.FindIndex(codecNames, codec => codec == codecName);
- codecLabel = GetCodecLabel(property.serializedObject.targetObject);
- hasCodecOptions = codecOptions.Length > 1;
- if (hasCodecOptions)
- selectCodecOptionIndex = FindOptionIndex(selectedCodecs);
- cache = true;
- }
- var rect = position;
- rect.height = EditorGUIUtility.singleLineHeight;
- EditorGUI.BeginProperty(rect, label, propertyMimeType);
- rect = EditorGUI.PrefixLabel(rect, codecLabel);
- EditorGUI.BeginChangeCheck();
- selectCodecIndex = EditorGUI.Popup(rect, selectCodecIndex, codecNames);
- if (EditorGUI.EndChangeCheck())
- {
- if(0 < selectCodecIndex)
- {
- string codecName = codecNames[selectCodecIndex];
- selectedCodecs = codecs.Where(codec => codec.name == codecName).OrderBy(codec => codec.order);
- codecOptions = selectedCodecs.Select(codec => codec.optionTitle).ToArray();
- hasCodecOptions = codecOptions.Length > 1;
- var codec = selectedCodecs.First();
- propertyMimeType.stringValue = codec.mimeType;
- propertySdpFmtpLine.stringValue = codec.sdpFmtpLine;
- if(propertyChannelCount != null)
- propertyChannelCount.intValue = codec.channelCount;
- if (propertySampleRate != null)
- propertySampleRate.intValue = codec.sampleRate;
- }
- else
- {
- propertyMimeType.stringValue = null;
- propertySdpFmtpLine.stringValue = null;
- if (propertyChannelCount != null)
- propertyChannelCount.intValue = 0;
- if (propertySampleRate != null)
- propertySampleRate.intValue = 0;
- hasCodecOptions = false;
- }
- }
- EditorGUI.EndProperty();
- int codecIndex = selectCodecIndex - 1;
- if (0 < codecIndex)
- {
- if (hasCodecOptions && 0 < codecOptions.Length)
- {
- // sdp fmtp line
- rect.y += EditorGUIUtility.singleLineHeight;
- EditorGUI.BeginProperty(rect, label, propertySdpFmtpLine);
- EditorGUI.BeginChangeCheck();
- selectCodecOptionIndex = EditorGUI.Popup(rect, selectCodecOptionIndex, codecOptions);
- if (EditorGUI.EndChangeCheck())
- {
- var codec = selectedCodecs.ElementAt(selectCodecOptionIndex);
- propertySdpFmtpLine.stringValue = codec.sdpFmtpLine;
- if (propertyChannelCount != null)
- propertyChannelCount.intValue = codec.channelCount;
- if (propertySampleRate != null)
- propertySampleRate.intValue = codec.sampleRate;
- }
- EditorGUI.EndProperty();
- }
- }
- if (changed)
- {
- // todo: not supported changing codecs in play mode.
- //if (Application.isPlaying)
- //{
- // var objectReferenceValue = property.serializedObject.targetObject;
- // var type = objectReferenceValue.GetType();
- // var attribute = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
- // var methodName = "SetCodec";
- // var method = type.GetMethod(methodName, attribute);
- // method.Invoke(objectReferenceValue, new object[] { newValue });
- //}
- changed = false;
- }
- }
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- if (property == null)
- throw new System.ArgumentNullException(nameof(property));
- int lineCount = hasCodecOptions ? 2 : 1;
- return EditorGUIUtility.singleLineHeight * lineCount;
- }
- }
- }
- #endif
|