public static Func <IList <IFormat>, IList <IFormat> > BuildSelectorFunction(FormatSelector selector, string mergeOutputFormat = null) { Func <IList <IFormat>, IList <IFormat> > selector_func = null; switch (selector.Type) { case FormatType.Group: selector_func = BuildSelectorFunction((IList <FormatSelector>)selector.Selector, mergeOutputFormat); break; case FormatType.Pickfirst: var fs = (selector.Selector as List <FormatSelector>).Select(s => BuildSelectorFunction(s, mergeOutputFormat)); selector_func = new Func <IList <IFormat>, IList <IFormat> >(delegate(IList <IFormat> ctx) { foreach (var f in fs) { var picked_formats = f(ctx); if (picked_formats != null) { return(picked_formats); } } return(new List <IFormat>()); }); break; case FormatType.Single: string format_spec = (string)selector.Selector; selector_func = new Func <IList <IFormat>, IList <IFormat> >(delegate(IList <IFormat> formats) { if (formats == null) { return(new List <IFormat>()); } List <IFormat> rformats = new List <IFormat>(); switch (format_spec) { case "all": return(formats); case "best": case null: var best = formats.LastOrDefault(f => f is IMuxedFormat); if (best == default) { return(null); } else { return new List <IFormat>() { best } }; case "worst": var worst = formats.FirstOrDefault(f => f is IMuxedFormat); if (worst == default) { return(null); } else { return new List <IFormat>() { worst } }; case "bestaudio": var bestaudio = formats.LastOrDefault(f => f is IAudioFormat && !(f is IVideoFormat)); if (bestaudio == default) { return(null); } else { return new List <IFormat>() { bestaudio } }; case "worstaudio": var worstaudio = formats.FirstOrDefault(f => f is IAudioFormat && !(f is IVideoFormat)); if (worstaudio == default) { return(null); } else { return new List <IFormat>() { worstaudio } }; case "bestvideo": var bestvideo = formats.LastOrDefault(f => f is IVideoFormat && !(f is IAudioFormat)); if (bestvideo == default) { return(null); } else { return new List <IFormat>() { bestvideo } }; case "worstvideo": var worstvideo = formats.FirstOrDefault(f => f is IVideoFormat && !(f is IAudioFormat)); if (worstvideo == default) { return(null); } else { return new List <IFormat>() { worstvideo } }; default: Func <IFormat, bool> filter_f = null; var extensions = new List <string> { "mp4", "flv", "webm", "3gp", "m4a", "mp3", "ogg", "aac", "wav" }; if (extensions.Contains(format_spec)) { filter_f = f => f.Extension == format_spec; } else { filter_f = f => f.Id == format_spec; } var matches = formats.Where(filter_f); if (matches != null && matches.Count() >= 1) { return new List <IFormat> { matches.Last() } } ; break; } return(new List <IFormat>()); }); break;
public static IList <FormatSelector> ParseFormatSelection(string[] tokens, ref int index, bool inMerge = false, bool inPickfirst = false, bool inGroup = false) { List <FormatSelector> selectors = new List <FormatSelector>(); FormatSelector current = null; for (index++; index < tokens.Length; index++) { if (tokens[index] == @")") { if (!inGroup) { index--; } break; } else if (inMerge && (tokens[index] == @"/" || tokens[index] == @",")) { index--; break; } else if (inPickfirst && tokens[index] == @",") { index--; break; } else if (tokens[index] == @",") { if (current == null) { throw new Exception("\",\" must follow a format selector"); } selectors.Add(current); current = null; } else if (tokens[index] == @"/") { if (current == null) { throw new Exception("\"\\\" must follow a format selector"); } var first_choice = current; var second_choice = ParseFormatSelection(tokens, ref index, inPickfirst = true); current = new FormatSelector(FormatType.Pickfirst, (first_choice, second_choice)); } else if (tokens[index] == @"[") { if (current == null) { current = new FormatSelector(FormatType.Single, "best"); } var filter = ParseFormatFilter(tokens, ref index); current.Filter.Add(filter); } else if (tokens[index] == @"(") { if (current != null) { throw new Exception("Unexpected \"(\""); } var group = ParseFormatSelection(tokens, ref index, inGroup = true); current = new FormatSelector(FormatType.Group, group); } else if (tokens[index] == @"+") { var video_selector = current; var audio_selector = ParseFormatSelection(tokens, ref index, inMerge = true).Single(); if (video_selector == null || audio_selector == null) { throw new Exception("\"+\" must be between two format selectors"); } current = new FormatSelector(FormatType.Merge, (video_selector, audio_selector)); } else { current = new FormatSelector(FormatType.Single, tokens[index]); //throw new Exception("Operator not recognized: \"" + tokens[index] + "\""); } } if (current != null) { selectors.Add(current); } return(selectors); }