public void FrameBlockJpegDeltaEncodingTest() { // ks 10/28/11 - This particular method doesn't really test anything, other than that everything runs without exceptions, // but it's a helpful little framework to have around when troubleshooting encoding issues, so I'll leave it here. const int offset = 20; var ctxFactory = new JpegFrameContextFactory(VideoConstants.VideoBlockSize, VideoConstants.VideoBlockSize); var oldFrame = new FrameBlock(ctxFactory) { BlockType = BlockType.Jpeg }; var newFrame = new FrameBlock(ctxFactory) { BlockType = BlockType.JpegDiff }; var newFrameWithJpeg = new FrameBlock(ctxFactory) { BlockType = BlockType.Jpeg }; for (int i = 0; i < oldFrame.RgbaRaw.Length; i++) { oldFrame.RgbaRaw[i] = (byte)i; newFrame.RgbaRaw[i] = (byte)(i + offset); newFrameWithJpeg.RgbaRaw[i] = (byte)(i + offset); } newFrame.SubtractFrom(oldFrame, double.MinValue, double.MaxValue); // Make some copies for later comparison var oldFrameOriginal = new byte[oldFrame.RgbaRaw.Length]; Buffer.BlockCopy(oldFrame.RgbaRaw, 0, oldFrameOriginal, 0, oldFrameOriginal.Length); var newFrameOriginal = new byte[newFrame.RgbaRaw.Length]; Buffer.BlockCopy(newFrame.RgbaRaw, 0, newFrameOriginal, 0, newFrameOriginal.Length); var newFrameDelta = new byte[newFrame.RgbaDelta.Length]; Buffer.BlockCopy(newFrame.RgbaDelta, 0, newFrameDelta, 0, newFrameDelta.Length); oldFrame.Encode(50); oldFrame.Decode(); newFrameWithJpeg.Encode(50); newFrameWithJpeg.Decode(); newFrame.Encode(50); newFrame.Decode(); newFrame.AddTo(oldFrame); int totalOldError = 0; int totalNewError = 0; int totalNewDeltaError = 0; int totalNewJpegError = 0; for (int i = 0; i < newFrameOriginal.Length; i++) { if (i % 4 != 3) { totalOldError += Math.Abs(oldFrame.RgbaRaw[i] - oldFrameOriginal[i]); totalNewError += Math.Abs(newFrame.RgbaRaw[i] - newFrameOriginal[i]); totalNewDeltaError += Math.Abs(newFrame.RgbaDelta[i] - newFrameDelta[i]); totalNewJpegError += Math.Abs(newFrameWithJpeg.RgbaRaw[i] - newFrameOriginal[i]); Debug.WriteLine("OLD: Original: {0}; Encoded: {1}; Error: {2}; NEWJPEG: Original: {3}; Encoded: {4}; Error: {5}", oldFrameOriginal[i], oldFrame.RgbaRaw[i], Math.Abs(oldFrameOriginal[i] - oldFrame.RgbaRaw[i]), newFrameOriginal[i], newFrameWithJpeg.RgbaRaw[i], Math.Abs(newFrameOriginal[i] - newFrameWithJpeg.RgbaRaw[i])); // Assert.IsTrue(diff < 2); //if (oldError > 2) //{ // Debug.WriteLine("JPEG: Original:{0}, Encoded:{1}, Error:{2}", oldFrameOriginal[i], oldFrame.RgbaRaw[i], oldError); //} // Assert.IsTrue(diff < 2); //if (newError > 2) //{ // Debug.WriteLine("JPEGDIFF: Original:{0}, Encoded:{1}, Error:{2}", newFrameOriginal[i], newFrame.RgbaRaw[i], newError); //} } } double samples = oldFrameOriginal.Length * .75; double averageOldError = totalOldError / samples; double averageNewError = totalNewError / samples; double averageNewDeltaError = totalNewDeltaError / samples; double averageNewJpegError = totalNewJpegError / samples; Debug.WriteLine("old error: {0:0.00}; new error: {1:0.00}; new delta error: {2:0.00}; new with jpeg error: {3:0.00}", averageOldError, averageNewError, averageNewDeltaError, averageNewJpegError); }
private void EncodeAndDecodeImages() { // Encode and decode a delta (p-frame) image. var ctxFactory = new JpegFrameContextFactory(VideoConstants.Height, VideoConstants.Width); var remoteSourceBlock = new FrameBlock(ctxFactory) { BlockType = BlockType.Jpeg }; Buffer.BlockCopy(mRawFrames[0], 0, remoteSourceBlock.RgbaRaw, 0, mRawFrames[0].Length); remoteSourceBlock.Encode(jpegQuality); remoteSourceBlock.Decode(); var imgJpegDeltaFrame0 = new Image(); SetImage(imgJpegDeltaFrame0, mRawFrames[0], remoteSourceBlock.RgbaRaw, remoteSourceBlock.EncodedStream.Length); lstJpegDeltaFrames.Items.Clear(); lstJpegDeltaFrames.Items.Add(imgJpegDeltaFrame0); int frames = Math.Min(mRawFrames.Count, 20); for (int i = 1; i < frames; i++) { // Create a new source block, since we need to start with one that hasn't been encoded yet. var localSourceBlock = new FrameBlock(ctxFactory) { BlockType = BlockType.Jpeg }; Buffer.BlockCopy(mRawFrames[i - 1], 0, localSourceBlock.RgbaRaw, 0, mRawFrames[i - 1].Length); // Create the delta block based on the local source block (which has the raw data). var deltaFrameBlock = new FrameBlock(ctxFactory) { BlockType = BlockType.JpegDiff }; Buffer.BlockCopy(mRawFrames[i], 0, deltaFrameBlock.RgbaRaw, 0, mRawFrames[i].Length); deltaFrameBlock.SubtractFrom(localSourceBlock, double.MinValue, double.MaxValue); deltaFrameBlock.Encode(jpegQuality); // Decode the delta block off of the remote source block (which has the cumulative encoded/decoded data) deltaFrameBlock.Decode(); deltaFrameBlock.AddTo(remoteSourceBlock); // Add the image to the UI. var img = new Image(); SetImage(img, mRawFrames[i], deltaFrameBlock.RgbaRaw, deltaFrameBlock.EncodedStream.Length); lstJpegDeltaFrames.Items.Add(img); // Set the remote source block to the most recently processed delta block for the next loop. remoteSourceBlock = deltaFrameBlock; } // Get the initial image and display it. SetImage(imgRawFrame0, mRawFrames[0], mRawFrames[0], mRawFrames[0].Length); SetImage(imgRawFrame1, mRawFrames[1], mRawFrames[1], mRawFrames[0].Length); // Encode and decode two images using the FJCore Jpeg library. var stream = EncodeJpeg(mRawFrames[0]); stream.Position = 0; var jpegOutputBmp = DecodeJpeg(stream); SetImage(imgJpegFrame0, mRawFrames[0], jpegOutputBmp, stream.Length); stream = EncodeJpeg(mRawFrames[1]); stream.Position = 0; jpegOutputBmp = DecodeJpeg(stream); SetImage(imgJpegFrame1, mRawFrames[1], jpegOutputBmp, stream.Length); // Encode and decode two images using the JpegFrame extensions to the FJCore Jpeg library. var frameBlock0 = new FrameBlock(ctxFactory); Buffer.BlockCopy(mRawFrames[0], 0, frameBlock0.RgbaRaw, 0, mRawFrames[0].Length); frameBlock0.Encode(jpegQuality); frameBlock0.Decode(); SetImage(imgJpegFrameFrame0, mRawFrames[0], frameBlock0.RgbaRaw, frameBlock0.EncodedStream.Length); var frameBlock1 = new FrameBlock(ctxFactory); Buffer.BlockCopy(mRawFrames[1], 0, frameBlock1.RgbaRaw, 0, mRawFrames[1].Length); frameBlock1.Encode(jpegQuality); frameBlock1.Decode(); SetImage(imgJpegFrameFrame1, mRawFrames[1], frameBlock1.RgbaRaw, frameBlock1.EncodedStream.Length); }