Esempio n. 1
0
        private void ReadAttachment(EbmlReader ebmlReader)
        {
            MatroskaConsts.MatroskaAttachment attachment = new MatroskaConsts.MatroskaAttachment();
            ElementDescriptor desc;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                {
                    if (desc.Name == "FileName")
                    {
                        attachment.FileName = ebmlReader.ReadUtf();
                    }
                    else if (desc.Name == "FileMimeType")
                    {
                        attachment.MimeType = ebmlReader.ReadAscii();
                    }
                    else if (desc.Name == "FileData")
                    {
                        byte[] data = new byte[ebmlReader.ElementSize];
                        ebmlReader.ReadBinary(data, 0, data.Length);
                        _attachments.Add(attachment.FileName, data);

                        attachment.FileSize = ebmlReader.ElementSize;
                    }
                }
            }
            _attachmentList.Add(attachment);
            ebmlReader.LeaveContainer();
        }
Esempio n. 2
0
    /// <summary>
    /// Reads the current position in the file as an unsigned integer converted from binary.
    /// </summary>
    /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
    /// <returns>The unsigned integer.</returns>
    internal static uint ReadUIntFromBinary(this EbmlReader reader)
    {
        var buffer = new byte[4];

        reader.ReadBinary(buffer, 0, 4);
        return(BinaryPrimitives.ReadUInt32BigEndian(buffer));
    }
Esempio n. 3
0
    /// <summary>
    /// Enters the Tracks segment and reads all tracks to find the specified type.
    /// </summary>
    /// <param name="reader">Instance of <see cref="EbmlReader"/>.</param>
    /// <param name="tracksPosition">The relative position of the tracks segment.</param>
    /// <param name="type">The track type identifier.</param>
    /// <returns>The first track number with the specified type.</returns>
    /// <exception cref="InvalidOperationException">Stream type is not found.</exception>
    internal static ulong FindFirstTrackNumberByType(this EbmlReader reader, long tracksPosition, ulong type)
    {
        reader.ReadAt(tracksPosition);

        reader.EnterContainer();
        while (reader.FindElement(MatroskaConstants.TrackEntry))
        {
            reader.EnterContainer();
            // Mandatory element
            reader.FindElement(MatroskaConstants.TrackNumber);
            var trackNumber = reader.ReadUInt();

            // Mandatory element
            reader.FindElement(MatroskaConstants.TrackType);
            var trackType = reader.ReadUInt();

            reader.LeaveContainer();
            if (trackType == MatroskaConstants.TrackTypeVideo)
            {
                reader.LeaveContainer();
                return(trackNumber);
            }
        }

        reader.LeaveContainer();

        throw new InvalidOperationException($"No stream with type {type} found");
    }
        private int[] readEbmlLaceSizes(int index, short laceCount)
        {
            int[] laceSizes = new int[laceCount + 1];
            laceSizes[laceCount] = (int)(data.Length - data.Position);

            int startIndex = index;

            laceSizes[0]          = (int)EbmlReader.ReadEbmlCode(data);
            index                += Utility.CodedSizeLength((ulong)laceSizes[0], 0);
            laceSizes[laceCount] -= laceSizes[0];

            ulong firstEbmlSize = (ulong)laceSizes[0];
            ulong lastEbmlSize  = 0;

            for (int l = 0; l < laceCount - 1; l++)
            {
                lastEbmlSize = EbmlReader.ReadSignedEbmlCode(data);
                index       += Utility.CodedSizeLength(lastEbmlSize, 0);

                firstEbmlSize   += lastEbmlSize;
                laceSizes[l + 1] = (int)firstEbmlSize;

                laceSizes[laceCount] -= laceSizes[l + 1];
            }

            headerSize           += (index - startIndex);
            laceSizes[laceCount] -= headerSize;

            return(laceSizes);
        }
Esempio n. 5
0
        public void ReadWriteContainer()
        {
            var innerdata = new MemoryStream();
            var container = new EbmlWriter(innerdata);

            container.WriteAscii(VInt.MakeId(1), "Hello");
            container.Write(VInt.MakeId(2), 12345);
            container.Write(VInt.MakeId(3), 123.45);

            _writer.Write(VInt.MakeId(5), innerdata.ToArray());
            _writer.WriteAscii(VInt.MakeId(6), "end");

            _stream.Position = 0;
            var reader = new EbmlReader(_stream);

            Assert.IsTrue(reader.ReadNext());
            Assert.AreEqual(VInt.MakeId(5), reader.ElementId);

            reader.EnterContainer();

            // reading inner data
            AssertRead(reader, 1, "Hello", r => r.ReadAscii());
            AssertRead(reader, 2, 12345, r => r.ReadInt());
            AssertRead(reader, 3, 123.45, r => r.ReadFloat());

            reader.LeaveContainer();

            // back to main stream
            AssertRead(reader, 6, "end", r => r.ReadAscii());
        }
Esempio n. 6
0
        public void GetInfoFromMkvFile()
        {
            var filePath = SampleFilePath;

            using (var dataStream = File.OpenRead(filePath))
            {
                var reader = new EbmlReader(dataStream);
                //reader.EnterContainer();

                var headDumper = MakeElementDumper(
                    StandardDtd.EBMLDesc.EBMLVersion,
                    StandardDtd.EBMLDesc.EBMLReadVersion,
                    StandardDtd.EBMLDesc.DocTypeVersion,
                    StandardDtd.EBMLDesc.DocType,
                    StandardDtd.EBMLDesc.DocTypeReadVersion);

                var trackInfoDumper = MakeElementDumper(
                    MatroskaDtd.Tracks.TrackEntry.TrackNumber,
                    MatroskaDtd.Tracks.TrackEntry.Name,
                    MatroskaDtd.Tracks.TrackEntry.Language,
                    MatroskaDtd.Tracks.TrackEntry.TrackType,
                    MatroskaDtd.Tracks.TrackEntry.CodecName
                    );

                reader.ReadNext();
                Assert.Equal(StandardDtd.EBML.Identifier, reader.ElementId);

                headDumper(reader);

                if (reader.LocateElement(MatroskaDtd.Segment))
                {
                    reader.EnterContainer();

                    if (reader.LocateElement(MatroskaDtd.Tracks))
                    {
                        Console.WriteLine("Tracks");
                        reader.EnterContainer();
                        while (reader.ReadNext())
                        {
                            if (reader.ElementId == MatroskaDtd.Tracks.TrackEntry.Identifier)
                            {
                                trackInfoDumper(reader);
                            }
                            Console.WriteLine();
                        }
                        reader.LeaveContainer();
                        Console.WriteLine("end of Tracks");
                    }

                    if (reader.LocateElement(MatroskaDtd.Segment.Cluster))
                    {
                        Console.WriteLine("Got first track");

                        // TODO have to deal with interlaced track data
                    }
                    // reader.LeaveContainer();
                }
            }
        }
Esempio n. 7
0
    /// <summary>
    /// Extracts the keyframes in ticks (scaled using the container timestamp scale) from the matroska container.
    /// </summary>
    /// <param name="filePath">The file path.</param>
    /// <returns>An instance of <see cref="KeyframeData"/>.</returns>
    public static KeyframeData GetKeyframeData(string filePath)
    {
        using var stream = File.OpenRead(filePath);
        using var reader = new EbmlReader(stream);

        var seekHead = reader.ReadSeekHead();
        // External lib does not support seeking backwards (yet)
        Info  info;
        ulong videoTrackNumber;

        if (seekHead.InfoPosition < seekHead.TracksPosition)
        {
            info             = reader.ReadInfo(seekHead.InfoPosition);
            videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVideo);
        }
        else
        {
            videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVideo);
            info             = reader.ReadInfo(seekHead.InfoPosition);
        }

        var keyframes = new List <long>();

        reader.ReadAt(seekHead.CuesPosition);
        reader.EnterContainer();

        while (reader.FindElement(MatroskaConstants.CuePoint))
        {
            reader.EnterContainer();
            ulong?trackNumber = null;
            // Mandatory element
            reader.FindElement(MatroskaConstants.CueTime);
            var cueTime = reader.ReadUInt();

            // Mandatory element
            reader.FindElement(MatroskaConstants.CueTrackPositions);
            reader.EnterContainer();
            if (reader.FindElement(MatroskaConstants.CuePointTrackNumber))
            {
                trackNumber = reader.ReadUInt();
            }

            reader.LeaveContainer();

            if (trackNumber == videoTrackNumber)
            {
                keyframes.Add(ScaleToTicks(cueTime, info.TimestampScale));
            }

            reader.LeaveContainer();
        }

        reader.LeaveContainer();

        var result = new KeyframeData(ScaleToTicks(info.Duration ?? 0, info.TimestampScale), keyframes);

        return(result);
    }
Esempio n. 8
0
        private void ReadTag(EbmlReader ebmlReader)
        {
            ulong             targetValue = 0;
            ElementDescriptor desc;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                {
                    if (desc.Name == "Targets")
                    {
                        ebmlReader.EnterContainer();
                        while (ebmlReader.ReadNext())
                        {
                            if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc) && desc.Name == "TargetTypeValue")
                            {
                                targetValue = ebmlReader.ReadUInt();
                            }
                        }
                        ebmlReader.LeaveContainer();
                    }
                    else if (desc.Name == "SimpleTag")
                    {
                        string tagName = null;
                        ebmlReader.EnterContainer();
                        while (ebmlReader.ReadNext())
                        {
                            if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                            {
                                if (desc.Name == "TagName")
                                {
                                    tagName = ebmlReader.ReadUtf();
                                }
                                else if (desc.Name == "TagString")
                                {
                                    string key = $"{targetValue}.{tagName}";
                                    if (!_tags.ContainsKey(key))
                                    {
                                        _tags.Add(key, new List <string> {
                                            ebmlReader.ReadUtf()
                                        });
                                    }
                                    else
                                    {
                                        _tags[key].Add(ebmlReader.ReadUtf());
                                    }
                                }
                            }
                        }
                        ebmlReader.LeaveContainer();
                    }
                }
            }
            ebmlReader.LeaveContainer();
        }
Esempio n. 9
0
        private EbmlReader StartRead()
        {
            _stream.Position = 0;
            var reader = new EbmlReader(_stream);

            Assert.IsTrue(reader.ReadNext());
            Assert.AreEqual(ElementId, reader.ElementId);

            return(reader);
        }
Esempio n. 10
0
        private List <(ElementDescriptor Element, ulong Position)> ReadSeekHeads(EbmlReader ebmlReader)
        {
            List <(ElementDescriptor, ulong)> availableElements = null;
            ElementDescriptor desc;
            ElementDescriptor availDesc = null;
            ulong             pos       = 0;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                {
                    if (desc.Name == "Seek")
                    {
                        ebmlReader.EnterContainer();
                        try
                        {
                            while (ebmlReader.ReadNext())
                            {
                                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                                {
                                    if (desc.Name == "SeekID")
                                    {
                                        byte[] data = new byte[ebmlReader.ElementSize];
                                        ebmlReader.ReadBinary(data, 0, data.Length);
                                        MemoryStream mem  = new MemoryStream(data);
                                        byte[]       temp = new byte[data.Length];
                                        VInt         id   = VInt.Read(mem, data.Length, temp);
                                        _descriptorsMap.TryGetValue(id.EncodedValue, out availDesc);
                                    }
                                    else if (desc.Name == "SeekPosition")
                                    {
                                        pos = ebmlReader.ReadUInt();
                                    }
                                }
                            }

                            if (availableElements == null)
                            {
                                availableElements = new List <(ElementDescriptor, ulong)>();
                            }
                            if (availDesc != null && pos > 0)
                            {
                                availableElements.Add((availDesc, pos));
                            }
                        }
                        catch { }
                    }
                    ebmlReader.LeaveContainer();
                }
            }
            ebmlReader.LeaveContainer();
            return(availableElements);
        }
Esempio n. 11
0
        public static string GetName(this EbmlReader r, bool dumpValue = false)
        {
            string name = "?";
            string dump = "?";

            if (MatroskaSpecification.ElementDescriptors.TryGetValue(r.ElementId, out var el))
            {
                name = el.Name;

                if (dumpValue)
                {
                    switch (el.Type)
                    {
                    case ElementType.AsciiString:
                        dump = r.ReadAscii();
                        break;

                    case ElementType.Binary:
                        dump = "'Binary Data'";
                        break;

                    case ElementType.Date:
                        dump = r.ReadDate().ToString();
                        break;

                    case ElementType.Float:
                        dump = r.ReadFloat().ToString();
                        break;

                    case ElementType.SignedInteger:
                        dump = r.ReadInt().ToString();
                        break;

                    case ElementType.UnsignedInteger:
                        dump = r.ReadUInt().ToString();
                        break;

                    case ElementType.Utf8String:
                        dump = r.ReadUtf();
                        break;

                    case ElementType.MasterElement:
                        dump = "'MasterElement'";
                        break;

                    default:
                        dump = $"unknown (id:{r})";
                        break;
                    }
                }
            }

            return($"0x{r.ElementId.Value:X8} {name} [{r.ElementSize} bytes]" + (dumpValue ? " Value: " + dump : ""));
        }
Esempio n. 12
0
    /// <summary>
    /// Traverses the current container to find the element with <paramref name="identifier"/> identifier.
    /// </summary>
    /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
    /// <param name="identifier">The element identifier.</param>
    /// <returns>A value indicating whether the element was found.</returns>
    internal static bool FindElement(this EbmlReader reader, ulong identifier)
    {
        while (reader.ReadNext())
        {
            if (reader.ElementId.EncodedValue == identifier)
            {
                return(true);
            }
        }

        return(false);
    }
Esempio n. 13
0
        public static bool LocateElement(this EbmlReader reader, ulong identifier)
        {
            while (reader.ReadNext())
            {
                if (reader.ElementId == identifier)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 14
0
        public static bool LocateElement(this EbmlReader reader, ElementDescriptor descriptor)
        {
            while (reader.ReadNext())
            {
                var identifier = reader.ElementId;

                if (identifier == descriptor.Identifier)
                {
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 15
0
        public void ReusesPriorFiller()
        {
            var stream = new MemoryStream();
            var writer = new EbmlWriter(stream);

            writer.Write(VInt.MakeId(122), 321);
            using (var segment = writer.StartMasterElement(MatroskaDtd.Segment.Identifier))
            {
                segment.Write(StandardDtd.Void.Identifier, new byte[1000]);

                using (var segmentInfo = segment.StartMasterElement(MatroskaDtd.Segment.Info.Identifier))
                {
                    segmentInfo.WriteUtf(MatroskaDtd.Segment.Info.Title.Identifier, "Test data");
                }

                // write some dummy data
                segment.Write(VInt.MakeId(123), 123);                   // marker
            }

            stream.Position = 0;

            // act
            var infoReader = new SegmentInfoUpdater();

            infoReader.Open(stream);
            infoReader.Title = new string('a', 500);
            infoReader.Write();

            // verify the stream is correct
            stream.Position = 0;
            var reader = new EbmlReader(stream);

            reader.ReadNext();
            Assert.AreEqual(122, reader.ElementId.Value, "start marker");
            Assert.AreEqual(321, reader.ReadInt());

            reader.ReadNext();
            Assert.AreEqual(MatroskaDtd.Segment.Identifier, reader.ElementId);
            reader.EnterContainer();

            reader.ReadNext();
            Assert.AreEqual(MatroskaDtd.Segment.Info.Identifier, reader.ElementId);
            Assert.Greater(reader.ElementSize, 500);

            reader.ReadNext();
            Assert.AreEqual(StandardDtd.Void.Identifier, reader.ElementId);

            reader.ReadNext();
            Assert.AreEqual(123, reader.ElementId.Value, "end data marker");
            Assert.AreEqual(123, reader.ReadInt());
        }
Esempio n. 16
0
        public void ParseBlock()
        {
            int index = 0;

            TrackNumber = (int)EbmlReader.ReadEbmlCode(data);
            index       = Utility.CodedSizeLength((ulong)TrackNumber, 0);
            headerSize += index;

            byte[] readBytes = new byte[2];
            data.Read(readBytes, 0, 2);
            BlockTimecode = BitConverter.ToInt16(readBytes, 0);

            byte flagsByte = (byte)data.ReadByte();
            int  keyFlag   = flagsByte & 0x80;

            IsKeyFrame = keyFlag > 0;

            int laceFlag = flagsByte & 0x06;

            index++;

            headerSize += 3;
            if (laceFlag != 0x00)
            {
                byte laceCount = (byte)data.ReadByte();
                headerSize += 1;
                if (laceFlag == 0x02)
                {
                    sizes = readXiphLaceSizes(index, laceCount);
                }
                else if (laceFlag == 0x06)
                {
                    sizes = readEbmlLaceSizes(index, laceCount);
                }
                else if (laceFlag == 0x04)
                {
                    sizes    = new int[laceCount + 1];
                    sizes[0] = (int)((data.Length - data.Position) - headerSize) / (laceCount + 1);
                    for (int s = 0; s < laceCount; s++)
                    {
                        sizes[s + 1] = sizes[0];
                    }
                }
                else
                {
                    throw new Exception("Unsupported lacing type flag.");
                }
            }
            headerSize = (int)data.Position;
        }
Esempio n. 17
0
        public MatroskaFile(FileStream inputDataSource)
        {
            level0           = null;
            TimecodeScale    = 1000000;
            stream           = inputDataSource;
            reader           = new EbmlReader(stream);
            trackList        = new List <MatroskaFileTrack>();
            tagList          = new List <MatroskaFileTagEntry>();
            frameQueue       = new List <MatroskaFileFrame>();
            ScanFirstCluster = true;
            logger           = null;

            initDocTypes();
        }
Esempio n. 18
0
        private void ReadTags(EbmlReader ebmlReader)
        {
            _tags = new Dictionary <string, IList <string> >();
            ElementDescriptor desc;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc) && desc.Name == "Tag")
                {
                    ReadTag(ebmlReader);
                }
            }
            ebmlReader.LeaveContainer();
        }
Esempio n. 19
0
        public static MatroskaDocument Deserialize(Stream stream)
        {
            var reader = new EbmlReader(stream);

            reader.ReadNext();
            var ebml = Deserialize <EBML>(reader);

            reader.ReadNext();
            var segment = Deserialize <Segment>(reader);

            return(new MatroskaDocument
            {
                Ebml = ebml,
                Segment = segment
            });
        }
Esempio n. 20
0
        private void ReadAttachments(EbmlReader ebmlReader)
        {
            _attachments    = new Dictionary <string, byte[]>();
            _attachmentList = new List <MatroskaConsts.MatroskaAttachment>();
            ElementDescriptor desc;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc) && desc.Name == "AttachedFile")
                {
                    ReadAttachment(ebmlReader);
                }
            }
            ebmlReader.LeaveContainer();
        }
Esempio n. 21
0
        private static object GetValue(MatroskaElementInfo info, EbmlReader reader)
        {
            switch (info.ElementDescriptor.Type)
            {
            case ElementType.AsciiString:
                return(reader.ReadAscii());

            case ElementType.Binary:
                int bufferLength = (int)reader.ElementSize;
                var buffer       = new byte[bufferLength];
                reader.ReadBinary(buffer, 0, bufferLength);     // TODO : EbmlReader does not yet support reading a Span<byte>

                if (typeof(IParseRawBinary).IsAssignableFrom(info.ElementType))
                {
                    var parsedRawBinary = (IParseRawBinary)Activator.CreateInstance(info.ElementType);
                    parsedRawBinary.Parse(buffer);

                    return(parsedRawBinary);
                }

                return(buffer);

            case ElementType.Date:
                return(reader.ReadDate());

            case ElementType.Float:
                return(reader.ReadFloat());

            case ElementType.MasterElement:
                return(Deserialize(info.ElementType, reader));

            case ElementType.SignedInteger:
                return(reader.ReadInt());

            case ElementType.UnsignedInteger:
                return(reader.ReadUInt());

            case ElementType.Utf8String:
                return(reader.ReadUtf());
            }

            throw new NotSupportedException();
        }
Esempio n. 22
0
        private void ReadInfo(EbmlReader ebmlReader)
        {
            _infoProps = new Dictionary <string, IList <string> >();
            ElementDescriptor desc;

            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                if (_descriptorsMap.TryGetValue(ebmlReader.ElementId.EncodedValue, out desc))
                {
                    if (!_infoProps.ContainsKey(desc.Name))
                    {
                        _infoProps.Add(desc.Name, new List <string>());
                    }

                    if (desc.Type == ElementType.AsciiString)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadAscii());
                    }
                    else if (desc.Type == ElementType.Date)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadDate().ToString(CultureInfo.InvariantCulture));
                    }
                    else if (desc.Type == ElementType.Float)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadFloat().ToString(CultureInfo.InvariantCulture));
                    }
                    else if (desc.Type == ElementType.SignedInteger)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadInt().ToString(CultureInfo.InvariantCulture));
                    }
                    else if (desc.Type == ElementType.UnsignedInteger)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadUInt().ToString(CultureInfo.InvariantCulture));
                    }
                    else if (desc.Type == ElementType.Utf8String)
                    {
                        _infoProps[desc.Name].Add(ebmlReader.ReadUtf());
                    }
                }
            }
            ebmlReader.LeaveContainer();
        }
Esempio n. 23
0
    /// <summary>
    /// Reads from SegmentContainer to retrieve the Info segment.
    /// </summary>
    /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
    /// <param name="position">The position of the info segment relative to the Segment container.</param>
    /// <returns>Instance of <see cref="Info"/>.</returns>
    internal static Info ReadInfo(this EbmlReader reader, long position)
    {
        reader.ReadAt(position);

        double?duration = null;

        reader.EnterContainer();
        // Mandatory element
        reader.FindElement(MatroskaConstants.TimestampScale);
        var timestampScale = reader.ReadUInt();

        if (reader.FindElement(MatroskaConstants.Duration))
        {
            duration = reader.ReadFloat();
        }

        reader.LeaveContainer();

        return(new Info((long)timestampScale, duration));
    }
Esempio n. 24
0
        public static void LoadSRS(SortedList <int, TrackData> tracks, ref FileData file, FileInfo inFile)
        {
            using (EbmlReader rdr = new EbmlReader(inFile.FullName, EbmlReadMode.SRS))
            {
                bool done = false;
                while (!done && rdr.Read())
                {
                    switch (rdr.ElementType)
                    {
                    case EbmlElementType.Segment:
                    case EbmlElementType.ReSample:
                        rdr.MoveToChild();
                        break;

                    case EbmlElementType.ReSampleFile:
                        byte[] buff = rdr.ReadContents();
                        file = new FileData(buff);
                        break;

                    case EbmlElementType.ReSampleTrack:
                        buff = rdr.ReadContents();
                        TrackData track = new TrackData(buff);
                        tracks.Add(track.TrackNumber, track);
                        break;

                    case EbmlElementType.Cluster:
                    case EbmlElementType.AttachmentList:
                        // if we get to either of these elements, we've passed the interesting part of the file, so bail out
                        rdr.SkipContents();
                        done = true;
                        break;

                    default:
                        rdr.SkipContents();
                        break;
                    }
                }
            }
        }
Esempio n. 25
0
        public Element ReadNextChild(EbmlReader reader)
        {
            if (usedSize >= Size)
            {
                Utility.LogTrace("Can't read any more children.");
                return(null);
            }

            Element element = reader.ReadNextElement();

            if (element == null)
            {
                Utility.LogDebug("Reader returned null");
                return(null);
            }

            element.Parent = this;

            usedSize += element.TotalSize;

            Utility.LogTrace($"Read element {element.TypeInfo.Name} of size {element.TotalSize}, {Size - usedSize} remaining.");
            return(element);
        }
Esempio n. 26
0
        public static object Deserialize(Type type, EbmlReader reader)
        {
            bool isMasterElement = reader.IsKnownMasterElement();

            if (isMasterElement)
            {
                reader.EnterContainer();
            }

            var instance = Activator.CreateInstance(type);

            try
            {
                while (reader.ReadNext())
                {
                    if (TryGetInfoByIdentifier(type, reader.ElementId.EncodedValue, out var info))
                    {
                        SetPropertyValue(instance, info, reader);
                    }
                    else
                    {
                        Console.WriteLine($"WARNING: {instance.GetType().Name}: property {reader.GetName(true)} not mapped.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: {instance.GetType().Name} at position {reader.ElementPosition} not mapped. Exception: {ex}");
            }

            if (isMasterElement)
            {
                reader.LeaveContainer();
            }

            return(instance);
        }
Esempio n. 27
0
        public static FileData RebuildSample(FileData file, SortedList <int, TrackData> tracks, Dictionary <string, AttachmentData> attachments, FileInfo srsFile, DirectoryInfo outDir)
        {
            uint crc = Crc32.StartValue;

            using (EbmlReader rdr = new EbmlReader(srsFile.FullName, EbmlReadMode.SRS))
                using (FileStream fsOut = new FileStream(Path.Combine(outDir.FullName, file.Name), FileMode.Create))
                {
                    string currentAttachment = null;
                    int    clustercount      = 0;
                    while (rdr.Read())
                    {
                        // the ReSample element is the only part of the SRS file we don't want copied into the new sample.
                        if (rdr.ElementType == EbmlElementType.ReSample)
                        {
                            rdr.SkipContents();
                            continue;
                        }

                        fsOut.Write(rdr.Element.RawHeader, 0, rdr.Element.RawHeader.Length);
                        crc = Crc32.GetCrc(crc, rdr.Element.RawHeader);

                        switch (rdr.ElementType)
                        {
                        case EbmlElementType.Segment:
                        case EbmlElementType.BlockGroup:
                        case EbmlElementType.AttachmentList:
                        case EbmlElementType.Attachment:
                            // these elements have no useful info of their own, but we want to step into them to examine their children
                            rdr.MoveToChild();
                            break;

                        case EbmlElementType.Cluster:
                            // simple progress indicator since this can take a while (cluster is good because they're about 1mb each)
                            Console.Write("\b{0}", Program.spinners[clustercount++ % Program.spinners.Length]);
                            rdr.MoveToChild();
                            break;

                        case EbmlElementType.AttachedFileName:
                            byte[] buff = rdr.ReadContents();
                            fsOut.Write(buff, 0, buff.Length);
                            crc = Crc32.GetCrc(crc, buff);
                            currentAttachment = Encoding.UTF8.GetString(buff);
                            break;

                        case EbmlElementType.AttachedFileData:
                            AttachmentData attachment = attachments[currentAttachment];
                            // restore data from extracted attachments
                            buff = new byte[rdr.Element.Length];
                            attachment.AttachmentFile.Read(buff, 0, buff.Length);
                            fsOut.Write(buff, 0, buff.Length);
                            crc = Crc32.GetCrc(crc, buff);
                            if ((file.Flags & FileData.FileDataFlags.AttachmentsRemoved) != 0)
                            {
                                rdr.MoveToChild();                                  // really means do nothing in this case
                            }
                            else
                            {
                                rdr.SkipContents();
                            }
                            break;

                        case EbmlElementType.Block:
                            TrackData track = tracks[rdr.Block.TrackNumber];
                            // restore data from extracted tracks
                            buff = new byte[rdr.Block.Length];
                            track.TrackFile.Read(buff, 0, buff.Length);
                            fsOut.Write(rdr.Block.RawBlockHeader, 0, rdr.Block.RawBlockHeader.Length);
                            crc = Crc32.GetCrc(crc, rdr.Block.RawBlockHeader);
                            fsOut.Write(buff, 0, buff.Length);
                            crc = Crc32.GetCrc(crc, buff);
                            rdr.MoveToChild();                              // really means do nothing in this case
                            break;

                        default:
                            // anything not caught above is considered metadata, so we copy it as is
                            buff = rdr.ReadContents();
                            fsOut.Write(buff, 0, buff.Length);
                            crc = Crc32.GetCrc(crc, buff);
                            break;
                        }
                    }
                }
            Console.Write('\b');

            FileData newFile = new FileData(Path.Combine(outDir.FullName, file.Name));

            newFile.Crc32 = ~crc;

            return(newFile);
        }
Esempio n. 28
0
 private static void AssertRead <T>(EbmlReader reader, uint elementId, T value, Func <EbmlReader, T> read)
 {
     Assert.IsTrue(reader.ReadNext());
     Assert.AreEqual(VInt.MakeId(elementId), reader.ElementId);
     Assert.AreEqual(value, read(reader));
 }
Esempio n. 29
0
        private void WriteData()
        {
            var reader = new EbmlReader(new MemoryStream(_oldSegmentInfoData), _oldSegmentInfoData.Length);

            // prepare writing part
            var infoStream = new MemoryStream();
            var infoWriter = new EbmlWriter(infoStream);

            var writeMap = new[]
            {
                new { Id = MatroskaDtd.Segment.Info.Title.Identifier, Value = _title },
                new { Id = MatroskaDtd.Segment.Info.WritingApp.Identifier, Value = _writingApp },
            };

            // enter the Segment block
            reader.ReadNext();
            reader.EnterContainer();

            while (reader.ReadNext())
            {
                if (!writeMap.Any(arg => arg.Id == reader.ElementId))
                {
                    // copying data as is
                    var buffer = new byte[reader.ElementSize];
                    reader.ReadBinary(buffer, 0, (int)reader.ElementSize);
                    infoWriter.Write(reader.ElementId, buffer);
                }
            }

            // write title/app in case it was not present!
            foreach (var e in writeMap.Where(arg => !string.IsNullOrEmpty(arg.Value)))
            {
                infoWriter.WriteUtf(e.Id, e.Value);
            }

            var outStream = new MemoryStream(_dataLength);
            var writer    = new EbmlWriter(outStream);

            writer.Write(MatroskaDtd.Segment.Info.Identifier, infoStream.ToArray());
            var extraByteCount = _dataLength - outStream.Position;

            if (extraByteCount != 0)
            {
                var extraHLen = StandardDtd.Void.Identifier.Length + 2;

                var blankDataLen = (int)(extraByteCount - extraHLen);
                if (blankDataLen < 0)
                {
                    throw new InvalidOperationException(string.Format("Not enough space to put the new data, {0} bytes to feet", -blankDataLen));
                }

                writer.WriteElementHeader(StandardDtd.Void.Identifier, VInt.EncodeSize((ulong)blankDataLen, 2));
                writer.Write(new byte[blankDataLen], 0, blankDataLen);
            }

            if (outStream.Length != _dataLength)
            {
                throw new InvalidOperationException("Failed to prepare modified data - block length mismatch");
            }

            _stream.Position = _dataStart;
            _stream.Write(outStream.ToArray(), 0, _dataLength);
        }
Esempio n. 30
0
        private void ReadData(Stream src)
        {
            var reader = new EbmlReader(src);

            var readMap = new[]
            {
                new { Element = MatroskaDtd.Segment.Info.Title, Code = new Action(() => _title = reader.ReadUtf()) },
                new { Element = MatroskaDtd.Segment.Info.WritingApp, Code = new Action(() => _writingApp = reader.ReadUtf()) },
                new { Element = MatroskaDtd.Segment.Info.MuxingApp, Code = new Action(() => MuxingApp = reader.ReadUtf()) },
                new { Element = MatroskaDtd.Segment.Info.Duration, Code = new Action(() => Duration = TimeSpan.FromMilliseconds(reader.ReadFloat())) },
            };

            if (!reader.LocateElement(MatroskaDtd.Segment))
            {
                throw new InvalidDataException("Failed to locate Segment");
            }

            reader.EnterContainer();

            var segmentInfoIdentifier = MatroskaDtd.Segment.Info.Identifier;

            // support for Void block right before SegmentInfo
            var priorElementId    = VInt.MakeId(0);
            var priorElementStart = -1l;

            // locate SegmentInfo and track its predesessor
            while (reader.ReadNext())
            {
                if (reader.ElementId == segmentInfoIdentifier)
                {
                    break;
                }
                priorElementId    = reader.ElementId;
                priorElementStart = reader.ElementPosition;
            }

            if (reader.ElementId != segmentInfoIdentifier)
            {
                throw new InvalidDataException("Failed to locate Segment");
            }

            _dataStart = priorElementId == StandardDtd.Void.Identifier ? priorElementStart : reader.ElementPosition;
            var oldDataStart = reader.ElementPosition;

            reader.EnterContainer();

            while (reader.ReadNext())
            {
                var entry = readMap.FirstOrDefault(arg => arg.Element.Identifier == reader.ElementId);
                if (entry != null)
                {
                    entry.Code();
                }
            }

            reader.LeaveContainer();

            // getting start of the next element
            reader.ReadNext();
            if (reader.ElementId == StandardDtd.Void.Identifier)
            {
                reader.ReadNext();
            }
            _dataLength = (int)(reader.ElementPosition - _dataStart);

            var oldDataLen = (int)(reader.ElementPosition - oldDataStart);

            _oldSegmentInfoData = new byte[oldDataLen];
            _stream.Seek(oldDataStart, SeekOrigin.Begin);
            _stream.Read(_oldSegmentInfoData, 0, oldDataLen);
        }