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);
        }
Example #4
0
        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);
 }