Example #1
0
        private void ParseMkvMergeOutput()
        {
            // start the loop for each line of the output
            foreach (String outputLine in _MKVMergeOutput.ToString().Split(new String[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
            {
                if (outputLine.StartsWith("File "))
                {
                    gMKVSegmentInfo tmp = new gMKVSegmentInfo();
                    if (outputLine.Contains("muxing_application:"))
                    {
                        tmp.MuxingApplication = ExtractProperty(outputLine, "muxing_application");
                    }
                    if (outputLine.Contains("writing_application:"))
                    {
                        tmp.WritingApplication = ExtractProperty(outputLine, "writing_application");
                    }
                    if (outputLine.Contains("date_utc:"))
                    {
                        tmp.Date = DateTime.ParseExact(ExtractProperty(outputLine, "date_utc"), formats, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime().
                                   ToString("ddd MMM dd HH:mm:ss yyyy UTC", CultureInfo.InvariantCulture);
                    }
                    if (outputLine.Contains("duration:"))
                    {
                        //Duration: 5979.008s (01:39:39.008)
                        String   originalDuration = ExtractProperty(outputLine, "duration");
                        TimeSpan tmpTime          = TimeSpan.FromMilliseconds(Convert.ToDouble(Int64.Parse(originalDuration)) / 1000000.0);
                        tmp.Duration = String.Format("{0}s ({1}:{2}:{3}.{4})",
                                                     (Convert.ToDouble(Int64.Parse(originalDuration)) / 1000000000.0).ToString("#0.000", CultureInfo.InvariantCulture),
                                                     tmpTime.Hours.ToString("00"),
                                                     tmpTime.Minutes.ToString("00"),
                                                     tmpTime.Seconds.ToString("00"),
                                                     tmpTime.Milliseconds.ToString("000"));
                    }
                    if (!String.IsNullOrEmpty(tmp.MuxingApplication) &&
                        !String.IsNullOrEmpty(tmp.WritingApplication) &&
                        !String.IsNullOrEmpty(tmp.Duration))
                    {
                        _SegmentList.Add(tmp);
                    }
                }
                else if (outputLine.StartsWith("Track ID "))
                {
                    Int32 trackID = Int32.Parse(outputLine.Substring(0, outputLine.IndexOf(":")).Replace("Track ID", String.Empty).Trim());
                    // Check if there is already a track with the same TrackID (workaround for a weird bug in MKVToolnix v4 when identifying files from AviDemux)
                    bool trackFound = false;
                    foreach (gMKVSegment tmpSeg in _SegmentList)
                    {
                        if (tmpSeg is gMKVTrack && ((gMKVTrack)tmpSeg).TrackID == trackID)
                        {
                            // If we already have a track with the same trackID, then don't bother adding it again
                            trackFound = true;
                            break;
                        }
                    }
                    // Check if track found
                    if (trackFound)
                    {
                        // If we already have a track with the same trackID, then don't bother adding it again
                        continue;
                    }
                    gMKVTrack tmp = new gMKVTrack();
                    tmp.TrackType = (MkvTrackType)Enum.Parse(typeof(MkvTrackType), outputLine.Substring(outputLine.IndexOf(":") + 1, outputLine.IndexOf("(") - outputLine.IndexOf(":") - 1).Trim());
                    tmp.TrackID   = trackID;
                    if (outputLine.Contains("number"))
                    {
                        // if we have version 5.x and newer
                        tmp.TrackNumber = Int32.Parse(ExtractProperty(outputLine, "number"));
                    }
                    else
                    {
                        // if we have version 4.x and older
                        tmp.TrackNumber = tmp.TrackID;
                    }
                    if (outputLine.Contains("codec_id"))
                    {
                        // if we have version 5.x and newer
                        tmp.CodecID = ExtractProperty(outputLine, "codec_id");
                    }
                    else
                    {
                        // if we have version 4.x and older
                        tmp.CodecID = outputLine.Substring(outputLine.IndexOf("(") + 1, outputLine.IndexOf(")") - outputLine.IndexOf("(") - 1);
                    }

                    if (outputLine.Contains("language:"))
                    {
                        tmp.Language = ExtractProperty(outputLine, "language");
                    }
                    if (outputLine.Contains("track_name:"))
                    {
                        tmp.TrackName = ExtractProperty(outputLine, "track_name");
                    }
                    if (outputLine.Contains("codec_private_data:"))
                    {
                        tmp.CodecPrivateData = ExtractProperty(outputLine, "codec_private_data");
                    }
                    switch (tmp.TrackType)
                    {
                    case MkvTrackType.video:
                        if (outputLine.Contains("pixel_dimensions:"))
                        {
                            tmp.ExtraInfo = ExtractProperty(outputLine, "pixel_dimensions");
                        }
                        // in versions after v9.0.1, Mosu was kind enough to provide us with the minimum_timestamp property
                        // in order to determine the current track's delay
                        if (outputLine.Contains("minimum_timestamp:"))
                        {
                            Int64 tmpInt64;
                            if (Int64.TryParse(ExtractProperty(outputLine, "minimum_timestamp"), out tmpInt64))
                            {
                                tmp.MinimumTimestamp = tmpInt64;
                            }
                        }
                        break;

                    case MkvTrackType.audio:
                        if (outputLine.Contains("audio_sampling_frequency:"))
                        {
                            tmp.ExtraInfo = ExtractProperty(outputLine, "audio_sampling_frequency");
                        }
                        if (outputLine.Contains("audio_channels:"))
                        {
                            tmp.ExtraInfo += ", Ch:" + ExtractProperty(outputLine, "audio_channels");
                        }
                        // in versions after v9.0.1, Mosu was kind enough to provide us with the minimum_timestamp property
                        // in order to determine the current track's delay
                        if (outputLine.Contains("minimum_timestamp:"))
                        {
                            Int64 tmpInt64;
                            if (Int64.TryParse(ExtractProperty(outputLine, "minimum_timestamp"), out tmpInt64))
                            {
                                tmp.MinimumTimestamp = tmpInt64;
                            }
                        }
                        break;

                    case MkvTrackType.subtitles:
                        break;

                    default:
                        break;
                    }
                    _SegmentList.Add(tmp);
                }
                else if (outputLine.StartsWith("Attachment ID "))
                {
                    gMKVAttachment tmp = new gMKVAttachment();
                    tmp.ID       = Int32.Parse(outputLine.Substring(0, outputLine.IndexOf(":")).Replace("Attachment ID", String.Empty).Trim());
                    tmp.Filename = outputLine.Substring(outputLine.IndexOf("file name")).Replace("file name", string.Empty);
                    tmp.Filename = tmp.Filename.Substring(tmp.Filename.IndexOf("'") + 1, tmp.Filename.LastIndexOf("'") - 2).Trim();
                    tmp.FileSize = outputLine.Substring(outputLine.IndexOf("size")).Replace("size", string.Empty).Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0].Replace("bytes", String.Empty).Trim();
                    tmp.MimeType = outputLine.Substring(outputLine.IndexOf("type")).Replace("type", string.Empty).Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0].Replace("'", String.Empty).Trim();
                    _SegmentList.Add(tmp);
                }
                else if (outputLine.StartsWith("Chapters: "))
                {
                    gMKVChapter tmp = new gMKVChapter();
                    tmp.ChapterCount = Int32.Parse(outputLine.Replace("Chapters: ", string.Empty).Replace("entry", String.Empty).Replace("entries", string.Empty).Trim());
                    _SegmentList.Add(tmp);
                }
            }
        }
Example #2
0
        private void ParseMkvInfoOutput()
        {
            // start the loop for each line of the output
            gMKVSegment       tmpSegment   = null;
            MkvInfoParseState tmpState     = MkvInfoParseState.Searching;
            Int32             attachmentID = 1;

            foreach (String outputLine in _MKVInfoOutput.ToString().Split(new String[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
            {
                // first determine the parse state we are in
                //if (outputLine.Contains("Segment,"))
                //{
                //    tmpState = MkvInfoParseState.InsideSegmentInfo;
                //    continue;
                //}
                if (outputLine.Contains("Segment information"))
                {
                    // if previous segment is not null, add it to the list and create a new one
                    if (tmpSegment != null)
                    {
                        _SegmentList.Add(tmpSegment);
                    }
                    tmpSegment = new gMKVSegmentInfo();
                    tmpState   = MkvInfoParseState.InsideSegmentInfo;
                    continue;
                }
                else if (outputLine.Contains("Segment tracks"))
                {
                    tmpState = MkvInfoParseState.InsideTrackInfo;
                    continue;
                }
                else if (outputLine.Contains("Attachments"))
                {
                    tmpState = MkvInfoParseState.InsideAttachentInfo;
                    continue;
                }
                else if (outputLine.Contains("Chapters"))
                {
                    tmpState = MkvInfoParseState.InsideChapterInfo;
                    continue;
                }

                // now that we have determined the state, we parse the segment
                switch (tmpState)
                {
                case MkvInfoParseState.Searching:
                    // if we are still searching for the state, just continue with next line
                    continue;

                case MkvInfoParseState.InsideSegmentInfo:
                    //if (outputLine.Contains("Segment information"))
                    //{
                    //    // if previous segment is not null, add it to the list and create a new one
                    //    if (tmpSegment != null)
                    //    {
                    //        _SegmentList.Add(tmpSegment);
                    //    }
                    //    tmpSegment = new gMKVSegmentInfo();
                    //}
                    //else if (outputLine.Contains("Timecode scale:"))
                    if (outputLine.Contains("Timecode scale:"))
                    {
                        ((gMKVSegmentInfo)tmpSegment).TimecodeScale = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Muxing application:"))
                    {
                        ((gMKVSegmentInfo)tmpSegment).MuxingApplication = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Writing application:"))
                    {
                        ((gMKVSegmentInfo)tmpSegment).WritingApplication = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Duration:"))
                    {
                        ((gMKVSegmentInfo)tmpSegment).Duration = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Date:"))
                    {
                        ((gMKVSegmentInfo)tmpSegment).Date = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    //8 + Segment, size 320677930
                    //9 |+ Seek head (subentries will be skipped)
                    //10 |+ EbmlVoid (size: 4013)
                    //11 |+ Segment information
                    //12 | + Timecode scale: 1000000
                    //13 | + Muxing application: libebml v1.3.0 + libmatroska v1.4.1
                    //14 | + Writing application: mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00
                    //15 | + Duration: 1364.905s (00:22:44.905)
                    //16 | + Date: Mon Jan 20 21:40:32 2014 UTC
                    //17 | + Segment UID: 0xa3 0x55 0x8d 0x9c 0x25 0x0f 0xba 0x16 0x94 0x09 0xf0 0xc9 0xb4 0x0f 0xc7 0x4b
                    break;

                case MkvInfoParseState.InsideTrackInfo:
                    if (outputLine.Contains("+ A track"))
                    {
                        // if previous segment is not null, add it to the list and create a new one
                        if (tmpSegment != null)
                        {
                            _SegmentList.Add(tmpSegment);
                        }
                        tmpSegment = new gMKVTrack();
                    }
                    else if (outputLine.Contains("Track number:"))
                    {
                        if (outputLine.Contains("track ID for mkvmerge & mkvextract"))
                        {
                            // if we have version 5.x and newer
                            ((gMKVTrack)tmpSegment).TrackNumber = Int32.Parse(outputLine.Substring(outputLine.IndexOf(":") + 1, outputLine.IndexOf("(") - outputLine.IndexOf(":") - 1).Trim());
                            ((gMKVTrack)tmpSegment).TrackID     = Int32.Parse(outputLine.Substring(outputLine.LastIndexOf(":") + 1, outputLine.IndexOf(")") - outputLine.LastIndexOf(":") - 1).Trim());
                        }
                        else
                        {
                            // if we have version 4.x and older
                            ((gMKVTrack)tmpSegment).TrackNumber = Int32.Parse(outputLine.Substring(outputLine.IndexOf(":") + 1).Trim());
                            ((gMKVTrack)tmpSegment).TrackID     = ((gMKVTrack)tmpSegment).TrackNumber;
                        }
                    }
                    else if (outputLine.Contains("Track type:"))
                    {
                        ((gMKVTrack)tmpSegment).TrackType = (MkvTrackType)Enum.Parse(typeof(MkvTrackType), outputLine.Substring(outputLine.IndexOf(":") + 1).Trim());
                    }
                    else if (outputLine.Contains("Codec ID:"))
                    {
                        ((gMKVTrack)tmpSegment).CodecID = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Language:"))
                    {
                        ((gMKVTrack)tmpSegment).Language = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Name:"))
                    {
                        ((gMKVTrack)tmpSegment).TrackName = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Pixel width:"))
                    {
                        ((gMKVTrack)tmpSegment).ExtraInfo = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Pixel height:"))
                    {
                        ((gMKVTrack)tmpSegment).ExtraInfo += "x" + outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Sampling frequency:"))
                    {
                        ((gMKVTrack)tmpSegment).ExtraInfo = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Channels:"))
                    {
                        ((gMKVTrack)tmpSegment).ExtraInfo += ", Ch:" + outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("CodecPrivate,"))
                    {
                        ((gMKVTrack)tmpSegment).CodecPrivate = outputLine.Substring(outputLine.IndexOf(",") + 1).Trim();
                    }

                    //18 |+ Segment tracks
                    //19 | + A track
                    //20 |  + Track number: 1 (track ID for mkvmerge & mkvextract: 0)
                    //21 |  + Track UID: 16103463283017343410
                    //22 |  + Track type: video
                    //23 |  + Lacing flag: 0
                    //24 |  + MinCache: 1
                    //25 |  + Codec ID: V_MPEG4/ISO/AVC
                    //26 |  + CodecPrivate, length 41 (h.264 profile: High @L4.1)
                    //27 |  + Default duration: 41.708ms (23.976 frames/fields per second for a video track)
                    //28 |  + Language: jpn
                    //29 |  + Name: Video
                    //30 |  + Video track
                    //31 |   + Pixel width: 1280
                    //32 |   + Pixel height: 720
                    //33 |   + Display width: 1280
                    //34 |   + Display height: 720
                    //35 | + A track
                    //36 |  + Track number: 2 (track ID for mkvmerge & mkvextract: 1)
                    //37 |  + Track UID: 7691413846401821864
                    //38 |  + Track type: audio
                    //39 |  + Codec ID: A_AAC
                    //40 |  + CodecPrivate, length 5
                    //41 |  + Default duration: 21.333ms (46.875 frames/fields per second for a video track)
                    //42 |  + Language: jpn
                    //43 |  + Name: Audio
                    //44 |  + Audio track
                    //45 |   + Sampling frequency: 48000
                    //46 |   + Channels: 2
                    //47 | + A track
                    //48 |  + Track number: 3 (track ID for mkvmerge & mkvextract: 2)
                    //49 |  + Track UID: 12438050378713133751
                    //50 |  + Track type: subtitles
                    //51 |  + Lacing flag: 0
                    //52 |  + Codec ID: S_TEXT/ASS
                    //53 |  + CodecPrivate, length 1530
                    //54 |  + Language: gre
                    //55 |  + Name: Subs
                    break;

                case MkvInfoParseState.InsideAttachentInfo:
                    if (outputLine.Contains("Attached"))
                    {
                        // if previous segment is not null, add it to the list and create a new one
                        if (tmpSegment != null)
                        {
                            _SegmentList.Add(tmpSegment);
                        }
                        tmpSegment = new gMKVAttachment();
                        ((gMKVAttachment)tmpSegment).ID = attachmentID;
                        attachmentID++;
                    }
                    else if (outputLine.Contains("File name:"))
                    {
                        ((gMKVAttachment)tmpSegment).Filename = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("File data, size:"))
                    {
                        ((gMKVAttachment)tmpSegment).FileSize = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }
                    else if (outputLine.Contains("Mime type:"))
                    {
                        ((gMKVAttachment)tmpSegment).MimeType = outputLine.Substring(outputLine.IndexOf(":") + 1).Trim();
                    }

                    //57 |+ Attachments
                    //58 | + Attached
                    //59 |  + File name: CENSCBK.TTF
                    //60 |  + Mime type: application/x-truetype-font
                    //61 |  + File data, size: 51716
                    //62 |  + File UID: 2140725150727954330
                    //63 | + Attached
                    //64 |  + File name: segoeui.ttf
                    //65 |  + Mime type: application/x-truetype-font
                    //66 |  + File data, size: 516560
                    //67 |  + File UID: 16764867774861384581
                    //68 | + Attached
                    //69 |  + File name: segoeuib.ttf
                    //70 |  + Mime type: application/x-truetype-font
                    //71 |  + File data, size: 497372
                    //72 |  + File UID: 9565689537892410299
                    //73 | + Attached
                    //74 |  + File name: segoeuii.ttf
                    //75 |  + Mime type: application/x-truetype-font
                    //76 |  + File data, size: 385560
                    //77 |  + File UID: 13103126947871579286
                    //78 | + Attached
                    //79 |  + File name: segoeuil.ttf
                    //80 |  + Mime type: application/x-truetype-font
                    //81 |  + File data, size: 330908
                    //82 |  + File UID: 3235680178630447031
                    //83 | + Attached
                    //84 |  + File name: segoeuiz.ttf
                    //85 |  + Mime type: application/x-truetype-font
                    //86 |  + File data, size: 398148
                    //87 |  + File UID: 17520358819351445890
                    //88 | + Attached
                    //89 |  + File name: seguisb.ttf
                    //90 |  + Mime type: application/x-truetype-font
                    //91 |  + File data, size: 406192
                    //92 |  + File UID: 8550836732450669472

                    break;

                case MkvInfoParseState.InsideChapterInfo:
                    if (outputLine.Contains("EditionEntry"))
                    {
                        // if previous segment is not null, add it to the list and create a new one
                        if (tmpSegment != null)
                        {
                            _SegmentList.Add(tmpSegment);
                        }
                        tmpSegment = new gMKVChapter();
                    }
                    else if (outputLine.Contains("ChapterAtom"))
                    {
                        ((gMKVChapter)tmpSegment).ChapterCount += 1;
                    }

                    //93 |+ Chapters
                    //94 | + EditionEntry
                    //95 |  + EditionFlagHidden: 0
                    //96 |  + EditionFlagDefault: 0
                    //97 |  + EditionUID: 5248481698181523363
                    //98 |  + ChapterAtom
                    //99 |   + ChapterUID: 13651813039521317265
                    //100 |   + ChapterTimeStart: 00:00:00.000000000
                    //101 |   + ChapterTimeEnd: 00:00:40.874000000
                    //102 |   + ChapterFlagHidden: 0
                    //103 |   + ChapterFlagEnabled: 1
                    //104 |   + ChapterDisplay
                    //105 |    + ChapterString: ��������
                    //106 |    + ChapterLanguage: und
                    //107 |  + ChapterAtom
                    //108 |   + ChapterUID: 9861180919652459706
                    //109 |   + ChapterTimeStart: 00:00:40.999000000
                    //110 |   + ChapterTimeEnd: 00:02:00.829000000
                    //111 |   + ChapterFlagHidden: 0
                    //112 |   + ChapterFlagEnabled: 1
                    //113 |   + ChapterDisplay
                    //114 |    + ChapterString: ������ �����
                    //115 |    + ChapterLanguage: und
                    //116 |  + ChapterAtom
                    //117 |   + ChapterUID: 18185444543032186557
                    //118 |   + ChapterTimeStart: 00:02:00.954000000
                    //119 |   + ChapterTimeEnd: 00:21:24.700000000
                    //120 |   + ChapterFlagHidden: 0
                    //121 |   + ChapterFlagEnabled: 1
                    //122 |   + ChapterDisplay
                    //123 |    + ChapterString: ������ �����
                    //124 |    + ChapterLanguage: und
                    //125 |  + ChapterAtom
                    //126 |   + ChapterUID: 12481834811641996944
                    //127 |   + ChapterTimeStart: 00:21:24.867000000
                    //128 |   + ChapterTimeEnd: 00:22:44.864000000
                    //129 |   + ChapterFlagHidden: 0
                    //130 |   + ChapterFlagEnabled: 1
                    //131 |   + ChapterDisplay
                    //132 |    + ChapterString: ������ ������
                    //133 |    + ChapterLanguage: und

                    break;

                default:
                    break;
                }
            }
            // if the last segment was not added to the list and it is not null, add it to the list
            if (tmpSegment != null)
            {
                _SegmentList.Add(tmpSegment);
            }
        }