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