/// <summary> /// Constructor that Takes an IImage /// </summary> /// <param name="image"></param> /// <param name="clone"></param> /// <param name="aspectRatio"></param> /// <param name="fourCC"></param> /// <param name="frameRateNumerator"></param> /// <param name="frameRateDenominator"></param> /// <param name="format"></param> public VideoFrame(IImage image, bool clone, float aspectRatio, NDIlib.FourCC_type_e fourCC, int frameRateNumerator, int frameRateDenominator, NDIlib.frame_format_type_e format) { var ar = aspectRatio; if (ar <= 0.0) { ar = (float)image.Info.Width / image.Info.Height; } int bufferSize = image.Info.ImageSize; IntPtr videoBufferPtr; if (clone) { // we have to know to free it later _memoryOwned = true; // allocate some memory for a video buffer videoBufferPtr = Marshal.AllocHGlobal(bufferSize); using (var handle = image.GetData().Bytes.Pin()) { unsafe { System.Buffer.MemoryCopy((void *)handle.Pointer, (void *)videoBufferPtr.ToPointer(), bufferSize, bufferSize); } } } else { _pinnedBytes = true; unsafe { _handle = image.GetData().Bytes.Pin(); //unpin when frame gets Disposed videoBufferPtr = (IntPtr)_handle.Pointer; } } _ndiVideoFrame = new NDIlib.video_frame_v2_t() { xres = image.Info.Width, yres = image.Info.Height, FourCC = fourCC, frame_rate_N = frameRateNumerator, frame_rate_D = frameRateDenominator, picture_aspect_ratio = ar, frame_format_type = format, timecode = NDIlib.send_timecode_synthesize, p_data = videoBufferPtr, line_stride_in_bytes = image.Info.ScanSize, p_metadata = IntPtr.Zero, timestamp = 0 }; }
public unsafe PointerBitmap(System.Buffers.MemoryHandle bitmapData, BitmapInfo bitmapInfo, bool isReadOnly = false) { if (bitmapData.Pointer == null) { throw new ArgumentNullException(nameof(bitmapData)); } _Pointer = new IntPtr(bitmapData.Pointer); _Info = bitmapInfo; _IsReadOnly = isReadOnly; }
/// <summary> /// Creates a new pinned buffer from an existing buffer /// </summary> /// <param name="buffer">existing buffer to pin</param> public PinnedBuffer(T[] buffer) { // allocate managed space ManagedBuffer = buffer; // pin the memory Memory = new Memory <T>(ManagedBuffer); Handle = Memory.Pin(); // get a pointer to the pinned memory pData = (T *)Handle.Pointer; }
/// <summary> /// Runs the loaded model for the given inputs and outputs. Uses the given RunOptions for this run. /// /// Outputs need to be created with correct type and dimension to receive the fetched data. /// </summary> /// <param name="inputNames">Specify a collection of string that indicates the input names. Should match <paramref name="inputValues"/>.</param> /// <param name="inputValues">Specify a collection of <see cref="FixedBufferOnnxValue"/> that indicates the input values.</param> /// <param name="output">Specify a collection of <see cref="NamedOnnxValue"/> that indicates the output values.</param> /// <param name="options"></param> public void Run( IReadOnlyCollection <string> inputNames, IReadOnlyCollection <FixedBufferOnnxValue> inputValues, IReadOnlyCollection <NamedOnnxValue> outputs, RunOptions options) { if (inputNames.Count != inputValues.Count) { throw new ArgumentException($"Length of {nameof(inputNames)} ({inputNames.Count}) must match that of {nameof(inputValues)} ({inputValues.Count})."); } var outputNamesArray = new string[outputs.Count]; var outputValuesArray = new IntPtr[outputs.Count]; var pinnedOutputBufferHandles = new System.Buffers.MemoryHandle[outputs.Count]; var disposeOutputs = new bool[outputs.Count]; try { // prepare inputs string[] inputNamesArray = inputNames as string[] ?? inputNames.ToArray(); IntPtr[] inputValuesArray = new IntPtr[inputNames.Count]; int inputIndex = 0; foreach (var input in inputValues) { inputValuesArray[inputIndex] = input.Value; inputIndex++; } // prepare outputs int outputIndex = 0; foreach (var output in outputs) { outputNamesArray[outputIndex] = output.Name; // create native OrtValue from the output if feasible, else throw notsupported exception for now output.ToNativeOnnxValue( out outputValuesArray[outputIndex], out pinnedOutputBufferHandles[outputIndex], out disposeOutputs[outputIndex]); outputIndex++; } IntPtr status = NativeMethods.OrtRun( _nativeHandle, options.Handle, inputNamesArray, inputValuesArray, (UIntPtr)inputNames.Count, outputNamesArray, (UIntPtr)outputs.Count, outputValuesArray /* pointers to Pre-allocated OrtValue instances */ ); NativeApiStatus.VerifySuccess(status); } finally { for (int i = 0; i < outputs.Count; i++) { if (disposeOutputs[i]) { NativeMethods.OrtReleaseValue(outputValuesArray[i]); // For elementary type Tensors, this should not release the buffer, but should delete the native tensor object. // For string tensors, this releases the native memory allocated for the tensor, including the buffer pinnedOutputBufferHandles[i].Dispose(); } } } }
/// <summary> /// Runs the loaded model for the given inputs, and fetches the specified outputs in <paramref name="outputNames"/>. Uses the given RunOptions for this run. /// </summary> /// <param name="inputs">Specify a collection of <see cref="NamedOnnxValue"/> that indicates the input values.</param> /// <param name="outputNames">Specify a collection of string that indicates the output names to fetch.</param> /// <param name="options"></param> /// <returns>Output Tensors in a Collection of NamedOnnxValue. User must dispose the output.</returns> public IDisposableReadOnlyCollection <DisposableNamedOnnxValue> Run(IReadOnlyCollection <NamedOnnxValue> inputs, IReadOnlyCollection <string> outputNames, RunOptions options) { // prepare inputs var inputNamesArray = new string[inputs.Count]; var inputValuesArray = new IntPtr[inputs.Count]; var pinnedInputBufferHandles = new System.Buffers.MemoryHandle[inputs.Count]; var disposeInputs = new bool[inputs.Count]; int inputIndex = 0; foreach (var input in inputs) { inputNamesArray[inputIndex] = input.Name; // create Tensor from the input if feasible, else throw notsupported exception for now input.ToNativeOnnxValue( out inputValuesArray[inputIndex], out pinnedInputBufferHandles[inputIndex], out disposeInputs[inputIndex]); inputIndex++; } // prepare outputs string[] outputNamesArray = outputNames as string[] ?? outputNames.ToArray(); IntPtr[] outputValuesArray = new IntPtr[outputNames.Count]; IntPtr status = NativeMethods.OrtRun( _nativeHandle, options.Handle, inputNamesArray, inputValuesArray, (UIntPtr)inputs.Count, outputNamesArray, (UIntPtr)outputNames.Count, outputValuesArray /* Empty array is passed in to receive output OrtValue pointers */ ); try { NativeApiStatus.VerifySuccess(status); var result = new DisposableList <DisposableNamedOnnxValue>(outputValuesArray.Length); for (int i = 0; i < outputValuesArray.Length; i++) { result.Add(DisposableNamedOnnxValue.CreateFromOnnxValue(outputNamesArray[i], outputValuesArray[i])); } return(result); } catch (OnnxRuntimeException e) { //clean up the individual output tensors if it is not null; for (int i = 0; i < outputValuesArray.Length; i++) { if (outputValuesArray[i] != IntPtr.Zero) { NativeMethods.OrtReleaseValue(outputValuesArray[i]); } } throw e; } finally { for (int i = 0; i < inputs.Count; i++) { if (disposeInputs[i]) { NativeMethods.OrtReleaseValue(inputValuesArray[i]); // For elementary type Tensors, this should not release the buffer, but should delete the native tensor object. // For string tensors, this releases the native memory allocated for the tensor, including the buffer pinnedInputBufferHandles[i].Dispose(); } } } }
/// <summary> /// Runs the loaded model for the given inputs, and fetches the specified outputs in <paramref name="outputNames"/>. /// </summary> /// <param name="inputs"></param> /// <param name="outputNames"></param> /// <param name="options"></param> /// <returns>Output Tensors in a Dictionary</returns> //TODO: kept internal until RunOptions is made public internal IReadOnlyCollection <NamedOnnxValue> Run(IReadOnlyCollection <NamedOnnxValue> inputs, IReadOnlyCollection <string> outputNames, RunOptions options) { var inputNames = new string[inputs.Count]; var inputTensors = new IntPtr[inputs.Count]; var pinnedBufferHandles = new System.Buffers.MemoryHandle[inputs.Count]; int offset = 0; foreach (var input in inputs) { inputNames[offset] = input.Name; // create Tensor from the input if feasible, else throw notsupported exception for now input.ToNativeOnnxValue(out inputTensors[offset], out pinnedBufferHandles[offset]); offset++; } string[] outputNamesArray = outputNames.ToArray(); IntPtr[] outputValueArray = new IntPtr[outputNames.Count]; IntPtr status = NativeMethods.OrtRunInference( this._nativeHandle, IntPtr.Zero, // TODO: use Run options when Run options creation API is available // Passing null uses the default run options in the C-api inputNames, inputTensors, (ulong)(inputTensors.Length), /* TODO: size_t, make it portable for x86 arm */ outputNamesArray, (ulong)outputNames.Count, /* TODO: size_t, make it portable for x86 and arm */ outputValueArray /* An array of output value pointers. Array must be allocated by the caller */ ); try { NativeApiStatus.VerifySuccess(status); var result = new List <NamedOnnxValue>(); for (uint i = 0; i < outputValueArray.Length; i++) { result.Add(NamedOnnxValue.CreateFromOnnxValue(outputNamesArray[i], outputValueArray[i])); } return(result); } catch (OnnxRuntimeException e) { //clean up the individual output tensors if it is not null; for (uint i = 0; i < outputValueArray.Length; i++) { if (outputValueArray[i] != IntPtr.Zero) { NativeMethods.OrtReleaseValue(outputValueArray[i]); } } throw e; } finally { // always unpin the input buffers, and delete the native Onnx value objects for (int i = 0; i < inputs.Count; i++) { NativeMethods.OrtReleaseValue(inputTensors[i]); // this should not release the buffer, but should delete the native tensor object pinnedBufferHandles[i].Dispose(); } } }
/// <summary> /// Runs the loaded model for the given inputs, and fetches the specified outputs in <paramref name="outputNames". Uses the given RunOptions for this run./>. /// </summary> /// <param name="inputs"></param> /// <param name="outputNames"></param> /// <param name="options"></param> /// <returns>Output Tensors in a Collection of NamedOnnxValue. User must dispose the output.</returns> public IDisposableReadOnlyCollection <DisposableNamedOnnxValue> Run(IReadOnlyCollection <NamedOnnxValue> inputs, IReadOnlyCollection <string> outputNames, RunOptions options) { var inputNames = new string[inputs.Count]; var inputTensors = new IntPtr[inputs.Count]; var pinnedBufferHandles = new System.Buffers.MemoryHandle[inputs.Count]; int inputIndex = 0; foreach (var input in inputs) { inputNames[inputIndex] = input.Name; // create Tensor from the input if feasible, else throw notsupported exception for now input.ToNativeOnnxValue(out inputTensors[inputIndex], out pinnedBufferHandles[inputIndex]); inputIndex++; } string[] outputNamesArray = outputNames.ToArray(); IntPtr[] outputValueArray = new IntPtr[outputNames.Count]; IntPtr status = NativeMethods.OrtRun( this._nativeHandle, options.Handle, inputNames, inputTensors, (UIntPtr)(inputTensors.Length), outputNamesArray, (UIntPtr)outputNames.Count, outputValueArray /* An array of output value pointers. Array must be allocated by the caller */ ); try { NativeApiStatus.VerifySuccess(status); var result = new DisposableList <DisposableNamedOnnxValue>(); for (uint i = 0; i < outputValueArray.Length; i++) { result.Add(DisposableNamedOnnxValue.CreateFromOnnxValue(outputNamesArray[i], outputValueArray[i])); } return(result); } catch (OnnxRuntimeException e) { //clean up the individual output tensors if it is not null; for (uint i = 0; i < outputValueArray.Length; i++) { if (outputValueArray[i] != IntPtr.Zero) { NativeMethods.OrtReleaseValue(outputValueArray[i]); } } throw e; } finally { inputIndex = 0; foreach (var input in inputs) { // For NamedOnnxValue, always unpin the input buffers, and delete the native Onnx value objects // For DisposableNamedOnnxValue, the user needs to do this by invoking Dispose if (input.GetType() == typeof(NamedOnnxValue)) { NativeMethods.OrtReleaseValue(inputTensors[inputIndex]); // For elementary type Tensors, this should not release the buffer, but should delete the native tensor object. // For string tensors, this releases the native memory allocated for the tensor, including the buffer pinnedBufferHandles[inputIndex].Dispose(); } inputIndex++; } } }