Example #1
0
        public void Parse(INalUnitReader reader, IResultNodeState resultState)
        {
            reader.GetFixedBits(1, 0, Attribute.ForbiddenZeroBit);
            reader.State.NalRefIdc   = reader.GetBits(2, Attribute.NalRefIdc);
            reader.State.NalUnitType = (NalUnitType)reader.GetBits(5, Attribute.NalUnitType);

            INalUnitPayloadParser nalUnitPayloadParser;

            if (!_nalUnitParsers.TryGetValue(reader.State.NalUnitType, out nalUnitPayloadParser))
            {
                resultState.Invalidate();
                return;
            }

            //Parse remainder with specific nalunitparser (NOTE: Is not a sub-object)
            nalUnitPayloadParser.Parse(reader, resultState);

            if (!resultState.Valid)
            {
                return;                 // Stop processing of invalid NAL unit.
            }
            if (!CanParseNalUnitType(reader.State.SliceState, reader.State.NalUnitType))
            {
                // Forward to the estimated end of the NAL unit
                reader.Position = reader.Length;
                resultState.Invalidate();              // Invalidates the result
                resultState.Recover();                 // Revalidates the reader state so parsing can continue!
                return;
            }

            if (reader.State.NalUnitType == NalUnitType.SequenceParameterSet)
            {
                return;                 // Note: SPS validate their own data!
            }
            if (reader.State.NalUnitType == NalUnitType.PictureParameterSet)
            {
                return;                 // Note: PPS validate their own data!
            }

            if (!IsSlice(reader.State.NalUnitType) || !reader.State.SliceState.PictureState.EntropyCodingMode)
            {
                if (reader.GetBits(1) != 1)                 // rbsp_stop_one_bit (equal to 1)
                {
                    resultState.Invalidate();
                    return;
                }
            }
            if (IsSlice(reader.State.NalUnitType) && resultState.Valid)
            {
                return;                 // Random (e.g. audio) data is allowed after a valid slice
            }

            reader.ReadZeroAlignmentBits();
        }
        private void ParseSliceGroupMap(INalUnitReader reader, IState resultState, IPictureStateBuilder builder, uint sliceGroupCount)
        {
            var sliceGroupMapType = (SliceGroupMapType)reader.GetExpGolombCoded(Attribute.SliceGroupMapType, _sliceGroupMapTypeFormatter);             // slice_group_map_type

            builder.SliceGroupMapType = sliceGroupMapType;

            switch (sliceGroupMapType)
            {
            case SliceGroupMapType.InterleavedSliceGroups:
                uint[] runLengthMinus1 = new uint[sliceGroupCount];
                for (int iGroup = 0; iGroup < sliceGroupCount; iGroup++)
                {
                    runLengthMinus1[iGroup] = reader.GetExpGolombCoded();                             // run_length_minus1[iGroup]
                }
                builder.RunLengthMinus1 = runLengthMinus1;
                break;

            case SliceGroupMapType.DispersedSliceGroups:
                break;

            case SliceGroupMapType.ForegroundAndLeftoverSliceGroups:
                uint[] topLeft     = new uint[sliceGroupCount - 1];
                uint[] bottomRight = new uint[sliceGroupCount - 1];
                for (int iGroup = 0; iGroup < (sliceGroupCount - 1); iGroup++)
                {
                    topLeft[iGroup]     = reader.GetExpGolombCoded();
                    bottomRight[iGroup] = reader.GetExpGolombCoded();
                }
                builder.TopLeft     = topLeft;
                builder.BottomRight = bottomRight;
                break;

            case SliceGroupMapType.ChangingSliceGroups3:
            case SliceGroupMapType.ChangingSliceGroups4:
            case SliceGroupMapType.ChangingSliceGroups5:
                builder.SliceGroupChangeDirectionFlag = reader.GetBit();
                builder.SliceGroupChangeRateMinus1    = reader.GetExpGolombCoded();
                break;

            case SliceGroupMapType.ExplicitSliceGroups:
                uint   pictureSizeInMapUnits = 1 + reader.GetExpGolombCoded();                       // pic_size_in_map_units_minus1
                int    syntaxElementSize     = DetectorUtils.Log2(sliceGroupCount - 1) + 1;
                uint[] sliceGroupId          = new uint[pictureSizeInMapUnits];
                for (int i = 0; i < pictureSizeInMapUnits; i++)
                {
                    sliceGroupId[i] = reader.GetBits(syntaxElementSize);
                }
                builder.SliceGroupId = sliceGroupId;
                break;

            default:
                resultState.Invalidate();
                break;
            }
        }
        private static void GetHrdParameters(INalUnitReader reader, IState resultState)
        {
            uint cpbCntMinus1 = reader.GetExpGolombCoded();                             // cpb_cnt_minus1

            reader.GetBits(4);                                                          // bit_rate_scale
            reader.GetBits(4);                                                          // cpb_size_scale

            // for (SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++)
            for (int schedSelIdx = 0; schedSelIdx <= cpbCntMinus1; schedSelIdx++)
            {
                if (!reader.HasMoreRbspData())
                {
                    resultState.Invalidate();
                    return;
                }

                reader.GetExpGolombCoded();                                     // bit_rate_value_minus1[SchedSelIdx]
                reader.GetExpGolombCoded();                                     // cpb_size_value_minus1[SchedSelIdx]
                reader.GetBit();                                                // cbr_flag[SchedSelIdx]
            }
            reader.GetBits(5);                                                  // initial_cpb_removal_delay_length_minus1
            reader.GetBits(5);                                                  // cpb_removal_delay_length_minus1
            reader.GetBits(5);                                                  // dpb_output_delay_length_minus1
            reader.GetBits(5);                                                  // time_offset_length
        }
        // 7.3.2.2 PictureState parameter set RBSP syntax
        public void Parse(INalUnitReader reader, IResultNodeState resultState)
        {
            resultState.Name = Name;

            uint pictureParameterSetId  = reader.GetExpGolombCoded(Attribute.PictureParameterSetId, 255 /*7.4.2.2*/);
            uint sequenceParameterSetId = reader.GetExpGolombCoded(Attribute.SequenceParameterSetId, 31 /*7.4.2.2*/);
            var  sequenceState          = reader.State.SequenceStates[sequenceParameterSetId];

            if (sequenceState == null)
            {
                resultState.Invalidate();
                return;
            }

            IPictureStateBuilder builder = new PictureStateBuilder(pictureParameterSetId, sequenceState);

            builder.EntropyCodingMode = reader.GetBit(Attribute.EntropyCodingMode);
            builder.BottomFieldPicOrderInFramePresentFlag = reader.GetBit(Attribute.PictureOrderPresent);
            uint numSliceGroupsMinus1 = reader.GetExpGolombCoded(Attribute.NumSliceGroupsMinus1, 7 /*A.2*/);

            builder.NumSliceGroupsMinus1 = numSliceGroupsMinus1;

            if (numSliceGroupsMinus1 > 0)
            {
                if (sequenceState.Profile == Profile.Main)
                {
                    resultState.Invalidate();
                    return;
                }

                ParseSliceGroupMap(reader, resultState, builder, (numSliceGroupsMinus1 + 1));

                // FIXME: this code contains too many bugs, so it is disabled for now!
                resultState.Invalidate();
                // (end of FIXME)
                if (!resultState.Valid)
                {
                    return;
                }
            }

            builder.NumRefIdxL0DefaultActiveMinus1 = reader.GetExpGolombCoded(Attribute.NumRefIdxl0DefaultActiveMinus1, 31 /*7.4.2.2*/);
            builder.NumRefIdxL1DefaultActiveMinus1 = reader.GetExpGolombCoded(Attribute.NumRefIdxl1DefaultActiveMinus1, 31 /*7.4.2.2*/);
            builder.WeightedPredFlag  = reader.GetBit(Attribute.WeightedPrediction);
            builder.WeightedBipredIdc = reader.GetBits(2, Attribute.WeightedBidirectionalPrediction, _weightBidirectionalPredictionFormatter);
            // SliceQPY = 26 + PicInitQpMinus26 + slice_qp_delta
            int qpBdOffset = (6 * ((int)sequenceState.BitDepthLuma - 8));

            builder.PicInitQpMinus26 = reader.GetSignedExpGolombCoded(Attribute.PictureInitialQPyMinus26, -(26 + qpBdOffset), 25);
            reader.GetSignedExpGolombCoded(Attribute.PictureInitialQSyMinus26, -26, 25); // pic_init_qs_minus26; relative to 26
            reader.GetSignedExpGolombCoded(Attribute.ChromaQpIndexOffset, -12, 12);      // chroma_qp_index_offset
            builder.DeblockingFilterControlPresentFlag = reader.GetBit(Attribute.DeblockingFilterControlPresent);
            reader.GetBit(Attribute.ConstrainedIntraPrediction);                         // constrained_intra_pred_flag
            builder.RedundantPicCntPresentFlag = reader.GetBit(Attribute.RedundantPictureControlPresent);

            // Note: Total size upto this point is between 11 and 59 bits (+ 'slice group map')

            if (reader.HasMoreRbspData())                                       // more_rbsp_data()
            {
                builder.Transform8X8ModeFlag = reader.GetBit();                 // transform_8x8_mode_flag
                bool picScalingMatrixPresentFlag = reader.GetBit();
                //if (picScalingMatrixPresentFlag)		// pic_scaling_matrix_present_flag
                //{
                //    for (int i = 0; i < 6 + 2 * pictureState.transform_8x8_mode_flag; i++)
                //    {
                //        bool picScalingListPresentFlag = reader.GetBit();
                //        if (picScalingListPresentFlag)	// pic_scaling_list_present_flag[i]
                //        {
                //            if (i < 6)
                //            {
                //                throw new NotImplementedException("scaling_list(ScalingList4x4[i], 16, UseDefaultScalingMatrix4x4Flag[i]);");	// TODO
                //            }
                //            else
                //            {
                //                throw new NotImplementedException("scaling_list(ScalingList8x8[i – 6], 64, UseDefaultScalingMatrix8x8Flag[i – 6]);");	// TODO
                //            }
                //        }
                //    }
                //}
                reader.GetSignedExpGolombCoded();                 // second_chroma_qp_index_offset
            }

            // rbsp_trailing_bits()

            if (reader.ShowBits(1) == 1)
            {
                reader.GetBit();                 // rbsp_stop_one_bit (equal to 1)
                // trailing zero bits
            }

            if (resultState.Valid)
            {
                reader.State.PictureStates[pictureParameterSetId] = builder.Build();
            }
        }
Example #5
0
        private void ResidualBlockCavlc(int startIdx, int endIdx, int maxNumCoeff, CoeffToken coeffToken)
        {
            int suffixLength = ((coeffToken.TotalCoeff > 10) && (coeffToken.TrailingOnes < 3)) ? 1 : 0;

#if DEBUG
            H264Debug.Write("   - levels=");
            if (coeffToken.TrailingOnes > 0)
            {
                uint signs = _reader.GetBits(coeffToken.TrailingOnes);                 // (n) x trailing_ones_sign_flag
                for (int i = 0; i < coeffToken.TrailingOnes; i++)
                {
                    H264Debug.Write((((signs & (1 << (coeffToken.TrailingOnes - 1 - i))) == 0) ? "1," : "-1,"));
                }
            }
#else
            _reader.GetBits(coeffToken.TrailingOnes);             // (n) x trailing_ones_sign_flag
#endif

            for (int i = coeffToken.TrailingOnes; i < coeffToken.TotalCoeff; i++)
            {
                int levelCode = GetCoefficientLevelCode(suffixLength);

                // The first non-zero coefficient after 'trailing ones' must be larger than 1,
                // unless the maximum count of trailing ones, i.e. 3, was reached.
                // This will further reduce the amount of bits required to represent a
                // coefficient level.
                if ((i == coeffToken.TrailingOnes) && (i /*trailing ones*/ < 3))
                {
                    levelCode += 2;                     // 2 instead of 1, because the lowest bit is the sign bit!
                }
#if DEBUG
                H264Debug.Write("{0},", ((levelCode % 2) == 0) ? ((levelCode + 2) >> 1) : ((-levelCode - 1) >> 1));
#endif

                // Automatically adjust the suffix length if high coefficients levels are
                // encountered, to reduce the number of bits required to represent subsequent
                // high coefficient levels.
                if (suffixLength == 0)
                {
                    suffixLength = 1;
                }
                if (suffixLength < 6)
                {
                    int absLevelMinusOne = (levelCode >> 1);
                    if (absLevelMinusOne >= (3 << (suffixLength - 1)))
                    {
                        suffixLength++;
                    }
                }
            }
#if DEBUG
            H264Debug.WriteLine();
#endif

            if (coeffToken.TotalCoeff < (endIdx - startIdx + 1))
            {
                int zerosLeft = GetTotalZeros(coeffToken.TotalCoeff, maxNumCoeff);                 // total_zeros
#if DEBUG
                H264Debug.WriteLine("   - total_zeros={0}", zerosLeft);
                H264Debug.WriteLine("ShowBits(32) = {0:x8} at {1:x8}", _reader.ShowBits(32), _reader.Position);
                H264Debug.Write("   - run_before=");
#endif
                for (int i = 0; i < (coeffToken.TotalCoeff - 1) && (zerosLeft > 0); i++)
                {
#if DEBUG
                    int runBefore = _reader.GetVlc(RunBeforeTable[Math.Min(zerosLeft, 7)]);
                    zerosLeft -= runBefore;                     // run_before
                    H264Debug.Write("{0},", runBefore);
#else
                    zerosLeft -= _reader.GetVlc(RunBeforeTable[Math.Min(zerosLeft, 7)]);                     // run_before
#endif
                }
#if DEBUG
                H264Debug.WriteLine();
#endif
            }
        }
        // 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
            }
        }