/** Now, this is a bit complicated. Once you understand the follwing code, you will * understand the Tao of SkypeKit video transport. */ internal bool GetFrame() { // At this point, we already have fresh control struct in our memory. // This is because we have just called IsNewFrameAvailable and that // used GetControlData() to fetch in new data. // The following will deterime, which buffer is available for reading, // and write the new states back into the control struct. The struct // will not be sent back to the shared memory until the end of this method. int bufferState = (controlStruct.bufferstates & 0x03); if (!haveFrame & bufferState == 0x01) { return false; } if (!haveFrame) haveFrame = true; if (bufferState == 0x00) controlStruct.bufferstates |= 0x02; if (bufferState == 0x03) controlStruct.bufferstates &= ~0x02; bufferState = (controlStruct.bufferstates & 0x03); // Now we map ourselves to either buffer1 or buffer2 FrameChannelStruct buffer; SharedMemoryChannel channel; if (bufferState == 0x1) { buffer = controlStruct.buffer1; channel = frameChannel1; } else if (bufferState == 0x2) { buffer = controlStruct.buffer2; channel = frameChannel2; } else throw new Exception("Error: unexpected video control buffer state"); // If there was no frame buffer channel opened for this buffer, we open it. if (channel == null) { channel = new SharedMemoryChannel(); bool success = channel.OpenMapping(buffer.bufid); if (!success) throw new Exception("Unable to map frame bitmap channel."); }; // If there was an open channel, we check if the IDs match if (channel != null) { if (channel.key != buffer.bufid) { return false; //throw new Exception("Error: video control buffer ID and frame buffer ID mismatch"); }; }; // Calculating the video frame size width = buffer.width; height = buffer.height; int bytesPerPixel = buffer.bitsperpixel >> 3; int newFrameSize = width * height * bytesPerPixel; // If it mismatches with our previous frame size, we need to reallocate buffers. if (newFrameSize != bitmapDataSize) { bitmapData = null; bitmapDataSize = newFrameSize; bitmapData = new byte[bitmapDataSize]; } // And now we marshal the frame into our bitmapData Marshal.Copy(channel.data, bitmapData, 0, bitmapDataSize); if (bufferState == 0x1) { controlStruct.buffer1 = buffer; frameChannel1 = channel; } else if (bufferState == 0x2) { controlStruct.buffer2 = buffer; frameChannel2 = channel; } // And finally, sending the modified control struct back to the shared memory. // Remember - we modified the buffer states at the behinning of this method. // We now need to let the other side know that we have finished with current // buffer and are basically ready for the next one. SendControlData(); return true; }
public FrameTransport() { sharedInfoSize = (uint)Marshal.SizeOf((Type)typeof(ControlChannelStruct)); haveFrame = false; bitmapData = null; bitmapDataSize = 0; frameChannel1 = null; frameChannel2 = null; controlStruct = new ControlChannelStruct(); controlStruct.bufferstates = 1; controlStruct.buffer1.bufid = -1; controlStruct.buffer2.bufid = -1; controlStruct.buffer1.clientpointer = 1; controlStruct.buffer2.clientpointer = 2; controlStruct.fourcccount = 0; controlStruct.buftype = BufferType.WinBuffers; // Mapping the control channel controlChannel = new SharedMemoryChannel(); bool success = controlChannel.CreateMapping(sharedInfoSize); if (!success) throw new Exception("Unable to create memory mapping for video frame transport"); // Opening the control channel for read-write controlChannel.OpenMapping(controlChannel.key); int error = Win32.GetLastError(); if (error != 0) throw new Exception("Unable to map memory for video frame transport"); }