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); } }
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); }
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(); }