SpsAndPpsReconstruction.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using Ryujinx.Common.Memory;
  2. using Ryujinx.Graphics.Video;
  3. using System;
  4. namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
  5. {
  6. static class SpsAndPpsReconstruction
  7. {
  8. public static Span<byte> Reconstruct(ref H264PictureInfo pictureInfo, byte[] workBuffer)
  9. {
  10. H264BitStreamWriter writer = new H264BitStreamWriter(workBuffer);
  11. // Sequence Parameter Set.
  12. writer.WriteU(1, 24);
  13. writer.WriteU(0, 1);
  14. writer.WriteU(3, 2);
  15. writer.WriteU(7, 5);
  16. writer.WriteU(100, 8); // Profile idc
  17. writer.WriteU(0, 8); // Reserved
  18. writer.WriteU(31, 8); // Level idc
  19. writer.WriteUe(0); // Seq parameter set id
  20. writer.WriteUe(pictureInfo.ChromaFormatIdc);
  21. if (pictureInfo.ChromaFormatIdc == 3)
  22. {
  23. writer.WriteBit(false); // Separate colour plane flag
  24. }
  25. writer.WriteUe(0); // Bit depth luma minus 8
  26. writer.WriteUe(0); // Bit depth chroma minus 8
  27. writer.WriteBit(pictureInfo.QpprimeYZeroTransformBypassFlag);
  28. writer.WriteBit(false); // Scaling matrix present flag
  29. writer.WriteUe(pictureInfo.Log2MaxFrameNumMinus4);
  30. writer.WriteUe(pictureInfo.PicOrderCntType);
  31. if (pictureInfo.PicOrderCntType == 0)
  32. {
  33. writer.WriteUe(pictureInfo.Log2MaxPicOrderCntLsbMinus4);
  34. }
  35. else if (pictureInfo.PicOrderCntType == 1)
  36. {
  37. writer.WriteBit(pictureInfo.DeltaPicOrderAlwaysZeroFlag);
  38. writer.WriteSe(0); // Offset for non-ref pic
  39. writer.WriteSe(0); // Offset for top to bottom field
  40. writer.WriteUe(0); // Num ref frames in pic order cnt cycle
  41. }
  42. writer.WriteUe(16); // Max num ref frames
  43. writer.WriteBit(false); // Gaps in frame num value allowed flag
  44. writer.WriteUe(pictureInfo.PicWidthInMbsMinus1);
  45. writer.WriteUe(pictureInfo.PicHeightInMapUnitsMinus1);
  46. writer.WriteBit(pictureInfo.FrameMbsOnlyFlag);
  47. if (!pictureInfo.FrameMbsOnlyFlag)
  48. {
  49. writer.WriteBit(pictureInfo.MbAdaptiveFrameFieldFlag);
  50. }
  51. writer.WriteBit(pictureInfo.Direct8x8InferenceFlag);
  52. writer.WriteBit(false); // Frame cropping flag
  53. writer.WriteBit(false); // VUI parameter present flag
  54. writer.End();
  55. // Picture Parameter Set.
  56. writer.WriteU(1, 24);
  57. writer.WriteU(0, 1);
  58. writer.WriteU(3, 2);
  59. writer.WriteU(8, 5);
  60. writer.WriteUe(0); // Pic parameter set id
  61. writer.WriteUe(0); // Seq parameter set id
  62. writer.WriteBit(pictureInfo.EntropyCodingModeFlag);
  63. writer.WriteBit(pictureInfo.PicOrderPresentFlag);
  64. writer.WriteUe(0); // Num slice groups minus 1
  65. writer.WriteUe(pictureInfo.NumRefIdxL0ActiveMinus1);
  66. writer.WriteUe(pictureInfo.NumRefIdxL1ActiveMinus1);
  67. writer.WriteBit(pictureInfo.WeightedPredFlag);
  68. writer.WriteU(pictureInfo.WeightedBipredIdc, 2);
  69. writer.WriteSe(pictureInfo.PicInitQpMinus26);
  70. writer.WriteSe(0); // Pic init qs minus 26
  71. writer.WriteSe(pictureInfo.ChromaQpIndexOffset);
  72. writer.WriteBit(pictureInfo.DeblockingFilterControlPresentFlag);
  73. writer.WriteBit(pictureInfo.ConstrainedIntraPredFlag);
  74. writer.WriteBit(pictureInfo.RedundantPicCntPresentFlag);
  75. writer.WriteBit(pictureInfo.Transform8x8ModeFlag);
  76. writer.WriteBit(pictureInfo.ScalingMatrixPresent);
  77. if (pictureInfo.ScalingMatrixPresent)
  78. {
  79. for (int index = 0; index < 6; index++)
  80. {
  81. writer.WriteBit(true);
  82. WriteScalingList(ref writer, pictureInfo.ScalingLists4x4[index]);
  83. }
  84. if (pictureInfo.Transform8x8ModeFlag)
  85. {
  86. for (int index = 0; index < 2; index++)
  87. {
  88. writer.WriteBit(true);
  89. WriteScalingList(ref writer, pictureInfo.ScalingLists8x8[index]);
  90. }
  91. }
  92. }
  93. writer.WriteSe(pictureInfo.SecondChromaQpIndexOffset);
  94. writer.End();
  95. return writer.AsSpan();
  96. }
  97. // ZigZag LUTs from libavcodec.
  98. private static readonly byte[] ZigZagDirect = new byte[]
  99. {
  100. 0, 1, 8, 16, 9, 2, 3, 10,
  101. 17, 24, 32, 25, 18, 11, 4, 5,
  102. 12, 19, 26, 33, 40, 48, 41, 34,
  103. 27, 20, 13, 6, 7, 14, 21, 28,
  104. 35, 42, 49, 56, 57, 50, 43, 36,
  105. 29, 22, 15, 23, 30, 37, 44, 51,
  106. 58, 59, 52, 45, 38, 31, 39, 46,
  107. 53, 60, 61, 54, 47, 55, 62, 63
  108. };
  109. private static readonly byte[] ZigZagScan = new byte[]
  110. {
  111. 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
  112. 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
  113. 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
  114. 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4
  115. };
  116. private static void WriteScalingList(ref H264BitStreamWriter writer, IArray<byte> list)
  117. {
  118. byte[] scan = list.Length == 16 ? ZigZagScan : ZigZagDirect;
  119. int lastScale = 8;
  120. for (int index = 0; index < list.Length; index++)
  121. {
  122. byte value = list[scan[index]];
  123. int deltaScale = value - lastScale;
  124. writer.WriteSe(deltaScale);
  125. lastScale = value;
  126. }
  127. }
  128. }
  129. }