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); } }
private List <TrackParameter> GetTrackParameters(gMKVSegment argSeg, String argMKVFile, String argOutputDirectory, MkvChapterTypes argChapterType, TimecodesExtractionMode argTimecodesExtractionMode, CuesExtractionMode argCueExtractionMode) { // create the new parameter list type List <TrackParameter> trackParameterList = new List <TrackParameter>(); // check the selected segment's type if (argSeg is gMKVTrack) { // if we are in a mode that requires timecodes extraction, add the parameter for the track if (argTimecodesExtractionMode != TimecodesExtractionMode.NoTimecodes) { trackParameterList.Add(new TrackParameter( MkvExtractModes.timecodes_v2, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}.tc.txt", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language))), false, String.Empty )); } // if we are in a mode that requires cues extraction, add the parameter for the track if (argCueExtractionMode != CuesExtractionMode.NoCues) { trackParameterList.Add(new TrackParameter( MkvExtractModes.cues, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}.cue", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language))), false, String.Empty )); } // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { String outputFileExtension = String.Empty; String outputDelayPart = String.Empty; // check the track's type in order to get the output file's extension and the delay for audio tracks switch (((gMKVTrack)argSeg).TrackType) { case MkvTrackType.video: // get the extension of the output via the CODEC_ID of the track outputFileExtension = getVideoFileExtensionFromCodecID((gMKVTrack)argSeg); break; case MkvTrackType.audio: // add the delay to the extraOutput for the track filename outputDelayPart = String.Format("_DELAY {0}ms", ((gMKVTrack)argSeg).EffectiveDelay.ToString(CultureInfo.InvariantCulture)); // get the extension of the output via the CODEC_ID of the track outputFileExtension = getAudioFileExtensionFromCodecID((gMKVTrack)argSeg); break; case MkvTrackType.subtitles: // get the extension of the output via the CODEC_ID of the track outputFileExtension = getSubtitleFileExtensionFromCodecID((gMKVTrack)argSeg); break; default: break; } // add the parameter for extracting the track trackParameterList.Add(new TrackParameter( MkvExtractModes.tracks, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}{3}.{4}", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language, outputDelayPart, outputFileExtension))), false, String.Empty )); } } else if (argSeg is gMKVAttachment) { // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { // add the parameter for extracting the attachment trackParameterList.Add(new TrackParameter( MkvExtractModes.attachments, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVAttachment)argSeg).ID, Path.Combine( argOutputDirectory, ((gMKVAttachment)argSeg).Filename)), false, String.Empty )); } } else if (argSeg is gMKVChapter) { // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { String outputFileExtension = String.Empty; String options = String.Empty; // check the chapter's type to determine the output file's extension and options switch (argChapterType) { case MkvChapterTypes.XML: outputFileExtension = "xml"; break; case MkvChapterTypes.OGM: outputFileExtension = "ogm.txt"; options = "--simple"; break; case MkvChapterTypes.CUE: outputFileExtension = "cue"; break; default: break; } // add the parameter for extracting the chapters trackParameterList.Add(new TrackParameter( MkvExtractModes.chapters, options, String.Empty, true, Path.Combine( argOutputDirectory, String.Format("{0}_chapters.{1}", Path.GetFileNameWithoutExtension(argMKVFile), outputFileExtension)) )); } } return(trackParameterList); }