|
- using System;
- using System.Buffers.Binary;
- using System.Collections.Generic;
- using System.Text;
-
- namespace JT1078.Flv.MessagePack
- {
- /// <summary>
- /// Exp-Golomb指数哥伦布编码
- /// </summary>
- public ref struct ExpGolombReader
- {
- public ReadOnlySpan<byte> SrcBuffer { get; }
- public int BytesAvailable { get; private set; }
- public int Word { get; private set; }
- public int BitsAvailable { get; private set; }
- public ExpGolombReader(ReadOnlySpan<byte> srcBuffer)
- {
- SrcBuffer = srcBuffer;
- BytesAvailable = srcBuffer.Length;
- Word = 0;
- BitsAvailable = 0;
- }
- public (byte profileIdc,byte levelIdc,uint profileCompat,int width, int height) ReadSPS()
- {
- int sarScale = 1;
- uint frameCropLeftOffset=0;
- uint frameCropRightOffset = 0;
- uint frameCropTopOffset = 0;
- uint frameCropBottomOffset = 0;
- ReadByte();
- //profile_idc
- byte profileIdc = ReadByte();
- //constraint_set[0-4]_flag, u(5)
- uint profileCompat = ReadBits(5);
- //reserved_zero_3bits
- SkipBits(3);
- //level_idc u(8)
- byte levelIdc = ReadByte();
- //seq_parameter_set_id
- SkipUEG();
- if (profileIdc == 100 ||
- profileIdc == 110 ||
- profileIdc == 122 ||
- profileIdc == 244 ||
- profileIdc == 44 ||
- profileIdc == 83 ||
- profileIdc == 86 ||
- profileIdc == 118 ||
- profileIdc == 128)
- {
- uint chromaFormatIdc = ReadUEG();
- if (chromaFormatIdc == 3)
- {
- SkipBits(1); // separate_colour_plane_flag
- }
- SkipUEG(); // bit_depth_luma_minus8
- SkipUEG(); // bit_depth_chroma_minus8
- SkipBits(1); // qpprime_y_zero_transform_bypass_flag
- if (ReadBoolean())
- { // seq_scaling_matrix_present_flag
- int scalingListCount = (chromaFormatIdc != 3) ? 8 : 12;
- for (int i = 0; i < scalingListCount; i++)
- {
- if (ReadBoolean())
- { // seq_scaling_list_present_flag[ i ]
- if (i < 6)
- {
- SkipScalingList(16);
- }
- else
- {
- SkipScalingList(64);
- }
- }
- }
- }
- }
- // log2_max_frame_num_minus4
- SkipUEG();
- var picOrderCntType = ReadUEG();
- if (picOrderCntType == 0)
- {
- ReadUEG(); //log2_max_pic_order_cnt_lsb_minus4
- }
- else if (picOrderCntType == 1)
- {
- SkipBits(1); // delta_pic_order_always_zero_flag
- SkipEG(); // offset_for_non_ref_pic
- SkipEG(); // offset_for_top_to_bottom_field
- uint numRefFramesInPicOrderCntCycle = ReadUEG();
- for (int i = 0; i < numRefFramesInPicOrderCntCycle; i++)
- {
- SkipEG(); // offset_for_ref_frame[ i ]
- }
- }
- SkipUEG(); // max_num_ref_frames
- SkipBits(1); // gaps_in_frame_num_value_allowed_flag
- uint picWidthInMbsMinus1 = ReadUEG();
- uint picHeightInMapUnitsMinus1 = ReadUEG();
- uint frameMbsOnlyFlag = ReadBits(1);
- if (frameMbsOnlyFlag == 0)
- {
- SkipBits(1); // mb_adaptive_frame_field_flag
- }
- this.SkipBits(1); // direct_8x8_inference_flag
- if (ReadBoolean())
- {
- // frame_cropping_flag
- frameCropLeftOffset = ReadUEG();
- frameCropRightOffset = ReadUEG();
- frameCropTopOffset = ReadUEG();
- frameCropBottomOffset = ReadUEG();
- }
- if (ReadBoolean())
- {
- // vui_parameters_present_flag
- if (ReadBoolean())
- {
- // aspect_ratio_info_present_flag
- byte[] sarRatio=null;
- byte aspectRatioIdc = ReadByte();
- switch (aspectRatioIdc)
- {
- case 1: sarRatio =new byte[2] { 1, 1 }; break;
- case 2: sarRatio =new byte[2] { 12, 11}; break;
- case 3: sarRatio =new byte[2] { 10, 11}; break;
- case 4: sarRatio =new byte[2] { 16, 11}; break;
- case 5: sarRatio =new byte[2] { 40, 33}; break;
- case 6: sarRatio =new byte[2] { 24, 11}; break;
- case 7: sarRatio =new byte[2] { 20, 11}; break;
- case 8: sarRatio =new byte[2] { 32, 11 }; break;
- case 9: sarRatio = new byte[2] {80, 33 }; break;
- case 10: sarRatio = new byte[2]{18, 11 }; break;
- case 11: sarRatio = new byte[2]{15, 11 }; break;
- case 12: sarRatio = new byte[2]{64, 33 }; break;
- case 13: sarRatio = new byte[2]{160, 99 }; break;
- case 14: sarRatio = new byte[2]{4, 3 }; break;
- case 15: sarRatio = new byte[2]{3, 2 }; break;
- case 16: sarRatio = new byte[2]{ 2, 1 }; break;
- case 255:
- {
- sarRatio = new byte[2] { (byte)(ReadByte() << 8 | ReadByte()), (byte)(ReadByte() << 8 | ReadByte()) };
- break;
- }
- }
- if (sarRatio != null)
- {
- sarScale = sarRatio[0] / sarRatio[1];
- }
- }
- }
- int width= (int)((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale);
- int height = (int)(((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - ((frameMbsOnlyFlag == 1U ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset)));
- return (profileIdc, levelIdc, profileCompat,width, height);
- }
- public void LoadWord()
- {
- var position = SrcBuffer.Length - BytesAvailable;
- int tmpAvailableBytes = BytesAvailable - 4;
- int availableBytes = Math.Min(4, BytesAvailable);
- //if (availableBytes == 0)
- //{
- // throw new OverflowException("no bytes available");
- //}
- ReadOnlySpan<byte> workingBytes=ReadOnlySpan<byte>.Empty;
- if (tmpAvailableBytes < 0)
- {
- var buffer = new byte[4];
- Array.Copy(SrcBuffer.Slice(position, BytesAvailable).ToArray(), buffer, BytesAvailable);
- workingBytes = buffer;
- }
- else
- {
- workingBytes = SrcBuffer.Slice(position, 4);
- }
- Word = BinaryPrimitives.ReadInt32BigEndian(workingBytes);
- // track the amount of this.data that has been processed
- BitsAvailable = availableBytes * 8;
- BytesAvailable -= availableBytes;
- }
- public void SkipBits(int count)
- {
- if (BitsAvailable > count)
- {
- Word <<= count;
- BitsAvailable -= count;
- }
- else
- {
- count -= BitsAvailable;
- int skipBytes = count >> 3;
- count -= (skipBytes >> 3);
- LoadWord();
- Word <<= count;
- BitsAvailable -= count;
- }
- }
- public uint ReadBits(int size)
- {
- var bits = Math.Min(BitsAvailable, size); // :uint
- var valu = (uint)Word >> (32 - bits); // :uint
- if (size > 32)
- {
- throw new OverflowException("Cannot read more than 32 bits at a time");
- }
- BitsAvailable -= bits;
- if (BitsAvailable > 0)
- {
- Word <<= bits;
- }
- else if (BytesAvailable > 0)
- {
- LoadWord();
- }
- bits = size - bits;
- if (bits > 0)
- {
- return ((valu << bits) | ReadBits(bits));
- }
- else
- {
- return valu;
- }
- }
- public int SkipLZ()
- {
- int leadingZeroCount; // :uint
- for (leadingZeroCount = 0; leadingZeroCount < this.BitsAvailable; ++leadingZeroCount)
- {
- if (0 != (Word & (0x80000000 >> leadingZeroCount)))
- {
- // the first bit of working word is 1
- Word <<= leadingZeroCount;
- BitsAvailable -= leadingZeroCount;
- return leadingZeroCount;
- }
- }
- // we exhausted word and still have not found a 1
- LoadWord();
- return (leadingZeroCount + SkipLZ());
- }
- public void SkipUEG()
- {
- SkipBits(1 + SkipLZ());
- }
- public void SkipEG()
- {
- SkipBits(1 + SkipLZ());
- }
- public uint ReadUEG()
- {
- var clz =SkipLZ();
- return ReadBits(clz + 1) - 1;
- }
- public int ReadEG()
- {
- var valu = (int)ReadUEG(); // :int
- if ((0x01 & valu)==1)
- {
- // the number is odd if the low order bit is set
- return (1 + valu) >> 1; // add 1 to make it even, and divide by 2
- }
- else
- {
- return -1 * (valu >> 1); // divide by two then make it negative
- }
- }
- public bool ReadBoolean()
- {
- return 1 == ReadBits(1);
- }
- public byte ReadByte()
- {
- return (byte)ReadBits(8);
- }
- public ushort ReadUShort()
- {
- return (ushort)ReadBits(16);
- }
- public uint ReadUInt()
- {
- return ReadBits(32);
- }
-
- /// <summary>
- ///Advance the ExpGolomb decoder past a scaling list.The scaling
- ///list is optionally transmitted as part of a sequence parameter
- ///set and is not relevant to transmuxing.
- ///@param count { number}
- ///the number of entries in this scaling list
- ///@see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
- /// </summary>
- /// <param name="count"></param>
- public void SkipScalingList(int count)
- {
- int lastScale = 8,
- nextScale = 8,
- j,
- deltaScale;
- for (j = 0; j < count; j++)
- {
- if (nextScale != 0)
- {
- deltaScale = ReadEG();
- nextScale = (lastScale + deltaScale + 256) % 256;
- }
- lastScale = (nextScale == 0) ? lastScale : nextScale;
- }
- }
- }
- }
|