private bool GetPopulairPoint(Rectangle rect, ref PopulairPoint PopuPoint)
 {
     for (int i = 0; i < populairPoints.Count; i++)
     {
         PopulairPoint point = populairPoints[i];
         if (point.Rect.Width == rect.Width &&
             point.Rect.Height == rect.Height &&
             point.Rect.X == rect.X &&
             point.Rect.Y == rect.Y)
         {
             PopuPoint = populairPoints[i];
             return(true);
         }
     }
     return(false);
 }
        public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream)
        {
            lock (ImageProcessLock)
            {
                byte *pScan0 = (byte *)Scan0.ToInt32();
                if (!outStream.CanWrite)
                {
                    throw new Exception("Must have access to Write in the Stream");
                }

                int Stride    = 0;
                int RawLength = 0;
                int PixelSize = 0;

                switch (Format)
                {
                case PixelFormat.Format24bppRgb:
                    PixelSize = 3;
                    break;

                case PixelFormat.Format32bppArgb:
                case PixelFormat.Format32bppPArgb:
                    PixelSize = 4;
                    break;

                default:
                    throw new NotSupportedException(Format.ToString());
                }

                Stride    = ImageSize.Width * PixelSize;
                RawLength = Stride * ImageSize.Height;

                if (EncodeBuffer == null)
                {
                    this.EncodedFormat = Format;
                    this.EncodedWidth  = ImageSize.Width;
                    this.EncodedHeight = ImageSize.Height;
                    this.EncodeBuffer  = new byte[RawLength];
                    fixed(byte *ptr = EncodeBuffer)
                    {
                        byte[] temp = null;
                        using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0))
                        {
                            temp = base.jpgCompression.Compress(TmpBmp);
                        }

                        outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4);
                        outStream.Write(temp, 0, temp.Length);
                        NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength);
                    }

                    return;
                }

                if (ScreenRefreshSW.ElapsedMilliseconds > ScreenRefreshTimer)
                {
                    for (int i = 0; i < populairPoints.Count; i++)
                    {
                        if (populairPoints[i].Score == 0 || populairPoints[i].LastUpdate.Elapsed.Seconds > 5)
                        {
                            populairPoints.RemoveAt(i);
                        }
                    }
                    ScreenRefreshSW = Stopwatch.StartNew();
                }

                long oldPos = outStream.Position;
                outStream.Write(new byte[4], 0, 4);
                int TotalDataLength = 0;

                List <byte[]> updates = new List <byte[]>();
                MemoryStream  ms      = new MemoryStream();
                byte[]        buffer  = null;

                if (this.EncodedFormat != Format)
                {
                    throw new Exception("PixelFormat is not equal to previous Bitmap");
                }

                if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height)
                {
                    throw new Exception("Bitmap width/height are not equal to previous bitmap");
                }

                List <Rectangle> Blocks = new List <Rectangle>();
                int index = 0;

                Size s        = new Size(ScanArea.Width, CheckBlock.Height);
                Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height);

                int lasty = ScanArea.Height - lastSize.Height;
                int lastx = ScanArea.Width - lastSize.Width;

                Rectangle        cBlock       = new Rectangle();
                List <Rectangle> finalUpdates = new List <Rectangle>();

                PopulairPoint[] points = GetPossibleVideos();
                if (points.Length > 0)
                {
                    ScanArea = new Rectangle(points[0].Rect.X, points[0].Rect.Y, points[0].Rect.Width + points[0].Rect.X, points[0].Rect.Height + points[0].Rect.Y);
                }

                s = new Size(ScanArea.Width, s.Height);
                fixed(byte *encBuffer = EncodeBuffer)
                {
                    if (points.Length == 0) //only scan if there is no video
                    {
                        for (int y = ScanArea.Y; y != ScanArea.Height;)
                        {
                            if (y == lasty)
                            {
                                s = new Size(ScanArea.Width, lastSize.Height);
                            }
                            cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height);

                            int offset = (y * Stride) + (ScanArea.X * PixelSize);
                            if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0)
                            {
                                if (onCodeDebugScan != null)
                                {
                                    onCodeDebugScan(cBlock);
                                }

                                index = Blocks.Count - 1;
                                if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y)
                                {
                                    cBlock        = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height);
                                    Blocks[index] = cBlock;
                                }
                                else
                                {
                                    Blocks.Add(cBlock);
                                }
                            }
                            y += s.Height;
                        }

                        for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++)
                        {
                            s = new Size(CheckBlock.Width, Blocks[i].Height);
                            x = ScanArea.X;
                            while (x != ScanArea.Width)
                            {
                                if (x == lastx)
                                {
                                    s = new Size(lastSize.Width, Blocks[i].Height);
                                }

                                cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height);
                                bool FoundChanges = false;
                                int  blockStride  = PixelSize * cBlock.Width;

                                for (int j = 0; j < cBlock.Height; j++)
                                {
                                    int blockOffset = (Stride * (cBlock.Y + j)) + (PixelSize * cBlock.X);
                                    if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0)
                                    {
                                        FoundChanges = true;
                                    }
                                    NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes
                                }

                                if (onCodeDebugScan != null)
                                {
                                    onCodeDebugScan(cBlock);
                                }

                                if (FoundChanges)
                                {
                                    index = finalUpdates.Count - 1;
                                    if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X)
                                    {
                                        Rectangle rect     = finalUpdates[index];
                                        int       newWidth = cBlock.Width + rect.Width;
                                        cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height);
                                        finalUpdates[index] = cBlock;
                                    }
                                    else
                                    {
                                        finalUpdates.Add(cBlock);
                                    }
                                }
                                x += s.Width;
                            }
                        }
                    }
                    else
                    {
                        finalUpdates.Add(points[0].Rect);
                    }
                }

                for (int i = 0; i < finalUpdates.Count; i++)
                {
                    Rectangle rect        = finalUpdates[i];
                    int       blockStride = PixelSize * rect.Width;

                    Bitmap     TmpBmp  = new Bitmap(rect.Width, rect.Height, Format);
                    BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat);
                    for (int j = 0, offset = 0; j < rect.Height; j++)
                    {
                        int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X);
                        NativeMethods.memcpy((byte *)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes
                        offset += blockStride;
                    }
                    TmpBmp.UnlockBits(TmpData);

                    outStream.Write(BitConverter.GetBytes(rect.X), 0, 4);
                    outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4);
                    outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4);
                    outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4);
                    outStream.Write(new byte[4], 0, 4);

                    long length = outStream.Position;
                    long OldPos = outStream.Position;
                    base.jpgCompression.Compress(TmpBmp, ref outStream);
                    length = outStream.Position - length;

                    outStream.Position = OldPos - 4;
                    outStream.Write(BitConverter.GetBytes((int)length), 0, 4);
                    outStream.Position += length;

                    if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height)
                    {
                        PopulairPoint point = null;
                        if (GetPopulairPoint(rect, ref point))
                        {
                            point.Score++;
                            point.LastUpdate = Stopwatch.StartNew();
                            //Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height);
                        }
                        else
                        {
                            populairPoints.Add(new PopulairPoint(rect));
                        }
                    }

                    TmpBmp.Dispose();
                    TotalDataLength += (int)length + (4 * 5);
                }

                /*for (int i = 0; i < finalUpdates.Count; i++)
                 * {
                 *  Rectangle rect = finalUpdates[i];
                 *  int blockStride = PixelSize * rect.Width;
                 *  buffer = new byte[blockStride * rect.Height];
                 *
                 *  fixed (byte* ptr = buffer)
                 *  {
                 *      for (int j = 0, offset = 0; j < rect.Height; j++)
                 *      {
                 *          int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X);
                 *          NativeMethods.memcpy(ptr + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes
                 *          offset += blockStride;
                 *      }
                 *
                 *      using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * PixelSize, Format, new IntPtr(ptr)))
                 *      {
                 *          buffer = base.jpgCompression.Compress(TmpBmp);
                 *
                 *          if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height)
                 *          {
                 *              PopulairPoint point = null;
                 *              if (GetPopulairPoint(rect, ref point))
                 *              {
                 *                   point.Score++;
                 *                   point.LastUpdate = Stopwatch.StartNew();
                 *                   Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height);
                 *              }
                 *              else
                 *              {
                 *                  populairPoints.Add(new PopulairPoint(rect));
                 *              }
                 *          }
                 *      }
                 *  }
                 *
                 *  outStream.Write(BitConverter.GetBytes(rect.X), 0, 4);
                 *  outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4);
                 *  outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4);
                 *  outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4);
                 *  outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4);
                 *  outStream.Write(buffer, 0, buffer.Length);
                 *  TotalDataLength += buffer.Length + (4 * 5);
                 * }*/

                outStream.Position = oldPos;
                outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4);
                Blocks.Clear();
                ms.Close();
                ms.Dispose();
            }
        }