private static uint ReadPayloadValue(INalUnitReader reader)
        {
            uint value = 0;
            uint b     = reader.GetByte(true);

            while (b == 0xff)
            {
                value += 255;
                b      = reader.GetByte(true);
            }
            return(value + b);
        }
        public void Parse(INalUnitReader reader, IResultNodeState resultState)
        {
            resultState.Name = Name;

            uint payloadType = ReadPayloadValue(reader);

            resultState.AddAttribute(Attribute.PayloadType, payloadType);

            uint payloadSize = ReadPayloadValue(reader);

            resultState.AddAttribute(Attribute.PayloadSize, payloadSize);

            //skip payload
            for (int i = 0; i < payloadSize; i++)
            {
                reader.GetByte(true);
            }

            // payload type = (FF)* E5
            // payload size = (FF)* 01
            // payload = 9C
        }
        // 7.3.2.1.1 SequenceState parameter set data syntax
        public void Parse(INalUnitReader reader, IResultNodeState resultState)
        {
            // Constraints from 7.4.2.11

            resultState.Name = Name;

            Profile profileIdc = reader.GetBits(8, Attribute.ProfileIdc, _profileValidator);

            reader.GetBits(6);             // constraint_set{0-5}_flag

            if (reader.GetBits(2) != 0)    // reserved_zero_2bits
            {
                resultState.Invalidate();
                return;
            }

            reader.GetByte(false, Attribute.LevelIdc, 59);             // level_idc, Table A-1 - Level limits
            uint sequenceParameterSetId = reader.GetExpGolombCoded(Attribute.SequenceParameterSetId, 31);

            ISequenceStateBuilder builder = new SequenceStateBuilder(sequenceParameterSetId);

            builder.ByteStreamFormat = reader.State.ByteStreamFormat;
            builder.ProfileIdc       = profileIdc;

            if (IsHighProfile(profileIdc))
            {
                uint chromaFormatIdc = reader.GetExpGolombCoded(Attribute.ChromaFormatIdc, 3);                 // Table 6-1
                builder.ChromaFormatIdc = chromaFormatIdc;

                if (chromaFormatIdc == 3)
                {
                    builder.SeparateColourPlaneFlag = reader.GetBit(Attribute.SeparateColorPlaneFlag);
                }

                builder.BitDepthLumaMinus8   = reader.GetExpGolombCoded(Attribute.BitDepthLumaArraySampleMinus8, 6);
                builder.BitDepthChromaMinus8 = reader.GetExpGolombCoded(Attribute.BitDepthChromaArraySampleMinus8, 6);
                reader.GetBit();                 // qpprime_y_zero_transform_bypass_flag

                if (reader.GetBit())             // seq_scaling_matrix_present_flag
                {
                    for (int i = 0; i < ((chromaFormatIdc != 3) ? 8 : 12); i++)
                    {
                        if (reader.GetBit())                         // seq_scaling_list_present_flag[i]
                        {
                            // FIXME: scaling_list() is not implemented!!

                            resultState.Invalidate();
                            return;
                        }
                    }
                }
            }

            builder.Log2MaxFrameNumMinus4 = reader.GetExpGolombCoded(Attribute.Log2MaxFrameNumMinus4, 28);

            DecodePictureOrderCount(reader, builder);

            uint maxDpbFramesUpperLimit = (profileIdc == Profile.MultiviewHigh) ? 160U : 16U;             //could use the exact maxDpbFrames, but this is easier

            builder.MaxNumRefFrames = reader.GetExpGolombCoded(Attribute.MaxNumberReferenceFrames, maxDpbFramesUpperLimit);
            reader.GetBit();             // gaps_in_frame_num_value_allowed_flag
            builder.PicWidthInMbsMinus1       = reader.GetExpGolombCoded(Attribute.PictureWidthInMacroBlocksMinus1, 543);
            builder.PicHeightInMapUnitsMinus1 = reader.GetExpGolombCoded(Attribute.PictureHeightInMapUnitsMinus1, 543);

            var frameMbsOnlyFlag = reader.GetBit(Attribute.FrameMbsOnlyFlag);

            builder.FrameMbsOnlyFlag = frameMbsOnlyFlag;
            if (!frameMbsOnlyFlag)
            {
                builder.MbAdaptiveFrameFieldFlag = reader.GetBit();
            }

            bool direct8X8InferenceFlag = reader.GetBit();

            builder.Direct8X8InferenceFlag = direct8X8InferenceFlag;
            if (!frameMbsOnlyFlag && !direct8X8InferenceFlag)
            {
                resultState.Invalidate();
                return;
            }

            if (reader.GetBit())             // frame_cropping_flag
            {
                // TODO: Cropping should not exceed the size of a frame!
                reader.GetExpGolombCoded(Attribute.FrameCropLeftOffset, 8703);
                reader.GetExpGolombCoded(Attribute.FrameCropRightOffset, 8703);
                reader.GetExpGolombCoded(Attribute.FrameCropTopOffset, 8703);
                reader.GetExpGolombCoded(Attribute.FrameCropBottomOffset, 8703);
            }
            if (reader.GetBit())             // vui_parameters_present_flag
            {
                GetVuiParameters(reader, resultState);
            }
            if (reader.ShowBits(1) == 1)
            {
                reader.GetBit();                 // rbsp_stop_one_bit (equal to 1)
                // trailing zero bits
            }

            if (resultState.Valid)
            {
                reader.State.SequenceStates[sequenceParameterSetId] = builder.Build();
            }
        }
        private static void GetVuiParameters(INalUnitReader reader, IResultNodeState resultState)
        {
            const byte extendedSar = 255;                               // Extended_SAR

            bool aspectRatioInfoPresentFlag = reader.GetBit();

            if (aspectRatioInfoPresentFlag)                             // aspect_ratio_info_present_flag
            {
                byte aspectRatioIdc = reader.GetByte(false);
                if (aspectRatioIdc == extendedSar)                      // aspect_ratio_idc
                {
                    reader.GetBits(16);                                 // sar_width
                    reader.GetBits(16);                                 // sar_height
                }
            }

            bool overscanInfoPresentFlag = reader.GetBit();

            if (overscanInfoPresentFlag)                                // overscan_info_present_flag
            {
                reader.GetBit();                                        // overscan_appropriate_flag
            }

            bool videoSignalTypePresentFlag = reader.GetBit();

            if (videoSignalTypePresentFlag)                             // video_signal_type_present_flag
            {
                reader.GetBits(3);                                      // video_format
                reader.GetBit();                                        // video_full_range_flag

                bool colourDescriptionPresentFlag = reader.GetBit();
                if (colourDescriptionPresentFlag)                       // colour_description_present_flag
                {
                    reader.GetByte(false);                              // colour_primaries
                    reader.GetByte(false);                              // transfer_characteristics
                    reader.GetByte(false);                              // matrix_coefficients
                }
            }

            bool chromaLocInfoPresentFlag = reader.GetBit();

            if (chromaLocInfoPresentFlag)                               // chroma_loc_info_present_flag
            {
                reader.GetExpGolombCoded();                             // chroma_sample_loc_type_top_field
                reader.GetExpGolombCoded();                             // chroma_sample_loc_type_bottom_field
            }

            bool timingInfoPresentFlag = reader.GetBit();

            if (timingInfoPresentFlag)                                          // timing_info_present_flag
            {
                reader.GetBits(32);                                             // num_units_in_tick
                reader.GetBits(32);                                             // time_scale
                reader.GetBit();                                                // fixed_frame_rate_flag
            }

            bool nalHrdParametersPresentFlag = reader.GetBit();

            if (nalHrdParametersPresentFlag)                            //nal_hrd_parameters_present_flag
            {
                GetHrdParameters(reader, resultState);                  // hrd_parameters()
            }

            bool vclHrdParametersPresentFlag = reader.GetBit();

            if (vclHrdParametersPresentFlag)                            // vcl_hrd_parameters_present_flag
            {
                GetHrdParameters(reader, resultState);                  // hrd_parameters()
            }
            if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag)
            {
                reader.GetBit();                                                        // low_delay_hrd_flag
            }

            reader.GetBit();                                                            // pic_struct_present_flag
            bool bitstreamRestrictionFlag = reader.GetBit();

            if (bitstreamRestrictionFlag)                               // bitstream_restriction_flag
            {
                reader.GetBit();                                        // motion_vectors_over_pic_boundaries_flag
                reader.GetExpGolombCoded();                             // max_bytes_per_pic_denom
                reader.GetExpGolombCoded();                             // max_bits_per_mb_denom
                reader.GetExpGolombCoded();                             // log2_max_mv_length_horizontal
                reader.GetExpGolombCoded();                             // log2_max_mv_length_vertical
                reader.GetExpGolombCoded();                             // num_reorder_frames
                reader.GetExpGolombCoded();                             // max_dec_frame_buffering
            }
        }