H264Decoder.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System.IO;
  2. namespace Ryujinx.Graphics.VDec
  3. {
  4. class H264Decoder
  5. {
  6. private int Log2MaxPicOrderCntLsbMinus4;
  7. private bool DeltaPicOrderAlwaysZeroFlag;
  8. private bool FrameMbsOnlyFlag;
  9. private int PicWidthInMbs;
  10. private int PicHeightInMapUnits;
  11. private bool EntropyCodingModeFlag;
  12. private bool BottomFieldPicOrderInFramePresentFlag;
  13. private int NumRefIdxL0DefaultActiveMinus1;
  14. private int NumRefIdxL1DefaultActiveMinus1;
  15. private bool DeblockingFilterControlPresentFlag;
  16. private bool RedundantPicCntPresentFlag;
  17. private bool Transform8x8ModeFlag;
  18. private bool MbAdaptiveFrameFieldFlag;
  19. private bool Direct8x8InferenceFlag;
  20. private bool WeightedPredFlag;
  21. private bool ConstrainedIntraPredFlag;
  22. private bool FieldPicFlag;
  23. private bool BottomFieldFlag;
  24. private int Log2MaxFrameNumMinus4;
  25. private int ChromaFormatIdc;
  26. private int PicOrderCntType;
  27. private int PicInitQpMinus26;
  28. private int ChromaQpIndexOffset;
  29. private int ChromaQpIndexOffset2;
  30. private int WeightedBipredIdc;
  31. private int FrameNumber;
  32. private byte[] ScalingMatrix4;
  33. private byte[] ScalingMatrix8;
  34. public void Decode(H264ParameterSets Params, H264Matrices Matrices, byte[] FrameData)
  35. {
  36. Log2MaxPicOrderCntLsbMinus4 = Params.Log2MaxPicOrderCntLsbMinus4;
  37. DeltaPicOrderAlwaysZeroFlag = Params.DeltaPicOrderAlwaysZeroFlag;
  38. FrameMbsOnlyFlag = Params.FrameMbsOnlyFlag;
  39. PicWidthInMbs = Params.PicWidthInMbs;
  40. PicHeightInMapUnits = Params.PicHeightInMapUnits;
  41. EntropyCodingModeFlag = Params.EntropyCodingModeFlag;
  42. BottomFieldPicOrderInFramePresentFlag = Params.BottomFieldPicOrderInFramePresentFlag;
  43. NumRefIdxL0DefaultActiveMinus1 = Params.NumRefIdxL0DefaultActiveMinus1;
  44. NumRefIdxL1DefaultActiveMinus1 = Params.NumRefIdxL1DefaultActiveMinus1;
  45. DeblockingFilterControlPresentFlag = Params.DeblockingFilterControlPresentFlag;
  46. RedundantPicCntPresentFlag = Params.RedundantPicCntPresentFlag;
  47. Transform8x8ModeFlag = Params.Transform8x8ModeFlag;
  48. MbAdaptiveFrameFieldFlag = ((Params.Flags >> 0) & 1) != 0;
  49. Direct8x8InferenceFlag = ((Params.Flags >> 1) & 1) != 0;
  50. WeightedPredFlag = ((Params.Flags >> 2) & 1) != 0;
  51. ConstrainedIntraPredFlag = ((Params.Flags >> 3) & 1) != 0;
  52. FieldPicFlag = ((Params.Flags >> 5) & 1) != 0;
  53. BottomFieldFlag = ((Params.Flags >> 6) & 1) != 0;
  54. Log2MaxFrameNumMinus4 = (int)(Params.Flags >> 8) & 0xf;
  55. ChromaFormatIdc = (int)(Params.Flags >> 12) & 0x3;
  56. PicOrderCntType = (int)(Params.Flags >> 14) & 0x3;
  57. PicInitQpMinus26 = (int)(Params.Flags >> 16) & 0x3f;
  58. ChromaQpIndexOffset = (int)(Params.Flags >> 22) & 0x1f;
  59. ChromaQpIndexOffset2 = (int)(Params.Flags >> 27) & 0x1f;
  60. WeightedBipredIdc = (int)(Params.Flags >> 32) & 0x3;
  61. FrameNumber = (int)(Params.Flags >> 46) & 0x1ffff;
  62. PicInitQpMinus26 = (PicInitQpMinus26 << 26) >> 26;
  63. ChromaQpIndexOffset = (ChromaQpIndexOffset << 27) >> 27;
  64. ChromaQpIndexOffset2 = (ChromaQpIndexOffset2 << 27) >> 27;
  65. ScalingMatrix4 = Matrices.ScalingMatrix4;
  66. ScalingMatrix8 = Matrices.ScalingMatrix8;
  67. if (FFmpegWrapper.IsInitialized)
  68. {
  69. FFmpegWrapper.DecodeFrame(FrameData);
  70. }
  71. else
  72. {
  73. FFmpegWrapper.H264Initialize();
  74. FFmpegWrapper.DecodeFrame(DecoderHelper.Combine(EncodeHeader(), FrameData));
  75. }
  76. }
  77. private byte[] EncodeHeader()
  78. {
  79. using (MemoryStream Data = new MemoryStream())
  80. {
  81. H264BitStreamWriter Writer = new H264BitStreamWriter(Data);
  82. //Sequence Parameter Set.
  83. Writer.WriteU(1, 24);
  84. Writer.WriteU(0, 1);
  85. Writer.WriteU(3, 2);
  86. Writer.WriteU(7, 5);
  87. Writer.WriteU(100, 8);
  88. Writer.WriteU(0, 8);
  89. Writer.WriteU(31, 8);
  90. Writer.WriteUe(0);
  91. Writer.WriteUe(ChromaFormatIdc);
  92. if (ChromaFormatIdc == 3)
  93. {
  94. Writer.WriteBit(false);
  95. }
  96. Writer.WriteUe(0);
  97. Writer.WriteUe(0);
  98. Writer.WriteBit(false);
  99. Writer.WriteBit(false); //Scaling matrix present flag
  100. Writer.WriteUe(Log2MaxFrameNumMinus4);
  101. Writer.WriteUe(PicOrderCntType);
  102. if (PicOrderCntType == 0)
  103. {
  104. Writer.WriteUe(Log2MaxPicOrderCntLsbMinus4);
  105. }
  106. else if (PicOrderCntType == 1)
  107. {
  108. Writer.WriteBit(DeltaPicOrderAlwaysZeroFlag);
  109. Writer.WriteSe(0);
  110. Writer.WriteSe(0);
  111. Writer.WriteUe(0);
  112. }
  113. int PicHeightInMbs = PicHeightInMapUnits / (FrameMbsOnlyFlag ? 1 : 2);
  114. Writer.WriteUe(16);
  115. Writer.WriteBit(false);
  116. Writer.WriteUe(PicWidthInMbs - 1);
  117. Writer.WriteUe(PicHeightInMbs - 1);
  118. Writer.WriteBit(FrameMbsOnlyFlag);
  119. if (!FrameMbsOnlyFlag)
  120. {
  121. Writer.WriteBit(MbAdaptiveFrameFieldFlag);
  122. }
  123. Writer.WriteBit(Direct8x8InferenceFlag);
  124. Writer.WriteBit(false); //Frame cropping flag
  125. Writer.WriteBit(false); //VUI parameter present flag
  126. Writer.End();
  127. //Picture Parameter Set.
  128. Writer.WriteU(1, 24);
  129. Writer.WriteU(0, 1);
  130. Writer.WriteU(3, 2);
  131. Writer.WriteU(8, 5);
  132. Writer.WriteUe(0);
  133. Writer.WriteUe(0);
  134. Writer.WriteBit(EntropyCodingModeFlag);
  135. Writer.WriteBit(false);
  136. Writer.WriteUe(0);
  137. Writer.WriteUe(NumRefIdxL0DefaultActiveMinus1);
  138. Writer.WriteUe(NumRefIdxL1DefaultActiveMinus1);
  139. Writer.WriteBit(WeightedPredFlag);
  140. Writer.WriteU(WeightedBipredIdc, 2);
  141. Writer.WriteSe(PicInitQpMinus26);
  142. Writer.WriteSe(0);
  143. Writer.WriteSe(ChromaQpIndexOffset);
  144. Writer.WriteBit(DeblockingFilterControlPresentFlag);
  145. Writer.WriteBit(ConstrainedIntraPredFlag);
  146. Writer.WriteBit(RedundantPicCntPresentFlag);
  147. Writer.WriteBit(Transform8x8ModeFlag);
  148. Writer.WriteBit(true);
  149. for (int Index = 0; Index < 6; Index++)
  150. {
  151. Writer.WriteBit(true);
  152. WriteScalingList(Writer, ScalingMatrix4, Index * 16, 16);
  153. }
  154. if (Transform8x8ModeFlag)
  155. {
  156. for (int Index = 0; Index < 2; Index++)
  157. {
  158. Writer.WriteBit(true);
  159. WriteScalingList(Writer, ScalingMatrix8, Index * 64, 64);
  160. }
  161. }
  162. Writer.WriteSe(ChromaQpIndexOffset2);
  163. Writer.End();
  164. return Data.ToArray();
  165. }
  166. }
  167. //ZigZag LUTs from libavcodec.
  168. private static readonly byte[] ZigZagDirect = new byte[]
  169. {
  170. 0, 1, 8, 16, 9, 2, 3, 10,
  171. 17, 24, 32, 25, 18, 11, 4, 5,
  172. 12, 19, 26, 33, 40, 48, 41, 34,
  173. 27, 20, 13, 6, 7, 14, 21, 28,
  174. 35, 42, 49, 56, 57, 50, 43, 36,
  175. 29, 22, 15, 23, 30, 37, 44, 51,
  176. 58, 59, 52, 45, 38, 31, 39, 46,
  177. 53, 60, 61, 54, 47, 55, 62, 63
  178. };
  179. private static readonly byte[] ZigZagScan = new byte[]
  180. {
  181. 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
  182. 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
  183. 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
  184. 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4
  185. };
  186. private static void WriteScalingList(H264BitStreamWriter Writer, byte[] List, int Start, int Count)
  187. {
  188. byte[] Scan = Count == 16 ? ZigZagScan : ZigZagDirect;
  189. int LastScale = 8;
  190. for (int Index = 0; Index < Count; Index++)
  191. {
  192. byte Value = List[Start + Scan[Index]];
  193. int DeltaScale = Value - LastScale;
  194. Writer.WriteSe(DeltaScale);
  195. LastScale = Value;
  196. }
  197. }
  198. }
  199. }