// License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2017 Intel Corporation. All Rights Reserved. namespace Intel.RealSense { using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; /// /// Base class for multiple frame extensions /// public class Frame : Base.PooledObject { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private static readonly Base.Deleter FrameReleaser = NativeMethods.rs2_release_frame; internal override void Initialize() { } internal Frame(IntPtr ptr) : base(ptr, FrameReleaser) { } /// /// Create a frame from a native pointer /// /// Native rs2_frame* pointer /// a new public static Frame Create(IntPtr ptr) { return Create(ptr); } /// /// Create a frame from a native pointer /// /// type or subclass /// Native rs2_frame* pointer /// a new public static T Create(IntPtr ptr) where T : Frame { return ObjectPool.Get(ptr); } /// Returns a strongly-typed clone /// type or subclass /// to clone /// an instance of public static T Create(Frame other) where T : Frame { object error; NativeMethods.rs2_frame_add_ref(other.Handle, out error); return ObjectPool.Get(other.Handle); } /// Test if the given frame can be extended to the requested extension /// The extension to which the frame should be tested if it is extendable /// iff the frame can be extended to the given extension public bool Is(Extension extension) { object error; return NativeMethods.rs2_is_frame_extendable_to(Handle, extension, out error) != 0; } /// Returns a strongly-typed clone /// type or subclass /// an instance of public T As() where T : Frame { return Create(this); } /// Returns a strongly-typed clone, is disposed /// type or subclass /// an instance of public T Cast() where T : Frame { using (this) { return Create(this); } } /// /// Add a reference to this frame and return a clone, does not copy data /// /// A clone of this frame public Frame Clone() { object error; NativeMethods.rs2_frame_add_ref(Handle, out error); return Create(Handle); } /// communicate to the library you intend to keep the frame alive for a while /// /// this will remove the frame from the regular count of the frame pool /// /// /// /// once this function is called, the SDK can no longer guarantee 0-allocations during frame cycling /// public void Keep() { NativeMethods.rs2_keep_frame(Handle); } /// /// Gets a value indicating whether frame is a composite frame /// Shorthand for Is() /// /// /// if frame is a composite frame and false otherwise [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsComposite { get { return Is(Extension.CompositeFrame); } } /// Gets the size of the frame data /// The size of the frame data public int DataSize { get { object error; return NativeMethods.rs2_get_frame_data_size(Handle, out error); } } /// Gets a pointer to the frame data /// pointer to the start of the frame data public IntPtr Data { get { object error; return NativeMethods.rs2_get_frame_data(Handle, out error); } } /// /// Returns the stream profile that was used to start the stream of this frame /// /// StreamProfile or subclass type /// the stream profile that was used to start the stream of this frame public T GetProfile() where T : StreamProfile { object error; var ptr = NativeMethods.rs2_get_frame_stream_profile(Handle, out error); return StreamProfile.Create(ptr); } /// /// Gets the stream profile that was used to start the stream of this frame /// /// public StreamProfile Profile => GetProfile(); /// Gets the frame number of the frame /// the frame nubmer of the frame public ulong Number { get { object error; return NativeMethods.rs2_get_frame_number(Handle, out error); } } /// Gets timestamp from frame handle in milliseconds /// the timestamp of the frame in milliseconds public double Timestamp { get { object error; return NativeMethods.rs2_get_frame_timestamp(Handle, out error); } } /// Gets the sensor owning the frame /// the pointer to the sensor owning the frame public Sensor Sensor { get { object error; return Sensor.Create(NativeMethods.rs2_get_frame_sensor(Handle, out error)); } } /// Gets the timestamp domain from frame handle. timestamps can only be comparable if they are in common domain /// /// (for example, depth timestamp might come from system time while color timestamp might come from the device) /// this method is used to check if two timestamp values are comparable (generated from the same clock) /// /// the timestamp domain of the frame (camera / microcontroller / system time) public TimestampDomain TimestampDomain { get { object error; return NativeMethods.rs2_get_frame_timestamp_domain(Handle, out error); } } public long this[FrameMetadataValue frame_metadata] { get { return GetFrameMetadata(frame_metadata); } } /// retrieve metadata from frame handle /// the FrameMetadataValue whose latest frame we are interested in /// the metadata value public long GetFrameMetadata(FrameMetadataValue frame_metadata) { object error; return NativeMethods.rs2_get_frame_metadata(Handle, frame_metadata, out error); } /// determine device metadata /// the metadata to check for support /// true if device has this metadata public bool SupportsFrameMetaData(FrameMetadataValue frame_metadata) { object error; return NativeMethods.rs2_supports_frame_metadata(Handle, frame_metadata, out error) != 0; } #if DEBUGGER_METADATA private static readonly FrameMetadataValue[] MetadataValues = Enum.GetValues(typeof(FrameMetadataValue)) as FrameMetadataValue[]; public ICollection> MetaData { get { return MetadataValues .Where(m => SupportsFrameMetaData(m)) .Select(m => new KeyValuePair(m, GetFrameMetadata(m))) .ToArray(); } } #endif } }