/// <summary>
 /// Emergeny clear-out. Drop all queued frames
 /// </summary>
 public void WipeBuffer()
 {
     lock (WaitingFrames) {
         WaitingFrames.Clear();
     }
     GC.Collect();
 }
        /// <summary>
        /// Remove all frames captured before the given capture time. They will not be encoded.
        /// </summary>
        public void WipeBufferUntil(double AbandonTime)
        {
            lock (this) {
                lock (WaitingCaptures) {
                    while (WaitingCaptures.DataAvailable(this))
                    {
                        var ti = WaitingCaptures.Peek(this);
                        if (ti != null && ti.Seconds < AbandonTime)
                        {
                            WaitingCaptures.Dequeue(this);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            lock (WaitingFrames) {
                while (WaitingFrames.Count > 0 && WaitingFrames[0].Seconds < AbandonTime)
                {
                    WaitingFrames.RemoveAt(0);
                }
            }

            GC.Collect();
        }
        /// <summary>
        /// Load the buffer into a MediaFrame for the encoder.
        /// IMPORTANT: You must call UnloadFrame after this method is called.
        /// For efficiency, unload as soon as possible.
        /// </summary>
        public void LoadToFrame(ref MediaFrame Frame)
        {
            try {
                if (WaitingFrames.Count > 0)
                {
                    TimedImage img = null;
                    lock (WaitingFrames) {
                        WaitingFrames.RemoveAll(a => a == null);
                        WaitingFrames.Sort((a, b) => a.Seconds.CompareTo(b.Seconds));

                        img = WaitingFrames[0];
                        WaitingFrames.RemoveAt(0);
                    }

                    if (img.Luma == null || img.Cr == null || img.Cb == null)
                    {
                        return;                                                                           // crap frame
                    }
                    Y = img.Luma;
                    u = img.Cr;
                    v = img.Cb;

                    Frame.VideoSize       = (ulong)Y.Length;
                    Frame.VideoSampleTime = img.Seconds;

                    pinY         = GCHandle.Alloc(Y, GCHandleType.Pinned);
                    Frame.Yplane = pinY.AddrOfPinnedObject();

                    pinU         = GCHandle.Alloc(u, GCHandleType.Pinned);
                    Frame.Uplane = pinU.AddrOfPinnedObject();

                    pinV         = GCHandle.Alloc(v, GCHandleType.Pinned);
                    Frame.Vplane = pinV.AddrOfPinnedObject();
                }
                else
                {
                    Frame.Yplane    = IntPtr.Zero;
                    Frame.Uplane    = IntPtr.Zero;
                    Frame.Vplane    = IntPtr.Zero;
                    Frame.VideoSize = 0;
                    Console.WriteLine("Frame buffer was empty (in ImageToYUV_Buffer.LoadToFrame())");
                }
            } catch {
                // Drop the bad frame data:
                UnloadFrame(ref Frame);                 // this can still be sent to the encoder, it should just mean a dropped frame
                Console.WriteLine("Lost a frame (no image)");
            }
        }