o Improved IMSC-1 profile detection. May not yet be perfect, experimentation
authorjhurst <jhurst@cinecert.com>
Wed, 7 Dec 2016 18:11:32 +0000 (18:11 +0000)
committerjhurst <>
Wed, 7 Dec 2016 18:11:32 +0000 (18:11 +0000)
   encouraged!
 o Refactored XML element & attribute visitation to KM_xml.h
 o Added km_join() template to KM_util.h

src/KM_util.h
src/KM_xml.h
src/ST2052_TextParser.cpp

index 4834891a3499e17a248e2d43726b2104f475a3ec..e8004c151ac91f9080ebcda1f5109050a2b823ac 100755 (executable)
@@ -543,6 +543,27 @@ namespace Kumu
   // adjacent instances of the separator. E.g., "/foo//bar/" will return ["", "foo", "", "bar", ""].
   std::list<std::string> km_token_split(const std::string& str, const std::string& separator);
 
+  // Join the tokens in the given list using delimiter. If prefix is defined then each token
+  // will be concatenated with the prefix before being added to the composite string.
+  template <class T>
+    std::string
+    km_join(const T& list, const std::string& delimiter, const std::string& prefix = "")
+    {
+      std::string result;
+
+      for ( typename T::const_iterator i = list.begin(); i != list.end(); ++i )
+       {
+         if ( i != list.begin() )
+           {
+             result += delimiter;
+           }
+      
+         result += prefix + *i;
+       }
+
+      return result;
+    }
+
 } // namespace Kumu
 
 
index 0c84e563c17035f098c4f96dc6b5a6896e83c187..120857c53f8d05cff4cc2fbbe948402ff2d495be 100644 (file)
@@ -35,6 +35,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <KM_util.h>
 #include <list>
+#include <set>
 #include <string>
 
 namespace Kumu
@@ -143,6 +144,77 @@ namespace Kumu
       void        DeleteChild(const XMLElement* element);
       void        ForgetChild(const XMLElement* element);
     };
+
+  //
+  template <class VisitorType>
+    bool
+    apply_visitor(const XMLElement& element, VisitorType& visitor)
+    {
+      const ElementList& l = element.GetChildren();
+      ElementList::const_iterator i;
+      
+      for ( i = l.begin(); i != l.end(); ++i )
+       {
+         if ( ! visitor.Element(**i) )
+           {
+             return false;
+           }
+
+         if ( ! apply_visitor(**i, visitor) )
+           {
+             return false;
+           }
+       }
+
+      return true;
+    }
+
+  //
+  class AttributeVisitor
+  {
+    std::string attr_name;
+
+  public:
+  AttributeVisitor(const std::string& n) : attr_name(n) {}
+    std::set<std::string> value_list;
+
+    bool Element(const XMLElement& e)
+    {
+      const AttributeList& l = e.GetAttributes();
+      AttributeList::const_iterator i;
+      for ( i = l.begin(); i != l.end(); ++i )
+       {
+         if ( i->name == attr_name )
+           {
+             value_list.insert(i->value);
+           }
+       }
+
+      return true;
+    }
+  };
+
+  //
+  class ElementVisitor
+  {
+    std::string element_name;
+
+  public:
+  ElementVisitor(const std::string& n) : element_name(n) {}
+    std::set<std::string> value_list;
+
+    bool Element(const XMLElement& e)
+    {
+      if ( e.GetBody() == element_name )
+       {
+         value_list.insert(e.GetBody());
+       }
+
+      return true;
+    }
+  };
+
 } // namespace Kumu
 
 #endif // _KM_XML_H_
index f291a1b213c49f7d285bfbddcf030bb10d1b8719..a98b4cabb03446b0e16d433aac418a44d0769e31 100644 (file)
@@ -290,55 +290,10 @@ AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead(const std::string&
   return OpenRead(profile_name);
 }
 
-//
-template <class VisitorType>
-bool
-apply_visitor(const XMLElement& element, VisitorType& visitor)
-{
-  const ElementList& l = element.GetChildren();
-  ElementList::const_iterator i;
-
-  for ( i = l.begin(); i != l.end(); ++i )
-    {
-      if ( ! visitor.Element(**i) )
-       {
-         return false;
-       }
-
-      if ( ! apply_visitor(**i, visitor) )
-       {
-         return false;
-       }
-    }
-
-  return true;
-}
 
-//
-class AttributeVisitor
-{
-  std::string attr_name;
-
-public:
-  AttributeVisitor(const std::string& n) : attr_name(n) {}
-  std::set<std::string> value_list;
-
-  bool Element(const XMLElement& e)
-  {
-    const AttributeList& l = e.GetAttributes();
-    AttributeList::const_iterator i;
-    for ( i = l.begin(); i != l.end(); ++i )
-      {
-       if ( i->name == attr_name )
-         {
-           value_list.insert(i->value);
-         }
-      }
 
-    return true;
-  }
-};
+std::string const IMSC1_imageProfile = "http://www.w3.org/ns/ttml/profile/imsc1/image";
+std::string const IMSC1_textProfile = "http://www.w3.org/ns/ttml/profile/imsc1/text";
 
 //
 Result_t
@@ -355,11 +310,45 @@ AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead(const std::string&
   m_TDesc.EncodingName = "UTF-8"; // the XML parser demands UTF-8
   m_TDesc.ResourceList.clear();
   m_TDesc.ContainerDuration = 0;
-  m_TDesc.NamespaceName = profile_name;
+  m_TDesc.NamespaceName = profile_name; // set the profile explicitly
+  std::set<std::string>::const_iterator i;
+
+  // Attempt to set the profile from <conformsToStandard>
+  if ( m_TDesc.NamespaceName.empty() )
+    {
+      ElementVisitor conforms_visitor("conformsToStandard");
+      apply_visitor(m_Root, conforms_visitor);
+
+      for ( i = conforms_visitor.value_list.begin(); i != conforms_visitor.value_list.end(); ++i )
+       {
+         if ( *i == IMSC1_imageProfile || *i == IMSC1_textProfile )
+           {
+             m_TDesc.NamespaceName = *i;
+             break;
+           }
+       }
+    }
+
+  // Attempt to set the profile from the use of attribute "profile"
+  if ( m_TDesc.NamespaceName.empty() )
+    {
+      AttributeVisitor profile_visitor("profile");
+      apply_visitor(m_Root, profile_visitor);
+
+      for ( i = profile_visitor.value_list.begin(); i != profile_visitor.value_list.end(); ++i )
+       {
+         if ( *i == IMSC1_imageProfile || *i == IMSC1_textProfile )
+           {
+             m_TDesc.NamespaceName = *i;
+             break;
+           }
+       }
+    }
 
+  // Find image resources for later packaging as GS partitions.
+  // Attempt to set the profile; infer from use of images.
   AttributeVisitor png_visitor("backgroundImage");
   apply_visitor(m_Root, png_visitor);
-  std::set<std::string>::const_iterator i;
 
   for ( i = png_visitor.value_list.begin(); i != png_visitor.value_list.end(); ++i )
     {
@@ -370,8 +359,27 @@ AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead(const std::string&
       m_TDesc.ResourceList.push_back(png_resource);
       m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(png_resource.ResourceID),
                                                           ASDCP::TimedText::MT_PNG));
+
+      if ( m_TDesc.NamespaceName.empty() )
+       {
+         m_TDesc.NamespaceName = IMSC1_imageProfile;
+       }
+    }
+
+  // If images are present and profile is "text" make sure to say something.
+  if ( ! m_ResourceTypes.empty() && m_TDesc.NamespaceName == IMSC1_textProfile )
+    {
+      DefaultLogSink().Warn("Unexpected IMSC-1 text profile; document contains images.\n ");
+    }
+  
+  // If all else fails set the profile to "text".
+  if ( m_TDesc.NamespaceName.empty() )
+    {
+      DefaultLogSink().Warn("Using default IMSC-1 text profile.\n ");
+      m_TDesc.NamespaceName = IMSC1_textProfile;
     }
 
+  // Find font resources for later packaging as GS partitions.
   AttributeVisitor font_visitor("fontFamily");
   apply_visitor(m_Root, font_visitor);
   char buf[64];