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(); }
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); }