Esempio n. 1
0
        /// <summary>
        /// Generate a 15-bit video fingerprint from the input YUV244 buffer
        /// This is currently unused but could be used to regenerate timecode on the destination video
        /// if this has been lost in the trancode process.  There are many other potential uses for this fingerprint data.
        ///
        /// The algorithm divides the frame into 16 blocks (4x4) and applies the Hadamard masks to divide these blocks
        /// into two sets in 15 different and orthogonal ways.  The relative brightness of each pair of sets yields one
        /// bit of the fingerprint.  The entire fingerprint is comprised of 15 bits; one from each Hadamard mask.
        /// The whole algorithm is resilient to changes of resolution, aspect, brightness, contrast and gamma that might occur in the
        /// transcode process.  It would be a simple matter to automatically detect letterboxing/pillarboxing and to only analyse the
        /// active video area if this were required.
        /// Testing with transcoded broadcast video has shown the fingerprint to be robust and reliable.
        /// </summary>
        /// <param name="videoFrame"></param>
        /// <param name="sums"></param>
        /// <returns></returns>
        private unsafe int VideoFingerprint(IDeckLinkVideoInputFrame videoFrame, int[] sums)
        {
            var qheight = videoFrame.GetHeight() >> 2;
            var qwidth  = videoFrame.GetWidth() >> 2;

            IntPtr buffer;

            videoFrame.GetBytes(out buffer);

            var ptr = (byte *)buffer + 1; // Skip over first U byte

            for (var r = 0; r < qheight; r++)
            {
                for (var c = 0; c < qwidth; c++)
                {
                    sums[0] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[1] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[2] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[3] += *ptr;
                    ptr     += 2;
                }
            }

            for (var r = 0; r < qheight; r++)
            {
                for (var c = 0; c < qwidth; c++)
                {
                    sums[4] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[5] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[6] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[7] += *ptr;
                    ptr     += 2;
                }
            }

            for (var r = 0; r < qheight; r++)
            {
                for (var c = 0; c < qwidth; c++)
                {
                    sums[8] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[9] += *ptr;
                    ptr     += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[10] += *ptr;
                    ptr      += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[11] += *ptr;
                    ptr      += 2;
                }
            }

            for (var r = 0; r < qheight; r++)
            {
                for (var c = 0; c < qwidth; c++)
                {
                    sums[12] += *ptr;
                    ptr      += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[13] += *ptr;
                    ptr      += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[14] += *ptr;
                    ptr      += 2;
                }

                for (var c = 0; c < qwidth; c++)
                {
                    sums[15] += *ptr;
                    ptr      += 2;
                }
            }

            for (var i = 0; i < 16; i++)
            {
                sums[i] /= qwidth * qheight;
            }

            var videoFingerprint = 0;
            var bit = 1;

            for (var i = 0; i < 15; i++)
            {
                var sum = 0;
                for (var j = 0; j < 16; j++)
                {
                    sum += sums[j] * masks[i, j];
                }

                if (sum > 0)
                {
                    videoFingerprint |= bit;
                }

                bit <<= 1;
            }
            return(videoFingerprint);
        }
Esempio n. 2
0
        void IDeckLinkInputCallback.VideoInputFrameArrived(IDeckLinkVideoInputFrame videoFrame, IDeckLinkAudioInputPacket audioPacket)
        {
            if (videoFrame != null)
            {
                try
                {
                    var frameFlags = videoFrame.GetFlags();

                    bool inputSignal = frameFlags.HasFlag(_BMDFrameFlags.bmdFrameHasNoInputSource);

                    if (inputSignal != validInputSignal)
                    {
                        validInputSignal = inputSignal;
                        InputSignalChanged?.Invoke(validInputSignal);
                    }
                    else
                    {
                        int width  = videoFrame.GetWidth();
                        int height = videoFrame.GetHeight();
                        int stride = videoFrame.GetRowBytes();
                        var format = videoFrame.GetPixelFormat();

                        var bufferLength = stride * height;
                        videoFrame.GetBytes(out IntPtr pBuffer);

                        VideoDataArrived?.Invoke(pBuffer, bufferLength, 0);


                        //var f = File.Create(@"d:\testBMP2\" + DateTime.Now.ToString("HH_mm_ss_fff") + " " + width + "x" + height + "_" + format + ".raw");

                        //byte[] data = new byte[bufferLength];
                        //Marshal.Copy(pBuffer, data, 0, data.Length);
                        //f.Write(data, 0, data.Length);
                        //f.Close();
                    }
                }
                finally
                {
                    Marshal.ReleaseComObject(videoFrame);
                }
            }


            if (audioPacket != null)
            {
                try
                {
                    long packetTime = 0;
                    //audioPacket.GetPacketTime(out packetTime, 30000);

                    int sampleSize   = ((int)AudioSampleType / 8); //32bit
                    int samplesCount = audioPacket.GetSampleFrameCount();
                    int dataLength   = sampleSize * AudioChannelsCount * samplesCount;

                    if (dataLength > 0)
                    {
                        audioPacket.GetBytes(out IntPtr pBuffer);

                        if (pBuffer != IntPtr.Zero)
                        {
                            byte[] data = new byte[dataLength];
                            Marshal.Copy(pBuffer, data, 0, data.Length);

                            AudioDataArrived?.Invoke(data, packetTime);
                        }
                    }
                }
                finally
                {
                    Marshal.ReleaseComObject(audioPacket);
                }
            }
        }