aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2016-02-25 01:21:40 -0500
committerLuke <luke.pulverenti@gmail.com>2016-02-25 01:21:40 -0500
commitf55d6ded74c8c5589d590141d8b0df9c81c125b2 (patch)
tree3a79a5fb255016b2e39446b1749d73567e43242c /MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
parentc2e75e99f406f16b6b66223484ceb08deaf2ef13 (diff)
parent06421248de0d91ef1b30b23ea2da36e4df93aa9a (diff)
Merge pull request #1497 from MediaBrowser/dev
Dev
Diffstat (limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs')
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs256
1 files changed, 243 insertions, 13 deletions
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 7936a824a..57c2f75cc 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -7,7 +7,10 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text;
+using System.Xml;
using CommonIO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
@@ -81,12 +84,29 @@ namespace MediaBrowser.MediaEncoding.Probing
}
FetchGenres(info, tags);
- var overview = FFProbeHelpers.GetDictionaryValue(tags, "description");
+ var shortOverview = FFProbeHelpers.GetDictionaryValue(tags, "description");
+ var overview = FFProbeHelpers.GetDictionaryValue(tags, "synopsis");
+
+ if (string.IsNullOrWhiteSpace(overview))
+ {
+ overview = shortOverview;
+ shortOverview = null;
+ }
+ if (string.IsNullOrWhiteSpace(overview))
+ {
+ overview = FFProbeHelpers.GetDictionaryValue(tags, "desc");
+ }
+
if (!string.IsNullOrWhiteSpace(overview))
{
info.Overview = overview;
}
+ if (!string.IsNullOrWhiteSpace(shortOverview))
+ {
+ info.ShortOverview = shortOverview;
+ }
+
var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
if (!string.IsNullOrWhiteSpace(title))
{
@@ -105,13 +125,15 @@ namespace MediaBrowser.MediaEncoding.Probing
{
SetAudioRuntimeTicks(data, info);
- // tags are normally located under data.format, but we've seen some cases with ogg where they're part of the audio stream
+ // tags are normally located under data.format, but we've seen some cases with ogg where they're part of the info stream
// so let's create a combined list of both
SetAudioInfoFromTags(info, tags);
}
else
{
+ FetchStudios(info, tags, "copyright");
+
var iTunEXTC = FFProbeHelpers.GetDictionaryValue(tags, "iTunEXTC");
if (!string.IsNullOrWhiteSpace(iTunEXTC))
{
@@ -124,13 +146,13 @@ namespace MediaBrowser.MediaEncoding.Probing
info.OfficialRatingDescription = parts[3];
}
}
-
+
var itunesXml = FFProbeHelpers.GetDictionaryValue(tags, "iTunMOVI");
if (!string.IsNullOrWhiteSpace(itunesXml))
{
FetchFromItunesInfo(itunesXml, info);
}
-
+
if (data.format != null && !string.IsNullOrEmpty(data.format.duration))
{
info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
@@ -151,13 +173,221 @@ namespace MediaBrowser.MediaEncoding.Probing
private void FetchFromItunesInfo(string xml, MediaInfo info)
{
+ // Make things simpler and strip out the dtd
+ xml = xml.Substring(xml.IndexOf("<plist", StringComparison.OrdinalIgnoreCase));
+ xml = "<?xml version=\"1.0\"?>" + xml;
+
// <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>cast</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Blender Foundation</string>\n\t\t</dict>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Janus Bager Kristensen</string>\n\t\t</dict>\n\t</array>\n\t<key>directors</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>name</key>\n\t\t\t<string>Sacha Goedegebure</string>\n\t\t</dict>\n\t</array>\n\t<key>studio</key>\n\t<string>Blender Foundation</string>\n</dict>\n</plist>\n
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
+ {
+ using (var streamReader = new StreamReader(stream))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader))
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "dict":
+ using (var subtree = reader.ReadSubtree())
+ {
+ ReadFromDictNode(subtree, info);
+ }
+ break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void ReadFromDictNode(XmlReader reader, MediaInfo info)
+ {
+ reader.MoveToContent();
+
+ string currentKey = null;
+ List<NameValuePair> pairs = new List<NameValuePair>();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "key":
+ if (!string.IsNullOrWhiteSpace(currentKey))
+ {
+ ProcessPairs(currentKey, pairs, info);
+ }
+ currentKey = reader.ReadElementContentAsString();
+ pairs = new List<NameValuePair>();
+ break;
+ case "string":
+ var value = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ pairs.Add(new NameValuePair
+ {
+ Name = value,
+ Value = value
+ });
+ }
+ break;
+ case "array":
+ if (!string.IsNullOrWhiteSpace(currentKey))
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ pairs.AddRange(ReadValueArray(subtree));
+ }
+ }
+ break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
+ private List<NameValuePair> ReadValueArray(XmlReader reader)
+ {
+ reader.MoveToContent();
+
+ List<NameValuePair> pairs = new List<NameValuePair>();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "dict":
+ using (var subtree = reader.ReadSubtree())
+ {
+ var dict = GetNameValuePair(subtree);
+ if (dict != null)
+ {
+ pairs.Add(dict);
+ }
+ }
+ break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+
+ return pairs;
+ }
+
+ private void ProcessPairs(string key, List<NameValuePair> pairs, MediaInfo info)
+ {
+ if (string.Equals(key, "studio", StringComparison.OrdinalIgnoreCase))
+ {
+ foreach (var pair in pairs)
+ {
+ info.Studios.Add(pair.Value);
+ }
+
+ info.Studios = info.Studios
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ }
+ else if (string.Equals(key, "screenwriters", StringComparison.OrdinalIgnoreCase))
+ {
+ foreach (var pair in pairs)
+ {
+ info.People.Add(new BaseItemPerson
+ {
+ Name = pair.Value,
+ Type = PersonType.Writer
+ });
+ }
+ }
+ else if (string.Equals(key, "producers", StringComparison.OrdinalIgnoreCase))
+ {
+ foreach (var pair in pairs)
+ {
+ info.People.Add(new BaseItemPerson
+ {
+ Name = pair.Value,
+ Type = PersonType.Producer
+ });
+ }
+ }
+ else if (string.Equals(key, "directors", StringComparison.OrdinalIgnoreCase))
+ {
+ foreach (var pair in pairs)
+ {
+ info.People.Add(new BaseItemPerson
+ {
+ Name = pair.Value,
+ Type = PersonType.Director
+ });
+ }
+ }
+ }
+
+ private NameValuePair GetNameValuePair(XmlReader reader)
+ {
+ reader.MoveToContent();
+
+ string name = null;
+ string value = null;
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "key":
+ name = reader.ReadElementContentAsString();
+ break;
+ case "string":
+ value = reader.ReadElementContentAsString();
+ break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(name) ||
+ string.IsNullOrWhiteSpace(value))
+ {
+ return null;
+ }
+
+ return new NameValuePair
+ {
+ Name = name,
+ Value = value
+ };
}
/// <summary>
/// Converts ffprobe stream info to our MediaStream class
/// </summary>
- /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
+ /// <param name="isAudio">if set to <c>true</c> [is info].</param>
/// <param name="streamInfo">The stream info.</param>
/// <param name="formatInfo">The format info.</param>
/// <returns>MediaStream.</returns>
@@ -434,11 +664,11 @@ namespace MediaBrowser.MediaEncoding.Probing
return null;
}
- private void SetAudioRuntimeTicks(InternalMediaInfoResult result, Model.MediaInfo.MediaInfo data)
+ private void SetAudioRuntimeTicks(InternalMediaInfoResult result, MediaInfo data)
{
if (result.streams != null)
{
- // Get the first audio stream
+ // Get the first info stream
var stream = result.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
if (stream != null)
@@ -703,10 +933,10 @@ namespace MediaBrowser.MediaEncoding.Probing
/// <summary>
/// Gets the studios from the tags collection
/// </summary>
- /// <param name="audio">The audio.</param>
+ /// <param name="info">The info.</param>
/// <param name="tags">The tags.</param>
/// <param name="tagName">Name of the tag.</param>
- private void FetchStudios(Model.MediaInfo.MediaInfo audio, Dictionary<string, string> tags, string tagName)
+ private void FetchStudios(MediaInfo info, Dictionary<string, string> tags, string tagName)
{
var val = FFProbeHelpers.GetDictionaryValue(tags, tagName);
@@ -717,19 +947,19 @@ namespace MediaBrowser.MediaEncoding.Probing
foreach (var studio in studios)
{
// Sometimes the artist name is listed here, account for that
- if (audio.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase))
+ if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase))
{
continue;
}
- if (audio.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase))
+ if (info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase))
{
continue;
}
- audio.Studios.Add(studio);
+ info.Studios.Add(studio);
}
- audio.Studios = audio.Studios
+ info.Studios = info.Studios
.Where(i => !string.IsNullOrWhiteSpace(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();