예제 #1
0
        /// <inheritdoc/>
        public void DecodeFromStream(Stream stream, Image image)
        {
            if (!this.HasNV12Header(stream))
            {
                throw new ArgumentException("Stream does not appear to be NV12-encoded (missing header).");
            }

            stream.Position = 4; // skip header

            // decode NV12
            var width    = image.Width;
            var height   = image.Height;
            int startUV  = width * height;
            int strideUV = width;

            var size = (int)(width * height * 1.5 + 0.5); // 12-bit/pixel

            using var sharedData = SharedArrayPool <byte> .GetOrCreate(size);

            var data = sharedData.Resource;

            stream.Read(data, 0, size);

            unsafe
            {
                var buffer = (byte *)image.UnmanagedBuffer.Data;
                for (int i = 0; i < height; i++)
                {
                    var p          = buffer + (i * 4 * width);
                    int row        = i * width;
                    var startUVrow = startUV + ((i / 2) * strideUV);
                    for (int j = 0; j < width; j++)
                    {
                        var y      = data[row + j] - 16;
                        var uindex = startUVrow + (2 * (j / 2));
                        var u      = data[uindex] - 128;
                        var v      = data[uindex + 1] - 128;

                        var yy = 1.164383 * y;
                        var b  = yy + (2.017232 * u);
                        var g  = yy - (0.812968 * v) - (0.391762 * u);
                        var r  = yy + (1.596027 * v);

                        *p++ = (byte)Math.Max(0, Math.Min(255, b + 0.5));
                        *p++ = (byte)Math.Max(0, Math.Min(255, g + 0.5));
                        *p++ = (byte)Math.Max(0, Math.Min(255, r + 0.5));
                        *p++ = 0xff; // alpha
                    }
                }
            }
        }
예제 #2
0
        public void SharedArrayPoolTest()
        {
            // allocate and release an array of size 10
            var int10 = SharedArrayPool <int> .GetOrCreate(10);

            Assert.AreEqual(10, int10.Resource.Length);
            object ref10 = int10.Resource; // capture the underlying array reference

            int10.Dispose();

            // allocate and release an array of size 20
            var int20 = SharedArrayPool <int> .GetOrCreate(20);

            Assert.AreEqual(20, int20.Resource.Length);
            object ref20 = int20.Resource; // capture the underlying array reference

            int20.Dispose();

            // request another array of size 10 without releasing
            int10 = SharedArrayPool <int> .GetOrCreate(10);

            Assert.AreEqual(10, int10.Resource.Length);
            Assert.AreSame(ref10, int10.Resource); // verify recycled resource

            // request another array of size 20 without releasing
            int20 = SharedArrayPool <int> .GetOrCreate(20);

            Assert.AreEqual(20, int20.Resource.Length);
            Assert.AreSame(ref20, int20.Resource); // verify recycled resource

            // allocate another array of size 20 without releasing
            var int20_2 = SharedArrayPool <int> .GetOrCreate(20);

            Assert.AreEqual(20, int20_2.Resource.Length);
            Assert.AreNotSame(ref20, int20_2.Resource); // not recycled

            // allocate another array of size 10 without releasing
            var int10_2 = SharedArrayPool <int> .GetOrCreate(10);

            Assert.AreEqual(10, int10_2.Resource.Length);
            Assert.AreNotSame(ref10, int10_2.Resource); // not recycled

            // release all instances
            int10.Dispose();
            int20.Dispose();
            int10_2.Dispose();
            int20_2.Dispose();
        }
예제 #3
0
        /// <inheritdoc/>
        public unsafe void Start(Action <DateTime> notifyCompletionTime)
        {
            // notify that this is an infinite source component
            notifyCompletionTime(DateTime.MaxValue);

            this.camera = new MediaCaptureInternal(this.configuration.DeviceId);
            this.camera.Open();
            var isFormatSupported = false;

            foreach (var format in this.camera.SupportedPixelFormats())
            {
                if (format.Pixels == this.configuration.PixelFormat)
                {
                    this.camera.SetVideoFormat(this.configuration.Width, this.configuration.Height, format);
                    isFormatSupported = true;
                }
            }

            if (!isFormatSupported)
            {
                throw new ArgumentException($"Pixel format {this.configuration.PixelFormat} is not supported by the camera");
            }

            var current = this.camera.GetVideoFormat();

            if (current.Width != this.configuration.Width || current.Height != this.configuration.Height)
            {
                throw new ArgumentException($"Width/height {this.configuration.Width}x{this.configuration.Height} is not supported by the camera");
            }

            this.camera.OnFrame += (_, frame) =>
            {
                var originatingTime = this.pipeline.GetCurrentTime();

                if (this.Raw.HasSubscribers)
                {
                    var len = frame.Length;
                    using (Shared <byte[]> shared = SharedArrayPool <byte> .GetOrCreate(len))
                    {
                        Marshal.Copy(frame.Start, shared.Resource, 0, len);
                        this.Raw.Post(shared, originatingTime);
                    }
                }

                if (this.Out.HasSubscribers)
                {
                    using (var sharedImage = ImagePool.GetOrCreate(this.configuration.Width, this.configuration.Height, PixelFormat.BGR_24bpp))
                    {
                        if (this.configuration.PixelFormat == PixelFormatId.BGR24)
                        {
                            sharedImage.Resource.CopyFrom((IntPtr)frame.Start);
                            this.Out.Post(sharedImage, this.pipeline.GetCurrentTime());
                        }
                        else if (this.configuration.PixelFormat == PixelFormatId.YUYV)
                        {
                            // convert YUYV -> BGR24 (see https://msdn.microsoft.com/en-us/library/ms893078.aspx)
                            var len = (int)(frame.Length * 1.5);
                            using (Shared <byte[]> shared = SharedArrayPool <byte> .GetOrCreate(len))
                            {
                                var bytes = shared.Resource;
                                var pY    = (byte *)frame.Start.ToPointer();
                                var pU    = pY + 1;
                                var pV    = pY + 3;
                                for (var i = 0; i < len;)
                                {
                                    int y = (*pY - 16) * 298;
                                    int u = *pU - 128;
                                    int v = *pV - 128;
                                    int r = (y + (409 * v) + 128) >> 8;
                                    int g = (y - (100 * u) - (208 * v) + 128) >> 8;
                                    int b = (y + (516 * u) + 128) >> 8;

                                    bytes[i++] = (byte)((r < 0) ? 0 : ((r > 255) ? 255 : r));
                                    bytes[i++] = (byte)((g < 0) ? 0 : ((g > 255) ? 255 : g));
                                    bytes[i++] = (byte)((b < 0) ? 0 : ((b > 255) ? 255 : b));

                                    pY += 2;

                                    y          = (*pY - 16) * 298;
                                    r          = (y + (409 * v) + 128) >> 8;
                                    g          = (y - (100 * u) - (208 * v) + 128) >> 8;
                                    b          = (y + (516 * u) + 128) >> 8;
                                    bytes[i++] = (byte)((r < 0) ? 0 : ((r > 255) ? 255 : r));
                                    bytes[i++] = (byte)((g < 0) ? 0 : ((g > 255) ? 255 : g));
                                    bytes[i++] = (byte)((b < 0) ? 0 : ((b > 255) ? 255 : b));

                                    pY += 2;
                                    pU += 4;
                                    pV += 4;
                                }

                                sharedImage.Resource.CopyFrom(bytes);
                                this.Out.Post(sharedImage, originatingTime);
                            }
                        }
                    }
                }

#if TEST_DROPPED_FRAMES
                System.Threading.Thread.Sleep(1000); // for testing dropped frames
#endif // TEST_DROPPED_FRAMES

                frame.Dispose(); // release back to driver!
            };

            this.camera.StreamBuffers();
        }