public override IDataPacket FindReferenceHeader(IDataReader dataReader, ICodecParametersSpec codecParameters) { // Note: Loop to detect reference headers preceeded by a block of video frames // (e.g. for 3GP files with 'mdat' before the 'moov' atom, so that the slices are located before the SPS/PPS pair) while (dataReader.State == DataReaderState.Ready) { IScanContext scanContext = new ReferenceHeaderScanContext { Detectors = new[] { this } }; var dataBlock = Carve(dataReader, new ReferenceHeaderDataBlockBuilder(), scanContext); if (dataBlock == null) { break; // No (more) data blocks detected } IResultNode videoObject = scanContext.Results.FindChild(VideoObjectName); if ((videoObject != null) && videoObject.HasChildren()) { IResultNode videoObjectLayer = videoObject.GetFirstChild(); if (videoObjectLayer.Name == VideoObjectLayerName) { return(CreateReferenceHeader(dataBlock.DataFormat, videoObject, videoObjectLayer, codecParameters)); } } // VideoObject or VideoObjectLayer is missing: Continue scanning after current data block ... dataReader.Position = dataBlock.EndOffset; } return(null); // No reference header detected }
private static bool HasResultNode(IResultNode resultNode, Func <IResultNode, bool> predicate) { if (predicate(resultNode)) { return(true); } if (resultNode.HasChildren()) { foreach (IResultNode childNode in resultNode.Children) { if (HasResultNode(childNode, predicate)) { return(true); } } } return(false); }
private static uint GetValidSliceCount(IResultNode resultNode) { uint count = 0; if (IsSlice(resultNode)) { uint?firstMacroblockInSlice = GetFirstMacroblockInSlice(resultNode); if ((firstMacroblockInSlice == 0) || (firstMacroblockInSlice >= 60)) { // TODO: check other attributes ++count; } } if (resultNode.HasChildren()) { foreach (IResultNode childNode in resultNode.Children) { count += GetValidSliceCount(childNode); } } return(count); }
private static IDataPacket CreateReferenceHeader(CodecID codec, IResultNode sequenceHeader, ICodecParametersSpec codecParameters) { IDataPacket data = sequenceHeader; // Include sequence extensions foreach (IResultNode childResultNode in sequenceHeader.Children) { if (!IsSequenceExtension(childResultNode.Name)) { break; } data = data.Append(childResultNode); } // Report codec parameters for reference header var width = GetAttribute <uint>(sequenceHeader, SequenceHeader.Attribute.HorizontalSizeValue); var height = GetAttribute <uint>(sequenceHeader, SequenceHeader.Attribute.VerticalSizeValue); if (sequenceHeader.HasChildren()) { IResult sequenceExtension = sequenceHeader.GetFirstChild(); if (sequenceExtension.Name == SequenceExtension.Name) { width |= GetAttribute <uint>(sequenceExtension, SequenceExtension.Attribute.HorizontalSizeExtension) << 12; height |= GetAttribute <uint>(sequenceExtension, SequenceExtension.Attribute.VerticalSizeExtension) << 12; } } codecParameters.Codec = codec; codecParameters.Width = width; codecParameters.Height = height; codecParameters.FrameRate = GetAttributeStringValue(sequenceHeader, SequenceHeader.Attribute.FrameRateCode); return(data); }
public static IResultNode GetLastDescendant(this IResultNode resultNode) { return(resultNode.HasChildren() ? resultNode.GetLastChild().GetLastDescendant() : resultNode); }