private void colorReplay_FrameArrived(ReplayColorFrame frame) { if (ColorFrameArrived != null) { ColorFrameArrived(this, new ReplayFrameArrivedEventArgs <ReplayColorFrame> { Frame = frame }); } }
/// <summary> /// Adds a frame to the Frames list. /// </summary> /// <param name="reader">The reader.</param> public void AddFrame(BinaryReader reader) { var frame = ReplayColorFrame.FromReader(reader, _codec); if (frame != null) { this.Frames.Add(frame); } }
/// <summary> /// Export all of the frames in this /// </summary> /// <param name="exportDir"></param> public async Task ExportColorFramesAsync(string exportDir) { if (!this.HasColorFrames || _colorReplay == null) { throw new InvalidOperationException("KDVR file has no color frames."); } int frameCounter = 0; var jpegCodec = ColorCodecs.Jpeg; var jpegCodecId = jpegCodec.CodecId; var lastRelativeTime = TimeSpan.MaxValue; foreach (var frame in _colorReplay.Frames) { ReplayColorFrame rcf = frame as ReplayColorFrame; var elapsed = rcf.RelativeTime - lastRelativeTime; lastRelativeTime = rcf.RelativeTime; var numFrames = 1; var mills = (int)Math.Ceiling(elapsed.TotalMilliseconds); if (mills > 60) { numFrames = mills / 33; } for (int i = 0; i < numFrames; i++) { var fileName = string.Format("\\{0:000000}.jpeg", frameCounter++); #if NETFX_CORE var file = await StorageFile.GetFileFromPathAsync(exportDir + fileName); using (var jpegStream = await file.OpenStreamForWriteAsync()) #else using (var jpegStream = new FileStream(exportDir + fileName, FileMode.Create, FileAccess.Write)) #endif { using (var jpegWriter = new BinaryWriter(jpegStream)) { var bytes = rcf.GetRawFrameData(); if (rcf.Codec.CodecId == jpegCodecId) { jpegWriter.Write(bytes); } else { await jpegCodec.EncodeAsync(bytes, jpegWriter); } } } } } }
/// <summary> /// Initializes a new instance of the <see cref="ReplayColorFrame"/> class /// by reading from the specified <c>BinaryReader</c> using the specified /// <c>IColorCodec</c>. /// </summary> /// <param name="reader">The reader.</param> /// <param name="codec">The codec.</param> /// <returns>The <c>ReplayColorFrame</c></returns> /// <exception cref="System.IO.IOException">The recording appears to be corrupt.</exception> public static ReplayColorFrame FromReader(BinaryReader reader, IColorCodec codec) { var frame = new ReplayColorFrame(); frame.FrameType = FrameTypes.Color; frame.RelativeTime = TimeSpan.FromMilliseconds(reader.ReadDouble()); frame.FrameSize = reader.ReadInt64(); long frameStartPos = reader.BaseStream.Position; frame.Codec = codec; frame.Codec.ReadHeader(reader, frame); frame.Stream = reader.BaseStream; frame.StreamPosition = frame.Stream.Position; frame.Stream.Position += frame.FrameDataSize; // Do Frame Integrity Check var isGoodFrame = false; try { if (reader.ReadString() == ReplayFrame.EndOfFrameMarker) { isGoodFrame = true; } } catch { } if (!isGoodFrame) { System.Diagnostics.Debug.WriteLine("BAD FRAME...RESETTING"); reader.BaseStream.Position = frameStartPos + frame.FrameSize; try { if (reader.ReadString() != ReplayFrame.EndOfFrameMarker) { throw new IOException("The recording appears to be corrupt."); } return(null); } catch { throw new IOException("The recording appears to be corrupt."); } } return(frame); }
/// <summary> /// Initializes a new instance of the <see cref="ColorFrameBitmap" /> class /// suitable for displaying the supplied <see cref="ReplayColorFrame" />. /// </summary> /// <param name="frame">The frame.</param> public ColorFrameBitmap(ReplayColorFrame frame) { #if NETFX_CORE _bitmap = BitmapFactory.New(frame.Width, frame.Height); _bytes = new byte[_bitmap.PixelWidth * _bitmap.PixelHeight * 4]; _stream = _bitmap.PixelBuffer.AsStream(); #else // force population of PixelFormat var data = frame.GetFrameDataAsync().Result; _bitmap = new WriteableBitmap(frame.Width, frame.Height, 96, 96, frame.Codec.PixelFormat, null); _bytes = new byte[_bitmap.PixelWidth * _bitmap.PixelHeight * (_bitmap.Format.BitsPerPixel / 8)]; _dirtyRect = new Int32Rect(0, 0, frame.Width, frame.Height); #endif }
/// <summary> /// Records a <c>ReplayColorFrame</c>. /// </summary> /// <param name="frame">The frame.</param> public async Task RecordAsync(ReplayColorFrame frame) { if (_writer.BaseStream == null || _writer.BaseStream.CanWrite == false) { return; } _isStarted = true; try { // Header _writer.Write((int)frame.FrameType); _writer.Write(frame.RelativeTime.TotalMilliseconds); // Data using (var dataStream = new MemoryStream()) { using (var dataWriter = new BinaryWriter(dataStream)) { _codec.Width = frame.Width; _codec.Height = frame.Height; await _codec.EncodeAsync(frame.FrameData, dataWriter); // Reset frame data stream dataWriter.Flush(); dataStream.Position = 0; // Write FrameSize _writer.Write(dataStream.Length); // Write actual frame data dataStream.CopyTo(_writer.BaseStream); // Write end of frame marker _writer.Write(ReplayFrame.EndOfFrameMarker); } } } catch (Exception ex) { // TODO: Change to log the error System.Diagnostics.Debug.WriteLine(ex); } }
/// <summary> /// Records a <c>ReplayColorFrame</c>. /// </summary> /// <param name="frame">The frame.</param> public async Task RecordAsync(ReplayColorFrame frame) { if (_writer.BaseStream == null || _writer.BaseStream.CanWrite == false) return; _isStarted = true; try { // Header _writer.Write((int)frame.FrameType); _writer.Write(frame.RelativeTime.TotalMilliseconds); // Data using (var dataStream = new MemoryStream()) { using (var dataWriter = new BinaryWriter(dataStream)) { _codec.Width = frame.Width; _codec.Height = frame.Height; await _codec.EncodeAsync(frame.FrameData, dataWriter); // Reset frame data stream dataWriter.Flush(); dataStream.Position = 0; // Write FrameSize _writer.Write(dataStream.Length); // Write actual frame data dataStream.CopyTo(_writer.BaseStream); // Write end of frame marker _writer.Write(ReplayFrame.EndOfFrameMarker); } } } catch (Exception ex) { // TODO: Change to log the error System.Diagnostics.Debug.WriteLine(ex); } }
/// <summary> /// Initializes a new instance of the <see cref="ReplayColorFrame"/> class /// by reading from the specified <c>BinaryReader</c> using the specified /// <c>IColorCodec</c>. /// </summary> /// <param name="reader">The reader.</param> /// <param name="codec">The codec.</param> /// <returns>The <c>ReplayColorFrame</c></returns> /// <exception cref="System.IO.IOException">The recording appears to be corrupt.</exception> internal static ReplayColorFrame FromReader(BinaryReader reader, IColorCodec codec) { var frame = new ReplayColorFrame(); frame.FrameType = FrameTypes.Color; frame.RelativeTime = TimeSpan.FromMilliseconds(reader.ReadDouble()); frame.FrameSize = reader.ReadInt64(); long frameStartPos = reader.BaseStream.Position; frame.Codec = codec; frame.Codec.ReadHeader(reader, frame); frame.Stream = reader.BaseStream; frame.StreamPosition = frame.Stream.Position; frame.Stream.Position += frame.FrameDataSize; // Do Frame Integrity Check var isGoodFrame = false; try { if (reader.ReadString() == ReplayFrame.EndOfFrameMarker) { isGoodFrame = true; } } catch { } if (!isGoodFrame) { System.Diagnostics.Debug.WriteLine("BAD FRAME...RESETTING"); reader.BaseStream.Position = frameStartPos + frame.FrameSize; try { if (reader.ReadString() != ReplayFrame.EndOfFrameMarker) { throw new IOException("The recording appears to be corrupt."); } return null; } catch { throw new IOException("The recording appears to be corrupt."); } } return frame; }
/// <summary> /// Update the Bitmap from the supplied <c>ReplayColorFrame</c>. /// </summary> public void Update(ReplayColorFrame frame) { if (frame != null) { frame.GetFrameDataAsync().ContinueWith(async (pixels) => { #if NETFX_CORE await _bitmap.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { _stream.Seek(0, SeekOrigin.Begin); _stream.Write(pixels.Result, 0, pixels.Result.Length); _bitmap.Invalidate(); }); #else await _bitmap.Dispatcher.InvokeAsync(() => { _bitmap.FromByteArray(pixels.Result); }); #endif }); } }
private void colorReplay_FrameArrived(ReplayColorFrame frame) { if (ColorFrameArrived != null) ColorFrameArrived(this, new ReplayFrameArrivedEventArgs<ReplayColorFrame> { Frame = frame }); }