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. }