Пример #1
0
        /// <summary>
        /// Read the cues from the root cue node.
        /// </summary>
        public static Cue[] GetCues(MatroskaSegment segment, Stream reader)
        {
            MatroskaTree cues = segment.GetChildFromSeek(reader, MatroskaTree.Segment_Cues);

            if (cues == null)
            {
                return(new Cue[0]);
            }

            segment.Position(reader);
            long offset = reader.Position;

            MatroskaTree[] sources = cues.GetChildren(reader, MatroskaTree.Segment_Cues_CuePoint);
            Cue[]          results = new Cue[sources.Length];
            for (int i = 0; i < sources.Length; ++i)
            {
                long         time     = sources[i].GetChildValue(reader, MatroskaTree.Segment_Cues_CuePoint_CueTime);
                MatroskaTree position = sources[i].GetChild(reader, MatroskaTree.Segment_Cues_CuePoint_CueTrackPositions);
                results[i] = new Cue(
                    time, position.GetChildValue(reader, MatroskaTree.Segment_Cues_CuePoint_CueTrackPositions_CueTrack),
                    offset +
                    position.GetChildValue(reader, MatroskaTree.Segment_Cues_CuePoint_CueTrackPositions_CueClusterPosition)
                    );
            }
            return(results);
        }
Пример #2
0
        /// <summary>
        /// Fetch all child instances of a tag.
        /// </summary>
        public MatroskaTree[] GetChildren(Stream reader, int tag)
        {
            int tags = 0;

            for (int i = 0, c = children.Count; i < c; ++i)
            {
                if (children[i].Tag == tag)
                {
                    ++tags;
                }
            }

            reader.Position = nextTag;
            while (reader.Position < end)
            {
                MatroskaTree subtree = new MatroskaTree(reader);
                children.Add(subtree);
                if (subtree.Tag == tag)
                {
                    ++tags;
                }
            }
            nextTag = end;

            MatroskaTree[] result = new MatroskaTree[tags];
            for (int i = 0, c = children.Count; i < c; ++i)
            {
                if (children[i].Tag == tag)
                {
                    result[^ tags] = children[i];
Пример #3
0
        /// <summary>
        /// Reads the segment with its seek header.
        /// </summary>
        public MatroskaSegment(Stream reader) : base(reader)
        {
            MatroskaTree seekHead = GetChild(reader, Segment_SeekHead);

            if (seekHead == null)
            {
                reader.Position = end;
                return;
            }

            MatroskaTree[] seekInputs = seekHead.GetChildren(reader, Segment_SeekHead_Seek);
            for (int i = 0; i < seekInputs.Length; ++i)
            {
                seeks[(int)seekInputs[i].GetChildValue(reader, Segment_SeekHead_Seek_SeekID)] =
                    seekInputs[i].GetChildValue(reader, Segment_SeekHead_Seek_SeekPosition);
            }
            reader.Position = end;
        }
Пример #4
0
        /// <summary>
        /// Fetch the first child of a tag if it exists.
        /// </summary>
        public MatroskaTree GetChild(Stream reader, int tag)
        {
            for (int i = 0, c = children.Count; i < c; ++i)
            {
                if (children[i].Tag == tag)
                {
                    return(children[i]);
                }
            }

            reader.Position = nextTag;
            while (nextTag < end)
            {
                MatroskaTree subtree = new MatroskaTree(reader);
                children.Add(subtree);
                if (subtree.Tag == tag)
                {
                    return(subtree);
                }
                nextTag = reader.Position;
            }
            return(null);
        }
Пример #5
0
        /// <summary>
        /// All blocks of the cluster, in order.
        /// </summary>
        public IReadOnlyList <Block> GetBlocks(Stream reader)
        {
            if (blocks != null)
            {
                return(blocks);
            }
            MemoryStream stream = new MemoryStream(source.GetRawData(reader));

            blocks = new List <Block>();
            long end = stream.Length - 2; // Safety barrier, a byte might remain, but a 2 byte child is impossible

            while (stream.Position < end)
            {
                MatroskaTree child        = new MatroskaTree(stream);
                long         continueFrom = stream.Position;

                // Block groups (Matroska v1)
                if (child.Tag == MatroskaTree.Segment_Cluster_BlockGroup)
                {
                    MatroskaTree[] blocksHere = child.GetChildren(stream, MatroskaTree.Segment_Cluster_BlockGroup_Block);
                    for (int i = 0; i < blocksHere.Length; ++i)
                    {
                        blocks.Add(new Block(stream, blocksHere[i]));
                    }
                }

                // Simple blocks (Matroska v2)
                else if (child.Tag == MatroskaTree.Segment_Cluster_SimpleBlock)
                {
                    blocks.Add(new Block(stream, child));
                }

                stream.Position = continueFrom;
            }

            return(blocks);
        }
Пример #6
0
 /// <summary>
 /// Parse metadata from a cluster.
 /// </summary>
 public Cluster(Stream reader, MatroskaTree source)
 {
     this.source = source;
     TimeStamp   = source.GetChildValue(reader, MatroskaTree.Segment_Cluster_Timestamp);
 }
Пример #7
0
        /// <summary>
        /// Parse the metadata of a data block.
        /// </summary>
        public Block(Stream reader, MatroskaTree source)
        {
            source.Position(reader);
            this.reader = reader;
            long start = reader.Position;

            Track     = VarInt.ReadValue(reader);
            TimeStamp = reader.ReadInt16BE();
            flags     = (byte)reader.ReadByte();

            Lacing lacing = LacingType;

            if (lacing != Lacing.None)
            {
                int x = reader.ReadByte();
                frameCount = x + 1;
                frameSizes = new int[frameCount];
                firstFrame = reader.Position;
                switch (lacing)
                {
                case Lacing.Xiph:
                    byte frame     = 0;
                    long totalSize = 0;
                    while (frame < frameCount - 1)
                    {
                        byte value;
                        int  sum = 0;
                        do
                        {
                            value = (byte)reader.ReadByte();
                            sum  += value;
                        } while (value == 255);
                        totalSize          += sum;
                        frameSizes[frame++] = sum;
                    }
                    frameSizes[frame] = (int)(source.Length - (reader.Position - start) - totalSize);
                    break;

                case Lacing.FixedSize:
                    int step = (int)((source.Length - (firstFrame - start)) / frameCount);
                    for (byte i = 0; i < frameCount; ++i)
                    {
                        frameSizes[i] = step;
                    }
                    break;

                case Lacing.EBML:
                    frameSizes[0] = (int)VarInt.ReadValue(reader);
                    long last = -frameSizes[0];
                    for (int i = 1; i < frameCount - 1; ++i)
                    {
                        frameSizes[i] = frameSizes[i - 1] + (int)VarInt.ReadSignedValue(reader);
                        last         -= frameSizes[i];
                    }
                    frameSizes[frameCount - 1] = (int)(last + source.Length - (reader.Position - start));
                    break;

                default:
                    break;
                }
            }
            else
            {
                firstFrame = reader.Position;
                frameCount = 1;
                frameSizes = new int[1] {
                    (int)(source.Length - (firstFrame - start))
                };
            }
        }
Пример #8
0
        /// <summary>
        /// Get a specific child by its order of the same kind of children.
        /// </summary>
        public MatroskaTree GetChild(Stream reader, int tag, int index)
        {
            if (childIndices == null)
            {
                childIndices = new Dictionary <int, List <int> >();
            }
            List <int> indices;

            if (childIndices.ContainsKey(tag))
            {
                indices = childIndices[tag];
            }
            else
            {
                indices = childIndices[tag] = new List <int>();
            }

            int c = indices.Count;

            if (index < indices.Count)
            {
                return(children[indices[index]]);
            }

            int lastChild = 0;

            if (c != 0)
            {
                lastChild = indices[c - 1] + 1;
            }
            for (int i = lastChild, childCount = children.Count; i < childCount; ++i)
            {
                if (children[i].Tag == tag)
                {
                    indices.Add(i);
                    if (c++ == index)
                    {
                        return(children[i]);
                    }
                }
            }

            int tagIndex = children.Count;

            reader.Position = nextTag;
            while (nextTag < end)
            {
                MatroskaTree subtree = TryCreate(reader, end);
                if (subtree == null)
                {
                    nextTag = end;
                    return(null);
                }

                children.Add(subtree);
                if (subtree.Tag == tag)
                {
                    indices.Add(tagIndex);
                    if (c++ == index)
                    {
                        nextTag = reader.Position;
                        return(subtree);
                    }
                }
                ++tagIndex;
            }
            nextTag = reader.Position;
            return(null);
        }