Exemplo n.º 1
0
        public void Decode(H264ParameterSets Params, H264Matrices Matrices, byte[] FrameData)
        {
            Log2MaxPicOrderCntLsbMinus4 = Params.Log2MaxPicOrderCntLsbMinus4;
            DeltaPicOrderAlwaysZeroFlag = Params.DeltaPicOrderAlwaysZeroFlag;
            FrameMbsOnlyFlag            = Params.FrameMbsOnlyFlag;
            PicWidthInMbs         = Params.PicWidthInMbs;
            PicHeightInMapUnits   = Params.PicHeightInMapUnits;
            EntropyCodingModeFlag = Params.EntropyCodingModeFlag;
            BottomFieldPicOrderInFramePresentFlag = Params.BottomFieldPicOrderInFramePresentFlag;
            NumRefIdxL0DefaultActiveMinus1        = Params.NumRefIdxL0DefaultActiveMinus1;
            NumRefIdxL1DefaultActiveMinus1        = Params.NumRefIdxL1DefaultActiveMinus1;
            DeblockingFilterControlPresentFlag    = Params.DeblockingFilterControlPresentFlag;
            RedundantPicCntPresentFlag            = Params.RedundantPicCntPresentFlag;
            Transform8x8ModeFlag = Params.Transform8x8ModeFlag;

            MbAdaptiveFrameFieldFlag = ((Params.Flags >> 0) & 1) != 0;
            Direct8x8InferenceFlag   = ((Params.Flags >> 1) & 1) != 0;
            WeightedPredFlag         = ((Params.Flags >> 2) & 1) != 0;
            ConstrainedIntraPredFlag = ((Params.Flags >> 3) & 1) != 0;
            FieldPicFlag             = ((Params.Flags >> 5) & 1) != 0;
            BottomFieldFlag          = ((Params.Flags >> 6) & 1) != 0;

            Log2MaxFrameNumMinus4 = (int)(Params.Flags >> 8) & 0xf;
            ChromaFormatIdc       = (int)(Params.Flags >> 12) & 0x3;
            PicOrderCntType       = (int)(Params.Flags >> 14) & 0x3;
            PicInitQpMinus26      = (int)(Params.Flags >> 16) & 0x3f;
            ChromaQpIndexOffset   = (int)(Params.Flags >> 22) & 0x1f;
            ChromaQpIndexOffset2  = (int)(Params.Flags >> 27) & 0x1f;
            WeightedBipredIdc     = (int)(Params.Flags >> 32) & 0x3;
            FrameNumber           = (int)(Params.Flags >> 46) & 0x1ffff;

            PicInitQpMinus26     = (PicInitQpMinus26 << 26) >> 26;
            ChromaQpIndexOffset  = (ChromaQpIndexOffset << 27) >> 27;
            ChromaQpIndexOffset2 = (ChromaQpIndexOffset2 << 27) >> 27;

            ScalingMatrix4 = Matrices.ScalingMatrix4;
            ScalingMatrix8 = Matrices.ScalingMatrix8;

            if (FFmpegWrapper.IsInitialized)
            {
                FFmpegWrapper.DecodeFrame(FrameData);
            }
            else
            {
                FFmpegWrapper.H264Initialize();

                FFmpegWrapper.DecodeFrame(DecoderHelper.Combine(EncodeHeader(), FrameData));
            }
        }
Exemplo n.º 2
0
        public void Decode(
            Vp9FrameKeys keys,
            Vp9FrameHeader header,
            Vp9ProbabilityTables probs,
            byte[]               frameData)
        {
            bool isKeyFrame         = ((header.Flags >> 0) & 1) != 0;
            bool lastIsKeyFrame     = ((header.Flags >> 1) & 1) != 0;
            bool frameSizeChanged   = ((header.Flags >> 2) & 1) != 0;
            bool errorResilientMode = ((header.Flags >> 3) & 1) != 0;
            bool lastShowFrame      = ((header.Flags >> 4) & 1) != 0;
            bool isFrameIntra       = ((header.Flags >> 5) & 1) != 0;

            bool showFrame = !isFrameIntra;

            //Write compressed header.
            byte[] compressedHeaderData;

            using (MemoryStream compressedHeader = new MemoryStream())
            {
                VpxRangeEncoder writer = new VpxRangeEncoder(compressedHeader);

                if (!header.Lossless)
                {
                    if ((uint)header.TxMode >= 3)
                    {
                        writer.Write(3, 2);
                        writer.Write(header.TxMode == 4);
                    }
                    else
                    {
                        writer.Write(header.TxMode, 2);
                    }
                }

                if (header.TxMode == 4)
                {
                    WriteProbabilityUpdate(writer, probs.Tx8x8Probs, DefaultTx8x8Probs);
                    WriteProbabilityUpdate(writer, probs.Tx16x16Probs, DefaultTx16x16Probs);
                    WriteProbabilityUpdate(writer, probs.Tx32x32Probs, DefaultTx32x32Probs);
                }

                WriteCoefProbabilityUpdate(writer, header.TxMode, probs.CoefProbs, _defaultCoefProbs);

                WriteProbabilityUpdate(writer, probs.SkipProbs, _defaultSkipProbs);

                if (!isFrameIntra)
                {
                    WriteProbabilityUpdateAligned4(writer, probs.InterModeProbs, _defaultInterModeProbs);

                    if (header.RawInterpolationFilter == 4)
                    {
                        WriteProbabilityUpdate(writer, probs.InterpFilterProbs, _defaultInterpFilterProbs);
                    }

                    WriteProbabilityUpdate(writer, probs.IsInterProbs, _defaultIsInterProbs);

                    if ((header.RefFrameSignBias[1] & 1) != (header.RefFrameSignBias[2] & 1) ||
                        (header.RefFrameSignBias[1] & 1) != (header.RefFrameSignBias[3] & 1))
                    {
                        if ((uint)header.CompPredMode >= 1)
                        {
                            writer.Write(1, 1);
                            writer.Write(header.CompPredMode == 2);
                        }
                        else
                        {
                            writer.Write(0, 1);
                        }
                    }

                    if (header.CompPredMode == 2)
                    {
                        WriteProbabilityUpdate(writer, probs.CompModeProbs, _defaultCompModeProbs);
                    }

                    if (header.CompPredMode != 1)
                    {
                        WriteProbabilityUpdate(writer, probs.SingleRefProbs, _defaultSingleRefProbs);
                    }

                    if (header.CompPredMode != 0)
                    {
                        WriteProbabilityUpdate(writer, probs.CompRefProbs, _defaultCompRefProbs);
                    }

                    for (int index = 0; index < 4; index++)
                    {
                        int i = index * 8;
                        int j = index;

                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 0], _defaultYModeProbs0[i + 0]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 1], _defaultYModeProbs0[i + 1]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 2], _defaultYModeProbs0[i + 2]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 3], _defaultYModeProbs0[i + 3]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 4], _defaultYModeProbs0[i + 4]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 5], _defaultYModeProbs0[i + 5]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 6], _defaultYModeProbs0[i + 6]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs0[i + 7], _defaultYModeProbs0[i + 7]);
                        WriteProbabilityUpdate(writer, probs.YModeProbs1[j + 0], _defaultYModeProbs1[j + 0]);
                    }

                    WriteProbabilityUpdateAligned4(writer, probs.PartitionProbs, _defaultPartitionProbs);

                    for (int i = 0; i < 3; i++)
                    {
                        WriteMvProbabilityUpdate(writer, probs.MvJointProbs[i], _defaultMvJointProbs[i]);
                    }

                    for (int i = 0; i < 2; i++)
                    {
                        WriteMvProbabilityUpdate(writer, probs.MvSignProbs[i], _defaultMvSignProbs[i]);

                        for (int j = 0; j < 10; j++)
                        {
                            int index = i * 10 + j;

                            WriteMvProbabilityUpdate(writer, probs.MvClassProbs[index], _defaultMvClassProbs[index]);
                        }

                        WriteMvProbabilityUpdate(writer, probs.MvClass0BitProbs[i], _defaultMvClass0BitProbs[i]);

                        for (int j = 0; j < 10; j++)
                        {
                            int index = i * 10 + j;

                            WriteMvProbabilityUpdate(writer, probs.MvBitsProbs[index], _defaultMvBitsProbs[index]);
                        }
                    }

                    for (int i = 0; i < 2; i++)
                    {
                        for (int j = 0; j < 2; j++)
                        {
                            for (int k = 0; k < 3; k++)
                            {
                                int index = i * 2 * 3 + j * 3 + k;

                                WriteMvProbabilityUpdate(writer, probs.MvClass0FrProbs[index], _defaultMvClass0FrProbs[index]);
                            }
                        }

                        for (int j = 0; j < 3; j++)
                        {
                            int index = i * 3 + j;

                            WriteMvProbabilityUpdate(writer, probs.MvFrProbs[index], _defaultMvFrProbs[index]);
                        }
                    }

                    if (header.AllowHighPrecisionMv)
                    {
                        for (int index = 0; index < 2; index++)
                        {
                            WriteMvProbabilityUpdate(writer, probs.MvClass0HpProbs[index], _defaultMvClass0HpProbs[index]);
                            WriteMvProbabilityUpdate(writer, probs.MvHpProbs[index], _defaultMvHpProbs[index]);
                        }
                    }
                }

                writer.End();

                compressedHeaderData = compressedHeader.ToArray();
            }

            //Write uncompressed header.
            using (MemoryStream encodedHeader = new MemoryStream())
            {
                VpxBitStreamWriter writer = new VpxBitStreamWriter(encodedHeader);

                writer.WriteU(2, 2);    //Frame marker.
                writer.WriteU(0, 2);    //Profile.
                writer.WriteBit(false); //Show existing frame.
                writer.WriteBit(!isKeyFrame);
                writer.WriteBit(showFrame);
                writer.WriteBit(errorResilientMode);

                if (isKeyFrame)
                {
                    writer.WriteU(FrameSyncCode, 24);
                    writer.WriteU(0, 3); //Color space.
                    writer.WriteU(0, 1); //Color range.
                    writer.WriteU(header.CurrentFrame.Width - 1, 16);
                    writer.WriteU(header.CurrentFrame.Height - 1, 16);
                    writer.WriteBit(false); //Render and frame size different.

                    _cachedRefFrames.Clear();

                    //On key frames, all frame slots are set to the current frame,
                    //so the value of the selected slot doesn't really matter.
                    GetNewFrameSlot(keys.CurrKey);
                }
                else
                {
                    if (!showFrame)
                    {
                        writer.WriteBit(isFrameIntra);
                    }

                    if (!errorResilientMode)
                    {
                        writer.WriteU(0, 2); //Reset frame context.
                    }

                    int refreshFrameFlags = 1 << GetNewFrameSlot(keys.CurrKey);

                    if (isFrameIntra)
                    {
                        writer.WriteU(FrameSyncCode, 24);
                        writer.WriteU(refreshFrameFlags, 8);
                        writer.WriteU(header.CurrentFrame.Width - 1, 16);
                        writer.WriteU(header.CurrentFrame.Height - 1, 16);
                        writer.WriteBit(false); //Render and frame size different.
                    }
                    else
                    {
                        writer.WriteU(refreshFrameFlags, 8);

                        int[] refFrameIndex = new int[]
                        {
                            GetFrameSlot(keys.Ref0Key),
                            GetFrameSlot(keys.Ref1Key),
                            GetFrameSlot(keys.Ref2Key)
                        };

                        byte[] refFrameSignBias = header.RefFrameSignBias;

                        for (int index = 1; index < 4; index++)
                        {
                            writer.WriteU(refFrameIndex[index - 1], 3);
                            writer.WriteU(refFrameSignBias[index], 1);
                        }

                        writer.WriteBit(true);  //Frame size with refs.
                        writer.WriteBit(false); //Render and frame size different.
                        writer.WriteBit(header.AllowHighPrecisionMv);
                        writer.WriteBit(header.RawInterpolationFilter == 4);

                        if (header.RawInterpolationFilter != 4)
                        {
                            writer.WriteU(header.RawInterpolationFilter, 2);
                        }
                    }
                }

                if (!errorResilientMode)
                {
                    writer.WriteBit(false); //Refresh frame context.
                    writer.WriteBit(true);  //Frame parallel decoding mode.
                }

                writer.WriteU(0, 2); //Frame context index.

                writer.WriteU(header.LoopFilterLevel, 6);
                writer.WriteU(header.LoopFilterSharpness, 3);
                writer.WriteBit(header.LoopFilterDeltaEnabled);

                if (header.LoopFilterDeltaEnabled)
                {
                    bool[] updateLoopFilterRefDeltas  = new bool[4];
                    bool[] updateLoopFilterModeDeltas = new bool[2];

                    bool loopFilterDeltaUpdate = false;

                    for (int index = 0; index < header.LoopFilterRefDeltas.Length; index++)
                    {
                        sbyte old = _loopFilterRefDeltas[index];
                        sbyte New = header.LoopFilterRefDeltas[index];

                        loopFilterDeltaUpdate |= (updateLoopFilterRefDeltas[index] = old != New);
                    }

                    for (int index = 0; index < header.LoopFilterModeDeltas.Length; index++)
                    {
                        sbyte old = _loopFilterModeDeltas[index];
                        sbyte New = header.LoopFilterModeDeltas[index];

                        loopFilterDeltaUpdate |= (updateLoopFilterModeDeltas[index] = old != New);
                    }

                    writer.WriteBit(loopFilterDeltaUpdate);

                    if (loopFilterDeltaUpdate)
                    {
                        for (int index = 0; index < header.LoopFilterRefDeltas.Length; index++)
                        {
                            writer.WriteBit(updateLoopFilterRefDeltas[index]);

                            if (updateLoopFilterRefDeltas[index])
                            {
                                writer.WriteS(header.LoopFilterRefDeltas[index], 6);
                            }
                        }

                        for (int index = 0; index < header.LoopFilterModeDeltas.Length; index++)
                        {
                            writer.WriteBit(updateLoopFilterModeDeltas[index]);

                            if (updateLoopFilterModeDeltas[index])
                            {
                                writer.WriteS(header.LoopFilterModeDeltas[index], 6);
                            }
                        }
                    }
                }

                writer.WriteU(header.BaseQIndex, 8);

                writer.WriteDeltaQ(header.DeltaQYDc);
                writer.WriteDeltaQ(header.DeltaQUvDc);
                writer.WriteDeltaQ(header.DeltaQUvAc);

                writer.WriteBit(false); //Segmentation enabled (TODO).

                int minTileColsLog2 = CalcMinLog2TileCols(header.CurrentFrame.Width);
                int maxTileColsLog2 = CalcMaxLog2TileCols(header.CurrentFrame.Width);

                int tileColsLog2Diff = header.TileColsLog2 - minTileColsLog2;

                int tileColsLog2IncMask = (1 << tileColsLog2Diff) - 1;

                //If it's less than the maximum, we need to add an extra 0 on the bitstream
                //to indicate that it should stop reading.
                if (header.TileColsLog2 < maxTileColsLog2)
                {
                    writer.WriteU(tileColsLog2IncMask << 1, tileColsLog2Diff + 1);
                }
                else
                {
                    writer.WriteU(tileColsLog2IncMask, tileColsLog2Diff);
                }

                bool tileRowsLog2IsNonZero = header.TileRowsLog2 != 0;

                writer.WriteBit(tileRowsLog2IsNonZero);

                if (tileRowsLog2IsNonZero)
                {
                    writer.WriteBit(header.TileRowsLog2 > 1);
                }

                writer.WriteU(compressedHeaderData.Length, 16);

                writer.Flush();

                encodedHeader.Write(compressedHeaderData, 0, compressedHeaderData.Length);

                if (!FFmpegWrapper.IsInitialized)
                {
                    FFmpegWrapper.Vp9Initialize();
                }

                FFmpegWrapper.DecodeFrame(DecoderHelper.Combine(encodedHeader.ToArray(), frameData));
            }

            _loopFilterRefDeltas  = header.LoopFilterRefDeltas;
            _loopFilterModeDeltas = header.LoopFilterModeDeltas;
        }