private void WritePendingFrame(bool forceKeyFrame) { if (!framePending) { return; } framePending = false; bool keyFrame = forceKeyFrame || frameCount % keyFramePeriodInFrames == 0; FlvWriter.FlvVideoFrameFlags frameFlags = FlvWriter.FlvVideoFrameFlags.Codec_ScreenVideo | (keyFrame ? FlvWriter.FlvVideoFrameFlags.Type_KeyFrame : FlvWriter.FlvVideoFrameFlags.Type_InterFrame); flvWriter.WriteFlvVideoFrame(frameFlags, (int)(frameCount * 1000.0 / framesPerSecond), reserveBytesPerFrame, delegate(byte[] buffer, ref int bufferOffset) { // write frame header buffer[bufferOffset++] = (byte)(((nominalBlockWidth / 16 - 1) << 4) | (width >> 8)); buffer[bufferOffset++] = (byte)width; buffer[bufferOffset++] = (byte)(((nominalBlockHeight / 16 - 1) << 4) | (height >> 8)); buffer[bufferOffset++] = (byte)height; // proceed from bottom-left to top-right row by row for (int blockYOrigin = height; blockYOrigin >= 0; blockYOrigin -= nominalBlockHeight) { int blockHeight = Math.Min(blockYOrigin, nominalBlockHeight); for (int blockXOrigin = 0; blockXOrigin < width; blockXOrigin += nominalBlockWidth) { int blockWidth = Math.Min(width - blockXOrigin, nominalBlockWidth); bool diff = false; int blockBufferOffset = 0; int frameOffset = blockYOrigin * width + blockXOrigin; for (int y = 0; y < blockHeight; y++) { frameOffset -= width; for (int x = 0; x < blockWidth; x++) { int color = currentFramePixels[frameOffset]; blockBuffer[blockBufferOffset++] = (byte)color; // B blockBuffer[blockBufferOffset++] = (byte)(color >> 8); // G blockBuffer[blockBufferOffset++] = (byte)(color >> 16); // R if (previousFramePixels[frameOffset++] != color) { diff = true; } } frameOffset -= blockWidth; } if (keyFrame || diff) { deflater.Reset(); deflater.SetInput(blockBuffer, 0, blockBufferOffset); deflater.Finish(); int blockLength = deflater.Deflate(buffer, bufferOffset + 2, buffer.Length - bufferOffset - 2); Debug.Assert(deflater.IsFinished, "Deflater should be finished."); buffer[bufferOffset++] = (byte)(blockLength >> 8); buffer[bufferOffset++] = (byte)blockLength; bufferOffset += blockLength; } else { buffer[bufferOffset++] = 0; buffer[bufferOffset++] = 0; } } } }); frameCount += 1; }