H264BitStreamWriter.cs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using System.IO;
  2. namespace Ryujinx.Graphics.VDec
  3. {
  4. class H264BitStreamWriter : BitStreamWriter
  5. {
  6. public H264BitStreamWriter(Stream BaseStream) : base(BaseStream) { }
  7. public void WriteU(int Value, int ValueSize)
  8. {
  9. WriteBits(Value, ValueSize);
  10. }
  11. public void WriteSe(int Value)
  12. {
  13. WriteExpGolombCodedInt(Value);
  14. }
  15. public void WriteUe(int Value)
  16. {
  17. WriteExpGolombCodedUInt((uint)Value);
  18. }
  19. public void End()
  20. {
  21. WriteBit(true);
  22. Flush();
  23. }
  24. private void WriteExpGolombCodedInt(int Value)
  25. {
  26. int Sign = Value <= 0 ? 0 : 1;
  27. if (Value < 0)
  28. {
  29. Value = -Value;
  30. }
  31. Value = (Value << 1) - Sign;
  32. WriteExpGolombCodedUInt((uint)Value);
  33. }
  34. private void WriteExpGolombCodedUInt(uint Value)
  35. {
  36. int Size = 32 - CountLeadingZeros((int)Value + 1);
  37. WriteBits(1, Size);
  38. Value -= (1u << (Size - 1)) - 1;
  39. WriteBits((int)Value, Size - 1);
  40. }
  41. private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
  42. private static int CountLeadingZeros(int Value)
  43. {
  44. if (Value == 0)
  45. {
  46. return 32;
  47. }
  48. int NibbleIdx = 32;
  49. int PreCount, Count = 0;
  50. do
  51. {
  52. NibbleIdx -= 4;
  53. PreCount = ClzNibbleTbl[(Value >> NibbleIdx) & 0b1111];
  54. Count += PreCount;
  55. }
  56. while (PreCount == 4);
  57. return Count;
  58. }
  59. }
  60. }