aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs')
-rw-r--r--Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs79
1 files changed, 79 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs b/Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs
new file mode 100644
index 00000000..b4fad59b
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec/VDec/H264BitStreamWriter.cs
@@ -0,0 +1,79 @@
+using System.IO;
+
+namespace Ryujinx.Graphics.VDec
+{
+ class H264BitStreamWriter : BitStreamWriter
+ {
+ public H264BitStreamWriter(Stream baseStream) : base(baseStream) { }
+
+ public void WriteU(int value, int valueSize)
+ {
+ WriteBits(value, valueSize);
+ }
+
+ public void WriteSe(int value)
+ {
+ WriteExpGolombCodedInt(value);
+ }
+
+ public void WriteUe(int value)
+ {
+ WriteExpGolombCodedUInt((uint)value);
+ }
+
+ public void End()
+ {
+ WriteBit(true);
+
+ Flush();
+ }
+
+ private void WriteExpGolombCodedInt(int value)
+ {
+ int sign = value <= 0 ? 0 : 1;
+
+ if (value < 0)
+ {
+ value = -value;
+ }
+
+ value = (value << 1) - sign;
+
+ WriteExpGolombCodedUInt((uint)value);
+ }
+
+ private void WriteExpGolombCodedUInt(uint value)
+ {
+ int size = 32 - CountLeadingZeros((int)value + 1);
+
+ WriteBits(1, size);
+
+ value -= (1u << (size - 1)) - 1;
+
+ WriteBits((int)value, size - 1);
+ }
+
+ private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ private static int CountLeadingZeros(int value)
+ {
+ if (value == 0)
+ {
+ return 32;
+ }
+
+ int nibbleIdx = 32;
+ int preCount, count = 0;
+
+ do
+ {
+ nibbleIdx -= 4;
+ preCount = ClzNibbleTbl[(value >> nibbleIdx) & 0b1111];
+ count += preCount;
+ }
+ while (preCount == 4);
+
+ return count;
+ }
+ }
+} \ No newline at end of file