private DmxFrame ReadFrame(BinaryReader binRead) { var target = new DmxFrame(); target.Start = binRead.ReadByte(); target.TimestampMS = (uint)binRead.ReadInt32(); target.Universe = (ushort)binRead.ReadInt16(); switch (target.Start) { case 1: target.Len = (ushort)binRead.ReadInt16(); target.Data = binRead.ReadBytes(target.Len); break; case 2: break; default: throw new ArgumentException("Invalid data"); } target.End = binRead.ReadByte(); if (target.End != 4) { throw new ArgumentException("Invalid data"); } return(target); }
private void OutputData(DmxFrame dmxFrame, Bitmap bitmap, Rectangle bitmapRect, int stride) { int[] mapping; if (dmxFrame.Data != null && this.pixelMapping.TryGetValue(dmxFrame.Universe, out mapping)) { BitmapData bitmapData = bitmap.LockBits(bitmapRect, ImageLockMode.WriteOnly, bitmap.PixelFormat); int maxLen = Math.Min(dmxFrame.Data.Length, mapping.Length * 3); for (int pos = 0; pos < maxLen; pos++) { int bytePos = mapping[pos]; if (bytePos >= 0 && bytePos < this.rgbValues.Length) { this.rgbValues[bytePos] = dmxFrame.Data[pos]; } } System.Runtime.InteropServices.Marshal.Copy(this.rgbValues, 0, bitmapData.Scan0, this.rgbValues.Length); bitmap.UnlockBits(bitmapData); } if (dmxFrame.Universe == this.triggerSyncOnUniverse) { this.device.PushOutput(this.sub.Token); } }
public DmxPlayback([System.Runtime.CompilerServices.CallerMemberName] string name = "") { this.name = name; this.sub = new Subroutine("SUB_" + this.name); this.watch = new Stopwatch(); this.pixelMapping = new Dictionary <int, int[]>(); long timestampOffset = 0; this.sub.RunAction(ins => { var bitmap = (Bitmap)this.device.GetFrameBuffer(this.sub.Token, this.device)[DataElements.PixelBitmap]; if (bitmap.Width != this.pixelWidth || bitmap.Height != this.pixelHeight) { throw new ArgumentException("Invalid bitmap size"); } var bitmapRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8; int stride = 4 * ((bitmap.Width * bytesPerPixel + 3) / 4); int byteCount = stride * bitmap.Height; this.rgbValues = new byte[byteCount]; do { // See if we should restart if (this.file.Position >= this.file.Length) { // Restart this.file.Position = 0; this.dmxFrame = null; this.watch.Reset(); } if (this.dmxFrame == null) { this.dmxFrame = ReadFrame(this.binRead); timestampOffset = this.dmxFrame.TimestampMS; } this.watch.Start(); while (!ins.IsCancellationRequested && this.file.Position < this.file.Length) { // Calculate when the next stop is this.nextStop = this.dmxFrame.TimestampMS - timestampOffset; long msLeft = this.nextStop - this.watch.ElapsedMilliseconds; if (msLeft <= 0) { // Output OutputData(this.dmxFrame, bitmap, bitmapRect, stride); // Read next frame this.dmxFrame = ReadFrame(this.binRead); continue; } else if (msLeft < 16) { SpinWait.SpinUntil(() => this.watch.ElapsedMilliseconds >= this.nextStop); continue; } Thread.Sleep(1); } } while (!ins.IsCancellationRequested && this.loop); this.watch.Stop(); }); }