// 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; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using Intel.RealSense.Base; using System.Reflection; public interface IProcessingBlock : IOptions { Frame Process(Frame original); } /// /// Base class for processing blocks /// public class ProcessingBlock : Base.Object, IProcessingBlock { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly FrameQueue queue = new FrameQueue(1); /// public IOptionsContainer Options { get; private set; } public InfoCollection Info { get; private set; } /// /// Gets the internal queue /// public FrameQueue Queue { get { return queue; } } /// /// Initializes a new instance of the class. /// /// Starts the processing block directing it's output to the /// /// /// native rs2_processing_block* pointer public ProcessingBlock(IntPtr ptr) : base(ptr, NativeMethods.rs2_delete_processing_block) { object error; Options = new OptionsList(Handle); Info = new InfoCollection(NativeMethods.rs2_supports_processing_block_info, NativeMethods.rs2_get_processing_block_info, Handle); NativeMethods.rs2_start_processing_queue(Handle, queue.Handle, out error); } /// /// Process frame and return the result /// /// Frame to process /// Processed frame public Frame Process(Frame original) { return Process(original); } /// /// Process frame and return the result /// /// Type of frame to return /// Frame to process /// Processed frame /// Thrown when errors occur during processing public T Process(Frame original) where T : Frame { object error; NativeMethods.rs2_frame_add_ref(original.Handle, out error); NativeMethods.rs2_process_frame(Handle, original.Handle, out error); T f; if (queue.PollForFrame(out f)) { return f; } // this occurs when the sdk runs out of frame resources and allocate_video_frame fails // sadly, that exception doesn't propagate here... // usually a sign of not properly disposing of frames throw new InvalidOperationException($"Error while running {GetType().Name} processing block, check the log for info"); } protected override void Dispose(bool disposing) { queue.Dispose(); (Options as OptionsList).Dispose(); base.Dispose(disposing); } /// Test if the given processing block can be extended to the requested extension /// The extension to which the processing block should be tested if it is extendable /// iff the processing block can be extended to the given extension public bool Is(Extension extension) { object error; return NativeMethods.rs2_is_processing_block_extendable_to(Handle, extension, out error) > 0; } /// Cast to a strongly-typed subclass /// type or subclass /// an instance of public T As() where T : ProcessingBlock { return (T)Activator.CreateInstance( typeof(T), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new object[] { Handle }, null); } } public static class IProcessingBlockExtensions { public static Frame ApplyFilter(this Frame frame, IProcessingBlock block) { return block.Process(frame); } } }