/// <summary>
        /// Builds the raw depth frame.
        /// </summary>
        /// <param name="depthFormat">Depth image format.</param>
        /// <param name="rawFrames">The raw frames.</param>
        /// <returns>
        /// Standard ccr iterator
        /// </returns>
        private IEnumerator <ITask> BuildRawDepthFrame(DepthImageFormat depthFormat, RawKinectFrames rawFrames)
        {
            var depthCamResponse = this.depthCamPartner.Get();

            yield return(depthCamResponse.Choice());

            var depthCamSensorState = (DepthCamSensorState)depthCamResponse;

            if (depthCamSensorState == null)
            {
                yield break;
            }

            var frameInfo = new KinectFrameInfo
            {
                Timestamp     = depthCamSensorState.TimeStamp.Ticks,
                Width         = depthCamSensorState.DepthImageSize.Width,
                Height        = depthCamSensorState.DepthImageSize.Height,
                BytesPerPixel = 2
            };

            var target = new short[depthCamSensorState.DepthImage.Length];

            // Raw depth data includes 3 bits for player information
            for (int i = 0; i < target.Length; i++)
            {
                target[i] = (short)(depthCamSensorState.DepthImage[i] << 3);
            }

            rawFrames.RawDepthFrameData = target;

            rawFrames.RawDepthFrameInfo = frameInfo;
        }
        /// <summary>
        /// Builds the video based data.
        /// </summary>
        /// <param name="imageFormat">Image format.</param>
        /// <param name="rawFrames">The raw frames.</param>
        /// <returns>
        /// Standard ccr iterator
        /// </returns>
        private IEnumerator <ITask> BuildRawVideoFrame(ColorImageFormat imageFormat, RawKinectFrames rawFrames)
        {
            var webCamResponse = this.webCamPartner.Get();

            yield return(webCamResponse.Choice());

            var webCamSensorState = (WebCamSensorState)webCamResponse;

            if (webCamSensorState == null)
            {
                yield break;
            }

            var frameInfo = new KinectFrameInfo
            {
                Timestamp     = webCamSensorState.TimeStamp.Ticks,
                Width         = webCamSensorState.Width,
                Height        = webCamSensorState.Height,
                BytesPerPixel = 4
            };

            var source = webCamSensorState.Data;

            // Move from 24rgb to 32rgb
            var target = new byte[(source.Length * 4) / 3];

            for (int i = 0, j = 0; i < source.Length && j < target.Length; i += 3, j += 4)
            {
                target[j]     = source[i];
                target[j + 1] = source[i + 1];
                target[j + 2] = source[i + 2];
            }

            rawFrames.RawColorFrameData = target;

            rawFrames.RawColorFrameInfo = frameInfo;
        }
        /// <summary>
        /// Drains the pending requests.
        /// </summary>
        /// <param name="timestamp">The timestamp.</param>
        /// <returns>Standard ccr iterator</returns>
        private IEnumerator <ITask> DrainPendingRequests(DateTime timestamp)
        {
            var stopwatch = Stopwatch.StartNew();

            try
            {
                // No pending request - exit early
                if (this.pendingFrameRequests.Count == 0)
                {
                    yield break;
                }

                // Fetch the depth and video in parallel as required. Do once each for any pending requests.
                var taskCount = 0;
                var donePort  = new Port <EmptyValue>();
                var rawFrames = new RawKinectFrames();

                if (this.pendingFrameRequests.Any(p => p.Body.IncludeDepth))
                {
                    Arbiter.ExecuteToCompletion(
                        TaskQueue,
                        new IterativeTask <DepthImageFormat, RawKinectFrames>(
                            this.state.DepthImageFormat,
                            rawFrames,
                            this.BuildRawDepthFrame),
                        donePort);

                    ++taskCount;
                }

                if (this.pendingFrameRequests.Any(p => p.Body.IncludeVideo))
                {
                    Arbiter.ExecuteToCompletion(
                        TaskQueue,
                        new IterativeTask <ColorImageFormat, RawKinectFrames>(
                            this.state.ColorImageFormat,
                            rawFrames,
                            this.BuildRawVideoFrame),
                        donePort);

                    ++taskCount;
                }

                if (taskCount > 0)
                {
                    // Wait for the operations to complete
                    yield return(Arbiter.MultipleItemReceive(false, donePort, taskCount, EmptyHandler));
                }

                // Stamp the returned frames
                var currentFrame = ++this.frameNumber;
                if (rawFrames.RawDepthFrameData != null)
                {
                    rawFrames.RawDepthFrameInfo.FrameNumber = currentFrame;
                    rawFrames.RawDepthFrameInfo.Timestamp   = timestamp.Ticks;
                }

                if (rawFrames.RawColorFrameData != null)
                {
                    rawFrames.RawColorFrameInfo.FrameNumber = currentFrame;
                    rawFrames.RawColorFrameInfo.Timestamp   = timestamp.Ticks;
                }

                // Return the requested frames to each pending request.
                foreach (var request in this.pendingFrameRequests)
                {
                    var response = new RawKinectFrames
                    {
                        RawDepthFrameInfo = request.Body.IncludeDepth ? rawFrames.RawDepthFrameInfo : null,
                        RawDepthFrameData = request.Body.IncludeDepth ? rawFrames.RawDepthFrameData : null,
                        RawColorFrameInfo = request.Body.IncludeVideo ? rawFrames.RawColorFrameInfo : null,
                        RawColorFrameData = request.Body.IncludeVideo ? rawFrames.RawColorFrameData : null,
                    };
                    request.ResponsePort.Post(new kinect.GetRawFrameResponse {
                        RawFrames = response
                    });
                }
            }
            finally
            {
                this.pendingFrameRequests.Clear();

                var timeToNextFrame = this.pollInterval - stopwatch.Elapsed;
                if (timeToNextFrame <= TimeSpan.Zero)
                {
                    this.pollPort.Post(DateTime.Now);
                }
                else
                {
                    TaskQueue.EnqueueTimer(timeToNextFrame, this.pollPort);
                }
            }
        }