Пример #1
0
        private void DecodePredictedFrame(Stream inStream, BitmapData currentData, BitmapData previousData, int pixelBytes)
        {
            int xBlocksCount = DivideRoundUp(frameWidth, MCBlockSize);
            int yBlocksCount = DivideRoundUp(frameHeight, MCBlockSize);

            MotionVector motionVector = MotionVector.ZERO;

            for (int yBlock = 0; yBlock < yBlocksCount; yBlock++)
            {
                for (int xBlock = 0; xBlock < xBlocksCount; xBlock++)
                {
                    int yStart = yBlock * MCBlockSize;
                    int xStart = xBlock * MCBlockSize;
                    // TODO: handle bad value
                    MCRecordType mcType = (MCRecordType)inStream.ReadUByte();
                    switch (mcType)
                    {
                        case MCRecordType.Identical:
                            DecodeTranslatedBlock(inStream, currentData, previousData, pixelBytes, yStart, xStart, MotionVector.ZERO);
                            break;
                        case MCRecordType.MotionVector:
                            motionVector.x = inStream.ReadSShort();
                            motionVector.y = inStream.ReadSShort();

                            DecodeTranslatedBlock(inStream, currentData, previousData, pixelBytes, yStart, xStart, motionVector);
                            break;
                        case MCRecordType.FullBlock:
                            DecodeFullBlock(inStream, currentData, previousData, pixelBytes, yStart, xStart);
                            break;
                    }
                }
            }
        }
Пример #2
0
        public Bitmap DecodeFrame(int frameIndex, Stream inStream)
        {
            if (inStream == null) return null;

            try
            {
                // Check the frame header:
                if (inStream.ReadUInt() != MAGIC_FRAME) return null;

                int encodedFrameIndex = inStream.ReadSShort();
                if (encodedFrameIndex != frameIndex) return null;

                BitmapData currentData = currentFrame.LockBits(
                    new Rectangle(0, 0, frameWidth, frameHeight),
                    ImageLockMode.ReadOnly, currentFrame.PixelFormat);
                BitmapData previousData = previousFrame.LockBits(
                    new Rectangle(0, 0, frameWidth, frameHeight),
                    ImageLockMode.ReadOnly, previousFrame.PixelFormat);

                if (VisualizeMCBlockTypes)
                {
                    debugFrame = new Bitmap(frameWidth, frameHeight, PixelFormat.Format24bppRgb);
                    debugFrameData = debugFrame.LockBits(
                        new Rectangle(0, 0, frameWidth, frameHeight),
                        ImageLockMode.ReadOnly, debugFrame.PixelFormat);
                }

                int pixelBytes = GetBytesPerPixel(currentFrame.PixelFormat);

                // TODO: handle bad value
                FrameType frameType = (FrameType)inStream.ReadUByte();
                switch (frameType)
                {
                    case FrameType.Intra:
                        DecodeIntraFrame(inStream, currentData, pixelBytes);
                        break;
                    case FrameType.Predicted:
                        DecodePredictedFrame(inStream, currentData, previousData, pixelBytes);
                        break;
                }

                currentFrame.UnlockBits(currentData);
                previousFrame.UnlockBits(previousData);

                if (VisualizeMCBlockTypes)
                {
                    debugFrame.UnlockBits(debugFrameData);
                    debugFrame.Save(String.Format("debug{0:000000}.png", frameIndex), ImageFormat.Png);
                    debugFrame.Dispose();
                }
            }
            catch (EndOfStreamException ex)
            {
                Log("Exception: {0} {1}", ex.Message, ex.StackTrace);
                return null;
            }

            Bitmap result = currentFrame;
            // double buffering
            // save the current bitmap to act as previous one when decoding the next frame
            SwapBitmaps(ref previousFrame, ref currentFrame);
            //currentFrame.Dispose();

            return result;
        }