示例#1
0
        public static ResultOfParsingMKV GetSubFromFile(string mkvFilePath)
        {

            ResultOfParsingMKV resPars = new ResultOfParsingMKV();

            using (var fs = new FileStream(mkvFilePath, FileMode.Open, FileAccess.Read))
            {
                using (EbmlReader ebmlReader = new EbmlReader(fs))
                {
                    var segmentFound = ebmlReader.LocateElement(MatroskaElementDescriptorProvider.Segment);
                    if (segmentFound)
                    {
                        StringBuilder sb = new StringBuilder();
                        MatroskaElementDescriptorProvider medp = new MatroskaElementDescriptorProvider();
                        ReadContainer(ebmlReader, medp, resPars, 0, sb);
                    }
                }
            }

            // reenumerate
            foreach(var elm in resPars.dicSub)
            {
                int i = 1;
                var coll = elm.Value.Items.OrderBy(x => x.TimeStart);
                foreach(var elm2 in coll)
                {
                    elm2.Number = i++;
                }
            }

            return resPars;
        }
示例#2
0
文件: MiscTests.cs 项目: juanii/NEbml
        public void MkvInfo(string filePath)
        {
            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.AreEqual(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();
                }

            }
        }
示例#3
0
 private static void MatroskaTagsDescriptor(EbmlReader ebmlReader, MatroskaElementDescriptorProvider medp, string tab)
 {
     //Console.WriteLine("\t " + (ebmlReader.ElementSize));
     
     while (ebmlReader.ReadNext())
     {
         var descriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
         if (descriptor == null) continue;
         if (descriptor.Name == "Cluster") continue;
         if (descriptor.Name == "Cues") continue;
         Console.WriteLine(tab + descriptor.Name + " " + ebmlReader.ElementPosition);
         if (descriptor.Type == ElementType.MasterElement)
         {
             ebmlReader.EnterContainer();
             MatroskaTagsDescriptor(ebmlReader, medp, tab + "\t");
         }
     }
     ebmlReader.LeaveContainer();
 }
示例#4
0
        // Hierarchie des tags du conteneur MKV
        public static void MatroskaTagsIndentator(string mkvFilePath)
        {
            MatroskaElementDescriptorProvider medp = new MatroskaElementDescriptorProvider();

            using (var fs = new FileStream(mkvFilePath, FileMode.Open, FileAccess.Read))
            using (EbmlReader ebmlReader = new EbmlReader(fs))
            {
                var segmentFound = ebmlReader.LocateElement(MatroskaElementDescriptorProvider.Segment);
                if (segmentFound)
                {
                    ebmlReader.EnterContainer();
                    MatroskaTagsDescriptor(ebmlReader, medp, "");
                }
            }
        }
示例#5
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);
        }
示例#6
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);
        }
示例#7
0
        public void ReusesNextFiller()
        {
            var stream = new MemoryStream();
            var writer = new EbmlWriter(stream);

            writer.Write(VInt.MakeId(122), 321);
            using (var segment = writer.StartMasterElement(MatroskaDtd.Segment.Identifier))
            {
                using (var segmentInfo = segment.StartMasterElement(MatroskaDtd.Segment.Info.Identifier))
                {
                    segmentInfo.WriteUtf(MatroskaDtd.Segment.Info.Title.Identifier, "Test data");
                }

                // write some dummy data
                segment.Write(StandardDtd.Void.Identifier, new byte[1000]);
                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());
        }
示例#8
0
        private void GetMatroskaTags()
        {
            MatroskaElementDescriptorProvider medp = new MatroskaElementDescriptorProvider();

            using (var fs = new FileStream(path + "/" + fullName, FileMode.Open, FileAccess.Read))
            using (EbmlReader ebmlReader = new EbmlReader(fs))
            {
                //Console.WriteLine("--------------" + labelName + "----------------");
                var segmentFound = ebmlReader.LocateElement(MatroskaElementDescriptorProvider.Segment);
                if (segmentFound)
                {
                    ebmlReader.EnterContainer();
                    while (ebmlReader.ReadNext())
                    {
                        var descriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                        if (descriptor == null) continue;
                        if (descriptor.Name == "Tracks")
                        {
                            ebmlReader.EnterContainer();
                            while (ebmlReader.ReadNext())
                            {
                                var trackDescriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                                if (trackDescriptor == null) continue;
                                if (trackDescriptor.Name == "TrackEntry")
                                {
                                    ebmlReader.EnterContainer();
                                    long trackType = 0;
                                    string trackLanguage = null;
                                    while (ebmlReader.ReadNext())
                                    {
                                        var trackEntryDescriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                                        if (trackEntryDescriptor == null) continue;
                                        if (trackEntryDescriptor.Name == "Video")
                                        {
                                            ebmlReader.EnterContainer();
                                            while (ebmlReader.ReadNext())
                                            {
                                                var videoDescriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                                                
                                                if (videoDescriptor == null) continue;
                                                if (videoDescriptor.Name == "PixelWidth")
                                                {
                                                    width = ebmlReader.ReadInt();
                                                }
                                                else if (videoDescriptor.Name == "PixelHeight")
                                                {
                                                    height = ebmlReader.ReadInt();
                                                }
                                            }
                                            ebmlReader.LeaveContainer();
                                        }
                                        else if (trackEntryDescriptor.Name == "TrackType")
                                        {
                                            trackType = ebmlReader.ReadInt();
                                        }
                                        else if (trackEntryDescriptor.Name == "Language")
                                        {
                                            trackLanguage = ebmlReader.ReadUtf();

                                            if (trackType == 0x11) //subtitle
                                            {
                                                listLanguageSubtitle.Add(trackLanguage);
                                                //Console.WriteLine("subtitle : ->" + trackLanguage + "<-");
                                            }
                                            else if (trackType == 2) //audio
                                            {
                                                listLanguageAudio.Add(trackLanguage);
                                                //Console.WriteLine("audio : ->" + trackLanguage + "<-");
                                            }
                                        }

                                    }
                                    ebmlReader.LeaveContainer();
                                }
                            }
                            ebmlReader.LeaveContainer();
                            break;
                        }
                    }
                }
            }
        }
示例#9
0
        private static void AnalizeTrackEntry(EbmlReader ebmlReader, MatroskaElementDescriptorProvider medp, ResultOfParsingMKV resPars, StringBuilder sb, string GroupName = "", string add = "")
        {
            ulong TrackNumber = 0;
            ulong TrackUID = 0;
            ulong TrackType = 0;
            ulong FlagDefault = 0;
            ulong FlagLacing = 0;
            string CodecID = "";
            string Name = "";
            ulong  DefaultDuration = 0;
            string Language = "";
            
            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                var descriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                if (descriptor == null)
                {
                    sb.Append(add + "undefined \r\n");
                    continue;
                }
                string dName = descriptor.Name;
                sb.Append(add + dName);

                switch (descriptor.Type)
                {
                    case ElementType.MasterElement:
                        sb.Append("\r\n");
                        //ReadContainer(ebmlReader, medp, dicSub, CurrentClusterTimeCode, sb, descriptor.Name, add + "    ");
                        break;
                    case ElementType.AsciiString:
                        string strVal = ebmlReader.ReadAscii();
                        if(dName == "CodecID") CodecID = strVal; 
                        if (dName == "Language") Language = strVal; 
                        sb.Append(" = " + strVal);
                        break;
                    case ElementType.Binary:
                        break;
                    case ElementType.Date:
                        sb.Append(" = " + ebmlReader.ReadDate());
                        break;
                    case ElementType.Float:
                        double flVal = ebmlReader.ReadFloat();
                        sb.Append(" = " + flVal);
                        break;
                    case ElementType.None:
                        sb.Append(" (none)");
                        break;
                    case ElementType.SignedInteger:
                        sb.Append(" = " + ebmlReader.ReadInt());
                        break;
                    case ElementType.UnsignedInteger:
                        ulong ulVal = ebmlReader.ReadUInt();
                        if(dName == "TrackNumber") TrackNumber = ulVal;
                        if(dName == "TrackType") TrackType = ulVal;
                        if(dName == "FlagDefault") FlagDefault = ulVal;
                        if(dName == "FlagLacing ") FlagLacing = ulVal;
                        if(dName == "DefaultDuration") DefaultDuration = ulVal;
                        if (dName == "TrackUID") TrackUID = ulVal;
                        sb.Append(" = " + ulVal);
                        break;
                    case ElementType.Utf8String:
                        string utfStr = ebmlReader.ReadUtf();
                        if (dName == "Name") Name = utfStr;
                        sb.Append(" = " + utfStr);
                        break;
                }
                sb.Append("\r\n");
            }
            ebmlReader.LeaveContainer();
            
            // If it's subtitles track
            if (TrackType == 17) { 
                Subtitles sub = new Subtitles();
                sub.Items = new SynchronizedObservableCollection<SubtitleItem>();
                sub.Language = Language.Length == 0 ? "eng" : Language;
                sub.Type = Name;
                sub.Format = CodecID;
                sub.TrackUID = (long)TrackUID;

                resPars.dicSub.Add(Convert.ToInt16(TrackNumber),sub);
            }

            // If it's subtitles track
            if (TrackType == 2)
            {
                AudioTrack aud = new AudioTrack();
                aud.Language = Language.Length == 0 ? "eng" : Language;
                aud.CodecID = CodecID;
                aud.Number = resPars.AudioTracks.Count + 1;

                resPars.AudioTracks.Add(aud);
            }

        }
示例#10
0
        private static void ReadContainer(EbmlReader ebmlReader, MatroskaElementDescriptorProvider medp, ResultOfParsingMKV resPars, ulong CurrentClusterTimeCode, StringBuilder sb, string GroupName = "", string add = "")
        {
            ebmlReader.EnterContainer();
            while (ebmlReader.ReadNext())
            {
                var descriptor = medp.GetElementDescriptor(ebmlReader.ElementId);
                if (descriptor == null)
                {
                    sb.Append(add + "undefined \r\n");
                    continue;
                }
                string dName = descriptor.Name;
                sb.Append(add + dName);

                if (dName == "TrackEntry") {
                    AnalizeTrackEntry(ebmlReader,medp,resPars,sb,GroupName,add);
                    continue;
                }

                switch (descriptor.Type)
                {
                    case ElementType.MasterElement:
                        sb.Append("\r\n");
                        ReadContainer(ebmlReader, medp, resPars, CurrentClusterTimeCode, sb,descriptor.Name, add + "    ");
                        break;
                    case ElementType.AsciiString:
                        sb.Append(" = " + ebmlReader.ReadAscii());
                        break;
                    case ElementType.Binary:
                        if (GroupName == "BlockGroup" && (dName == "Block" || dName == "SimpleBlock"))
                        {
                            int lSize = ebmlReader.ElementSize > 1000?1000:Convert.ToInt16(ebmlReader.ElementSize);
                            byte[] arr = new byte[lSize];
                            ebmlReader.ReadBinary(arr, 0, lSize);
                            int TrackNumber = arr[0] & 0x0F;
                            ulong DurationFromCluster = Convert.ToUInt64(arr[1] * 0xFF + arr[2]);

                            if (resPars.dicSub.ContainsKey(TrackNumber))
                            {
                                Subtitles lsub = resPars.dicSub[TrackNumber];
                                SubtitleItem subitem = new SubtitleItem();
                                lsub.Items.Add(subitem);

                                //subitem.Text = System.Text.Encoding.ASCII.GetString(arr, 4, lSize-4);
                                subitem.Text = System.Text.Encoding.UTF8.GetString(arr, 4, lSize - 4);
                                subitem.TimeStart = ((int)(CurrentClusterTimeCode + DurationFromCluster));

                                // reading the BlockDuration
                                ebmlReader.ReadNext();
                                ulong BlockDuration = ebmlReader.ReadUInt();
                                subitem.TimeEnd = subitem.TimeStart + ((int)BlockDuration);

                            }
                        }
                        sb.Append(" (binary size " + ebmlReader.ElementSize + ")");
                        break;
                    case ElementType.Date:
                        sb.Append(" = " + ebmlReader.ReadDate());
                        break;
                    case ElementType.Float:
                        double flVal = ebmlReader.ReadFloat();
                        sb.Append(" = " + flVal);
                        break;
                    case ElementType.None:
                        sb.Append(" (none)");
                        break;
                    case ElementType.SignedInteger:
                        sb.Append(" = " + ebmlReader.ReadInt());
                        break;
                    case ElementType.UnsignedInteger:
                        ulong ulVal = ebmlReader.ReadUInt();
                        if (GroupName == "Cluster" && dName == "Timecode")
                        {
                            CurrentClusterTimeCode = ulVal;
                        }
                        sb.Append(" = " + ulVal);
                        break;
                    case ElementType.Utf8String:
                        sb.Append(" = " + ebmlReader.ReadUtf());
                        break;
                }
                sb.Append("\r\n");
            }
            ebmlReader.LeaveContainer();
        }