public void Parse(IH264Reader reader, IResultNodeState resultState)
        {
            long bytesRemaining = (reader.Length - reader.Position);

            if (bytesRemaining < 4)
            {
                resultState.Invalidate();
                return;
            }

            long startPosition = reader.Position;

            // Check whether a sequence parameter set and a picture parameter set are
            // separated by exactly one byte in a NAL unit stream.
            // This is the case for H.264 streams embedded in 3GPP files.
            ulong nextFiveBytes = reader.PeekFiveBytes();

            if ((_state.NalUnitType == NalUnitType.SequenceParameterSet) &&
                !IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 16), bytesRemaining) &&
                IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 8) & 0xffffff, (bytesRemaining - 1)))
            {
                // Skip the byte that is part of the 3GPP container
                reader.Position++;
                bytesRemaining--;
                nextFiveBytes = reader.PeekFiveBytes();
            }
            if (IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 16), bytesRemaining))
            {
                if (ParseShortLengthPrefixedNalUnit(reader, resultState) && resultState.Valid)
                {
                    return;                     // Successfully parse SPS or PPS NAL unit
                }

                resultState.Reset();
                reader.Position = startPosition;
            }
            if (IsLongLengthPrefixedNalUnit(nextFiveBytes, bytesRemaining))
            {
                if (ParseLongLengthPrefixedNalUnit(reader, resultState))
                {
                    return;                     // Successfully parse slice NAL unit
                }
            }

            resultState.Invalidate();
        }
Пример #2
0
        public bool TryDefaultHeaders(IResultNodeState resultState, Action evaluateHeader)
        {
            if (!IsDetectingReferenceHeader() || !resultState.Valid)
            {
                return(false);
            }

            // This will make sure the reference headers are tested no more than twice (and not for every slice)
            _state.ReferenceHeadersTestCount++;

            long startPosition = Position;

            // Try reference headers to decode this slice
            foreach (var referenceHeader in ReferenceHeaders)
            {
                // Ignore reference headers with 'byte stream' <-> 'NAL unit stream' format mismatch
                if (referenceHeader.Value.SequenceState.ByteStreamFormat == _state.ByteStreamFormat)
                {
                    referenceHeader.Value.CopyTo(_state);

                    evaluateHeader();

                    // The restult state should be valid *AND* the slice should actually have been decoded!!!!
                    if (resultState.Valid && (_state.SliceState != null))
                    {
                        _state.ReferenceHeader = referenceHeader.Key;
                        return(true);                        // Header successfully decoded!
                    }
                }

                _state.SequenceStates.Clear();
                _state.PictureStates.Clear();

                resultState.Reset();
                Position = startPosition;
            }

            // Not able to decode slice using any reference header, defaulting to unparsable slices
            return(false);
        }