public static ReadAllStreams ( String filename ) : List |
||
filename | String | |
리턴 | List |
public static List<StreamInfo> ReadAllStreams(String filename) {
// use ffprobe/avprobe(?) to get nice XML-description of contents
String stdout = UtilsCommon.StartProcessAndGetOutput(InstanceSettings.systemSettings.formatProberCommand, @"-v quiet -print_format xml -show_streams """ + filename + @"""");
List<StreamInfo> allStreamInfos = new List<StreamInfo> ();
StreamInfo lastStreamInfo = null;
// use XmlReader to read all informations from "stream"-tags and "tag"-tags
using (XmlReader reader = XmlReader.Create(new StringReader (stdout))) {
while (reader.Read ()) {
if (reader.NodeType != XmlNodeType.Element)
continue;
// the "stream"-tag contains most of the information needed as attributes
if (reader.Name == "stream") {
// get stream type
StreamType streamType;
switch(reader["codec_type"]) {
case "video": streamType = StreamType.ST_VIDEO; break;
case "audio": streamType = StreamType.ST_AUDIO; break;
case "subtitle": streamType = StreamType.ST_SUBTITLE; break;
default: streamType = StreamType.ST_UNKNOWN; break;
}
// read all other information into dictionary
var attributeDictionary = new Dictionary<String, String>();
for(int i = 0; i < reader.AttributeCount; i++) {
reader.MoveToNextAttribute();
attributeDictionary.Add(reader.Name, reader.Value);
}
StreamInfo streamInfo = new StreamInfo (Int32.Parse(reader["index"]), streamType, reader["codec_name"], attributeDictionary);
allStreamInfos.Add (streamInfo);
lastStreamInfo = streamInfo;
}
// the "tag"-tag provides additonal information (mainly language)
if (reader.Name == "tag") {
if (lastStreamInfo == null)
continue;
switch (reader ["key"]) {
case "language":
lastStreamInfo.m_language = reader ["value"] ?? "";
break;
default:
break;
}
}
}
}
return allStreamInfos;
}
}
/// <summary> /// This function searches a container file by streamType. Let's say you want to extract an audio stream from /// a file with two audio streams. To identify the right one, the key "stream" is searched in "properties". The /// value for this key should be an index (this index refers to an entry of an array created by "StreamInfo.ReadAllStreams()", /// but not to the actual in-file stream for ffmpeg). /// /// In case there is no property given, the first stream of this type is selected (in array from "StreamInfo.ReadAllStreams()"). /// /// </summary> /// <returns>The stream info describing the requested stream</returns> /// <param name="filename">Filename.</param> /// <param name="properties">Properties.</param> /// <param name="streamType">Stream type.</param> public static StreamInfo ChooseStreamInfo(String filename, Dictionary <String, String> properties, StreamInfo.StreamType streamType) { List <StreamInfo> allStreams = StreamInfo.ReadAllStreams(filename); // find first stream of given type in file (after that we also know whether the file has any of these streams) int firstSuitableStream = -1; for (int i = 0; i < allStreams.Count; i++) { if (allStreams [i].StreamTypeValue == streamType) { firstSuitableStream = i; break; } } if (firstSuitableStream == -1) { throw new Exception("Container file \"" + filename + "\" does not contain any " + streamType.GetPlainString() + " streams"); } int streamIndex = 0; String streamIndexDictionaryString = ""; if (properties.TryGetValue("stream", out streamIndexDictionaryString)) { try { streamIndex = Int32.Parse(streamIndexDictionaryString); } catch (Exception) { throw new Exception("Stream property is not an integer."); } if (streamIndex < 0 || streamIndex >= allStreams.Count || allStreams [streamIndex].StreamTypeValue != streamType) { throw new Exception("Stream with index " + streamIndex + " is not a " + streamType.GetPlainString() + " stream (but stream at index " + firstSuitableStream + " is)."); } } else { streamIndex = firstSuitableStream; } return(allStreams [streamIndex]); }