| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- using System.IO;
- namespace Ryujinx.Graphics.VDec
- {
- class H264Decoder
- {
- private int Log2MaxPicOrderCntLsbMinus4;
- private bool DeltaPicOrderAlwaysZeroFlag;
- private bool FrameMbsOnlyFlag;
- private int PicWidthInMbs;
- private int PicHeightInMapUnits;
- private bool EntropyCodingModeFlag;
- private bool BottomFieldPicOrderInFramePresentFlag;
- private int NumRefIdxL0DefaultActiveMinus1;
- private int NumRefIdxL1DefaultActiveMinus1;
- private bool DeblockingFilterControlPresentFlag;
- private bool RedundantPicCntPresentFlag;
- private bool Transform8x8ModeFlag;
- private bool MbAdaptiveFrameFieldFlag;
- private bool Direct8x8InferenceFlag;
- private bool WeightedPredFlag;
- private bool ConstrainedIntraPredFlag;
- private bool FieldPicFlag;
- private bool BottomFieldFlag;
- private int Log2MaxFrameNumMinus4;
- private int ChromaFormatIdc;
- private int PicOrderCntType;
- private int PicInitQpMinus26;
- private int ChromaQpIndexOffset;
- private int ChromaQpIndexOffset2;
- private int WeightedBipredIdc;
- private int FrameNumber;
- private byte[] ScalingMatrix4;
- private byte[] ScalingMatrix8;
- 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));
- }
- }
- private byte[] EncodeHeader()
- {
- using (MemoryStream Data = new MemoryStream())
- {
- H264BitStreamWriter Writer = new H264BitStreamWriter(Data);
- //Sequence Parameter Set.
- Writer.WriteU(1, 24);
- Writer.WriteU(0, 1);
- Writer.WriteU(3, 2);
- Writer.WriteU(7, 5);
- Writer.WriteU(100, 8);
- Writer.WriteU(0, 8);
- Writer.WriteU(31, 8);
- Writer.WriteUe(0);
- Writer.WriteUe(ChromaFormatIdc);
- if (ChromaFormatIdc == 3)
- {
- Writer.WriteBit(false);
- }
- Writer.WriteUe(0);
- Writer.WriteUe(0);
- Writer.WriteBit(false);
- Writer.WriteBit(false); //Scaling matrix present flag
- Writer.WriteUe(Log2MaxFrameNumMinus4);
- Writer.WriteUe(PicOrderCntType);
- if (PicOrderCntType == 0)
- {
- Writer.WriteUe(Log2MaxPicOrderCntLsbMinus4);
- }
- else if (PicOrderCntType == 1)
- {
- Writer.WriteBit(DeltaPicOrderAlwaysZeroFlag);
- Writer.WriteSe(0);
- Writer.WriteSe(0);
- Writer.WriteUe(0);
- }
- int PicHeightInMbs = PicHeightInMapUnits / (FrameMbsOnlyFlag ? 1 : 2);
- Writer.WriteUe(16);
- Writer.WriteBit(false);
- Writer.WriteUe(PicWidthInMbs - 1);
- Writer.WriteUe(PicHeightInMbs - 1);
- Writer.WriteBit(FrameMbsOnlyFlag);
- if (!FrameMbsOnlyFlag)
- {
- Writer.WriteBit(MbAdaptiveFrameFieldFlag);
- }
- Writer.WriteBit(Direct8x8InferenceFlag);
- Writer.WriteBit(false); //Frame cropping flag
- Writer.WriteBit(false); //VUI parameter present flag
- Writer.End();
- //Picture Parameter Set.
- Writer.WriteU(1, 24);
- Writer.WriteU(0, 1);
- Writer.WriteU(3, 2);
- Writer.WriteU(8, 5);
- Writer.WriteUe(0);
- Writer.WriteUe(0);
- Writer.WriteBit(EntropyCodingModeFlag);
- Writer.WriteBit(false);
- Writer.WriteUe(0);
- Writer.WriteUe(NumRefIdxL0DefaultActiveMinus1);
- Writer.WriteUe(NumRefIdxL1DefaultActiveMinus1);
- Writer.WriteBit(WeightedPredFlag);
- Writer.WriteU(WeightedBipredIdc, 2);
- Writer.WriteSe(PicInitQpMinus26);
- Writer.WriteSe(0);
- Writer.WriteSe(ChromaQpIndexOffset);
- Writer.WriteBit(DeblockingFilterControlPresentFlag);
- Writer.WriteBit(ConstrainedIntraPredFlag);
- Writer.WriteBit(RedundantPicCntPresentFlag);
- Writer.WriteBit(Transform8x8ModeFlag);
- Writer.WriteBit(true);
- for (int Index = 0; Index < 6; Index++)
- {
- Writer.WriteBit(true);
- WriteScalingList(Writer, ScalingMatrix4, Index * 16, 16);
- }
- if (Transform8x8ModeFlag)
- {
- for (int Index = 0; Index < 2; Index++)
- {
- Writer.WriteBit(true);
- WriteScalingList(Writer, ScalingMatrix8, Index * 64, 64);
- }
- }
- Writer.WriteSe(ChromaQpIndexOffset2);
- Writer.End();
- return Data.ToArray();
- }
- }
- //ZigZag LUTs from libavcodec.
- private static readonly byte[] ZigZagDirect = new byte[]
- {
- 0, 1, 8, 16, 9, 2, 3, 10,
- 17, 24, 32, 25, 18, 11, 4, 5,
- 12, 19, 26, 33, 40, 48, 41, 34,
- 27, 20, 13, 6, 7, 14, 21, 28,
- 35, 42, 49, 56, 57, 50, 43, 36,
- 29, 22, 15, 23, 30, 37, 44, 51,
- 58, 59, 52, 45, 38, 31, 39, 46,
- 53, 60, 61, 54, 47, 55, 62, 63
- };
- private static readonly byte[] ZigZagScan = new byte[]
- {
- 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
- 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
- 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
- 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4
- };
- private static void WriteScalingList(H264BitStreamWriter Writer, byte[] List, int Start, int Count)
- {
- byte[] Scan = Count == 16 ? ZigZagScan : ZigZagDirect;
- int LastScale = 8;
- for (int Index = 0; Index < Count; Index++)
- {
- byte Value = List[Start + Scan[Index]];
- int DeltaScale = Value - LastScale;
- Writer.WriteSe(DeltaScale);
- LastScale = Value;
- }
- }
- }
- }
|