public void FrameArrivedDevice(FrameInformation frame) { using var _ = _resource.Map(); var resourceArray = _resource.GetMappedArray(); var rgbSize = frame.GetRgba32Size(); var width = frame.Info.Width; var rgba32Pitch = width * 4; var rgba32PitchPtr = (IntPtr)rgba32Pitch; using (var destPtr = CuDeviceMemory.Allocate(rgbSize)) { frame.DecodeToDeviceRgba32(destPtr); var memcopy = new CuMemcopy2D { SrcMemoryType = CuMemoryType.Device, SrcDevice = destPtr, SrcPitch = rgba32PitchPtr, DstMemoryType = CuMemoryType.Array, DstArray = resourceArray, WidthInBytes = rgba32PitchPtr, Height = (IntPtr)frame.Info.Height }; memcopy.Memcpy2D(); } _swap?.Present(1, PresentFlags.None); }
public unsafe void FrameArrivedHost(FrameInformation frame) { var rgbSize = frame.GetRgba32Size(); var width = frame.Info.Width; var rgba32Pitch = width * 4; var buffer = _swap.GetBackBuffer <Texture2D>(0); // TODO: Pool the buffer. var destHost = new byte[rgbSize]; fixed(byte *destHostPtr = destHost) { _device.ImmediateContext.UpdateSubresource( buffer, 0, null, (IntPtr)destHostPtr, rgba32Pitch, 0); } _swap?.Present(1, PresentFlags.None); }
private static void SaveAsBitmap( FrameInformation frame, string filename) { var width = frame.Info.Width; var height = frame.Info.Height; using var bitmap = new Bitmap( width, height, PixelFormat.Format32bppRgb); var locked = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); frame.DecodeToHostRgba32((byte *)locked.Scan0); bitmap.UnlockBits(locked); bitmap.Save(filename, ImageFormat.Bmp); }
public void FrameArrived(FrameInformation frame) { if (_disposed) { return; } using var _ = _context.Push(); // TODO: This does need to detect configuration changes. // https://en.wikipedia.org/wiki/Double-checked_locking if (!_hasSwap) { lock (_createdSwapSync) { if (!_hasSwap) { CreateSwap(frame); _hasSwap = true; } } } switch (frame.Buffer.MemoryType) { case CuMemoryType.Host: FrameArrivedHost(frame); break; case CuMemoryType.Device: FrameArrivedDevice(frame); break; default: throw new ArgumentOutOfRangeException( nameof(frame.Buffer.MemoryType), frame.Buffer.MemoryType, "Unsupported memory type."); } }
private void CreateSwap(FrameInformation frame) { var sc = new SwapChainDescription { BufferCount = 1, ModeDescription = new ModeDescription( frame.Info.Width, frame.Info.Height, new Rational(30, 1), Format.B8G8R8A8_UNorm), IsWindowed = true, OutputHandle = Hwnd, SampleDescription = new SampleDescription(1, 0), Usage = Usage.RenderTargetOutput, Flags = SwapChainFlags.None }; Device.CreateWithSwapChain( _adapter, DeviceCreationFlags.Debug, sc, out _device, out _swap); var buffer = _swap.GetBackBuffer <Texture2D>(0); _resource = CuGraphicsResource.Register(buffer.NativePointer); _resource.SetMapFlags(CuGraphicsMapResources.WriteDiscard); }
private CuCallbackResult VideoDisplayCallback( IntPtr data, IntPtr infoPtr) { using var _ = _context.Push(); if (CuVideoParseDisplayInfo.IsFinalFrame(infoPtr, out var info)) { if (!_framesChannel.Writer.TryWrite( FrameInformation.FinalFrame)) { _renderingCompleted.Set(); } return(CuCallbackResult.Success); } var processingParam = new CuVideoProcParams { ProgressiveFrame = info.ProgressiveFrame, SecondField = info.RepeatFirstField + 1, TopFieldFirst = info.TopFieldFirst, UnpairedField = info.RepeatFirstField < 0 ? 1 : 0 }; using var frame = _decoder.MapVideoFrame( info.PictureIndex, ref processingParam, out var pitch); var yuvInfo = _info.GetYuvInformation(pitch); var status = _decoder.GetDecodeStatus(info.PictureIndex); if (status != CuVideoDecodeStatus.Success) { // TODO: Determine what to do in this situation. This condition // is non-exceptional but may require different handling? } var frameByteSize = _info.GetFrameByteSize( pitch, out var chromaHeight); var destMemoryType = _useHostMemory ? CuMemoryType.Host : CuMemoryType.Device; AllocateNv12FrameBuffer( destMemoryType, frameByteSize, out var frameDevicePtr, out var frameLocalPtr); var byteWidth = _info.Width * _info.GetBytesPerPixel(); // Copy luma var memcopy = new CuMemcopy2D { SrcMemoryType = CuMemoryType.Device, SrcDevice = frame, SrcPitch = (IntPtr)pitch, DstMemoryType = destMemoryType, DstDevice = frameDevicePtr, DstHost = frameLocalPtr, DstPitch = (IntPtr)byteWidth, WidthInBytes = (IntPtr)byteWidth, Height = (IntPtr)_info.Height }; memcopy.Memcpy2D(); // Copy chroma memcopy.SrcDevice = new CuDevicePtr(frame.Handle + pitch * _info.Height); memcopy.DstDevice = new CuDevicePtr(frameDevicePtr.Handle + byteWidth * _info.Height); memcopy.DstHost = frameLocalPtr + byteWidth * _info.Height; memcopy.Height = (IntPtr)chromaHeight; memcopy.Memcpy2D(); var bufferStorage = new BufferStorage( frameLocalPtr, destMemoryType, frameDevicePtr, frameByteSize); var frameInfo = new FrameInformation( bufferStorage, pitch, _info, yuvInfo); if (!_framesChannel.Writer.TryWrite(frameInfo)) { _nv12BufferPool.Free(ref bufferStorage); } return(CuCallbackResult.Success); }