diff --git a/generated/org/smpte_ra/schemas/st2067_21_2016/ObjectFactory.java b/generated/org/smpte_ra/schemas/st2067_21_2016/ObjectFactory.java
new file mode 100644
index 00000000..b37f02d9
--- /dev/null
+++ b/generated/org/smpte_ra/schemas/st2067_21_2016/ObjectFactory.java
@@ -0,0 +1,62 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
+// See http://java.sun.com/xml/jaxb
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2020.07.12 at 09:01:40 PM PDT
+//
+
+
+package org.smpte_ra.schemas.st2067_21_2016;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.smpte_ra.schemas.st2067_21_2016 package.
+ *
An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _MaxCLL_QNAME = new QName("http://www.smpte-ra.org/schemas/2067-21/2016", "MaxCLL");
+ private final static QName _MaxFALL_QNAME = new QName("http://www.smpte-ra.org/schemas/2067-21/2016", "MaxFALL");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.smpte_ra.schemas.st2067_21_2016
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Integer }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.smpte-ra.org/schemas/2067-21/2016", name = "MaxCLL")
+ public JAXBElement createMaxCLL(Integer value) {
+ return new JAXBElement(_MaxCLL_QNAME, Integer.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Integer }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.smpte-ra.org/schemas/2067-21/2016", name = "MaxFALL")
+ public JAXBElement createMaxFALL(Integer value) {
+ return new JAXBElement(_MaxFALL_QNAME, Integer.class, null, value);
+ }
+
+}
diff --git a/generated/org/smpte_ra/schemas/st2067_2_2020/CDPSequence.java b/generated/org/smpte_ra/schemas/st2067_2_2020/CDPSequence.java
new file mode 100644
index 00000000..1353bbb5
--- /dev/null
+++ b/generated/org/smpte_ra/schemas/st2067_2_2020/CDPSequence.java
@@ -0,0 +1,76 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
+// See http://java.sun.com/xml/jaxb
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2020.07.12 at 07:25:26 PM PDT
+//
+
+
+package org.smpte_ra.schemas.st2067_2_2020;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import org.smpte_ra.schemas.st2067_2_2016.SequenceType;
+
+
+/**
+ *
Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "StereoImageTrackFileResourceType", propOrder = {
+ "leftEye",
+ "rightEye"
+})
+public class StereoImageTrackFileResourceType
+ extends BaseResourceType
+{
+
+ @XmlElement(name = "LeftEye", required = true)
+ protected TrackFileResourceType leftEye;
+ @XmlElement(name = "RightEye", required = true)
+ protected TrackFileResourceType rightEye;
+
+ /**
+ * Gets the value of the leftEye property.
+ *
+ * @return
+ * possible object is
+ * {@link TrackFileResourceType }
+ *
+ */
+ public TrackFileResourceType getLeftEye() {
+ return leftEye;
+ }
+
+ /**
+ * Sets the value of the leftEye property.
+ *
+ * @param value
+ * allowed object is
+ * {@link TrackFileResourceType }
+ *
+ */
+ public void setLeftEye(TrackFileResourceType value) {
+ this.leftEye = value;
+ }
+
+ /**
+ * Gets the value of the rightEye property.
+ *
+ * @return
+ * possible object is
+ * {@link TrackFileResourceType }
+ *
+ */
+ public TrackFileResourceType getRightEye() {
+ return rightEye;
+ }
+
+ /**
+ * Sets the value of the rightEye property.
+ *
+ * @param value
+ * allowed object is
+ * {@link TrackFileResourceType }
+ *
+ */
+ public void setRightEye(TrackFileResourceType value) {
+ this.rightEye = value;
+ }
+
+}
diff --git a/generated/org/smpte_ra/schemas/st2067_2_2020/package-info.java b/generated/org/smpte_ra/schemas/st2067_2_2020/package-info.java
new file mode 100644
index 00000000..105736dc
--- /dev/null
+++ b/generated/org/smpte_ra/schemas/st2067_2_2020/package-info.java
@@ -0,0 +1,9 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802
+// See http://java.sun.com/xml/jaxb
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2020.07.12 at 07:25:26 PM PDT
+//
+
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.smpte-ra.org/ns/2067-2/2020", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.smpte_ra.schemas.st2067_2_2020;
diff --git a/src/main/java/com/netflix/imflibrary/app/IMPFixer.java b/src/main/java/com/netflix/imflibrary/app/IMPFixer.java
index 75009cfa..1fb30fc5 100755
--- a/src/main/java/com/netflix/imflibrary/app/IMPFixer.java
+++ b/src/main/java/com/netflix/imflibrary/app/IMPFixer.java
@@ -17,6 +17,7 @@
import com.netflix.imflibrary.st0429_9.BasicMapProfileV2MappedFileSet;
import com.netflix.imflibrary.st2067_2.ApplicationComposition;
import com.netflix.imflibrary.st2067_2.ApplicationCompositionFactory;
+import com.netflix.imflibrary.st2067_2.CoreConstraints;
import com.netflix.imflibrary.st2067_2.IMFEssenceComponentVirtualTrack;
import com.netflix.imflibrary.utils.*;
import com.netflix.imflibrary.writerTools.CompositionPlaylistBuilder_2016;
@@ -228,16 +229,18 @@ public static List analyzePackageAndWrite(File rootFile
Set trackFileIDsSet = trackFileIDToHeaderPartitionPayLoadMap.keySet();
if(versionCPLSchema.equals(""))
{
- if (applicationComposition.getCoreConstraintsVersion().contains("st2067_2_2013")) {
+ String coreConstraintsSchema = applicationComposition.getCoreConstraintsSchema();
+ if (coreConstraintsSchema.equals(CoreConstraints.NAMESPACE_IMF_2013)) {
versionCPLSchema = "2013";
}
- else if (applicationComposition.getCoreConstraintsVersion().contains("st2067_2_2016")) {
+ else if (coreConstraintsSchema.equals(CoreConstraints.NAMESPACE_IMF_2016)
+ || coreConstraintsSchema.equals(CoreConstraints.NAMESPACE_IMF_2020)) {
versionCPLSchema = "2016";
}
else {
imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CORE_CONSTRAINTS_ERROR,
IMFErrorLogger.IMFErrors.ErrorLevels.FATAL,
- String.format("Input package CoreConstraintsVersion %s not supported", applicationComposition.getCoreConstraintsVersion().toString()));
+ String.format("Input package CoreConstraints Schema %s not supported", applicationComposition.getCoreConstraintsSchema()));
}
}
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/AbstractApplicationComposition.java b/src/main/java/com/netflix/imflibrary/st2067_2/AbstractApplicationComposition.java
index 68ed1913..812dee78 100644
--- a/src/main/java/com/netflix/imflibrary/st2067_2/AbstractApplicationComposition.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/AbstractApplicationComposition.java
@@ -84,7 +84,7 @@ public abstract class AbstractApplicationComposition implements ApplicationCompo
- private final String coreConstraintsVersion;
+ private final String coreConstraintsSchema;
private final Map virtualTrackMap;
private final IMFCompositionPlaylistType compositionPlaylistType;
private final Map> essenceDescriptorDomNodeMap;
@@ -140,7 +140,7 @@ public AbstractApplicationComposition(@Nonnull IMFCompositionPlaylistType imfCom
this.regXMLLibDictionary = new RegXMLLibDictionary();
- this.coreConstraintsVersion = this.compositionPlaylistType.getCoreConstraintsVersion();
+ this.coreConstraintsSchema = this.compositionPlaylistType.getCoreConstraintsSchema();
this.essenceDescriptorKeyIgnoreSet = Collections.unmodifiableSet(ignoreSet);
@@ -375,12 +375,22 @@ private IMFCompositionPlaylistType getCompositionPlaylistType() {
}
/**
- * Getter for the CoreConstraintsURI corresponding to this CompositionPlaylist
+ * Get the Java package string for the Core Constraints version
+ * @deprecated Instead use {@link #getCoreConstraintsSchema()}
*
- * @return the uri for the CoreConstraints schema for this CompositionPlaylist
+ * @return package containing the Core Constraints classes
*/
+ @Deprecated
public String getCoreConstraintsVersion() {
- return this.coreConstraintsVersion;
+ return CoreConstraints.packageFromSchema(this.coreConstraintsSchema);
+ }
+
+ /**
+ * Getter for the Core Constraints schema URI.
+ * @return URI for the Core Constraints schema
+ */
+ @Nonnull public String getCoreConstraintsSchema() {
+ return this.coreConstraintsSchema;
}
/**
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/Application2Composition.java b/src/main/java/com/netflix/imflibrary/st2067_2/Application2Composition.java
index 45e68894..c19b3b34 100755
--- a/src/main/java/com/netflix/imflibrary/st2067_2/Application2Composition.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/Application2Composition.java
@@ -25,6 +25,8 @@
* A class that models Composition with Application 2 constraints from 2067-20 specification
*/
public class Application2Composition extends AbstractApplicationComposition {
+ public static final String SCHEMA_URI_APP2_2013 = "http://www.smpte-ra.org/schemas/2067-20/2013";
+ public static final String SCHEMA_URI_APP2_2016 = "http://www.smpte-ra.org/schemas/2067-20/2016";
public static final Integer MAX_IMAGE_FRAME_WIDTH = 1920;
public static final Integer MAX_IMAGE_FRAME_HEIGHT = 1080;
public static final SetprogressiveSampleRateSupported = Collections.unmodifiableSet(new HashSet() {{
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/Application2ExtendedComposition.java b/src/main/java/com/netflix/imflibrary/st2067_2/Application2ExtendedComposition.java
index e43b9616..59438692 100755
--- a/src/main/java/com/netflix/imflibrary/st2067_2/Application2ExtendedComposition.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/Application2ExtendedComposition.java
@@ -23,6 +23,9 @@
* A class that models Composition with Application 2Extended constraints from 2067-21 specification
*/
public class Application2ExtendedComposition extends AbstractApplicationComposition {
+ public static final String SCHEMA_URI_APP2E_2014 = "http://www.smpte-ra.org/schemas/2067-21/2014";
+ public static final String SCHEMA_URI_APP2E_2016 = "http://www.smpte-ra.org/schemas/2067-21/2016";
+ public static final String SCHEMA_URI_APP2E_2020 = "http://www.smpte-ra.org/ns/2067-21/2020";
public static final Integer MAX_YUV_IMAGE_FRAME_WIDTH = 3840;
public static final Integer MAX_YUV_IMAGE_FRAME_HEIGHT = 2160;
public static final Integer MAX_RGB_IMAGE_FRAME_WIDTH = 4096;
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/Application5Composition.java b/src/main/java/com/netflix/imflibrary/st2067_2/Application5Composition.java
index 7b63c2c8..24f71648 100644
--- a/src/main/java/com/netflix/imflibrary/st2067_2/Application5Composition.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/Application5Composition.java
@@ -44,6 +44,7 @@
* A class that models Composition with Application 5 constraints from 2067-50 specification
*/
public class Application5Composition extends AbstractApplicationComposition {
+ public static final String SCHEMA_URI_APP5_2017 = "http://www.smpte-ra.org/ns/2067-50/2017";
public static final Integer MAX_RGB_IMAGE_FRAME_WIDTH = Integer.MAX_VALUE; //TODO: 2067-50 specifies 2^32-1, would require using Long instead of Integer
public static final Integer MAX_RGB_IMAGE_FRAME_HEIGHT = Integer.MAX_VALUE; //TODO: 2067-50 specifies 2^32-1, would require using Long instead of Integer
public static final Map>colorToBitDepthMap = Collections.unmodifiableMap(new HashMap>() {{
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationComposition.java b/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationComposition.java
index d5c05946..0ba15c0e 100644
--- a/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationComposition.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationComposition.java
@@ -106,12 +106,20 @@ public interface ApplicationComposition {
public UUID getUUID();
/**
- * Getter for the CoreConstraintsURI corresponding to this CompositionPlaylist
+ * Get the Java package string for the Core Constraints version
+ * @deprecated Instead use {@link #getCoreConstraintsSchema()}
*
- * @return the uri for the CoreConstraints schema for this CompositionPlaylist
+ * @return package containing the Core Constraints classes
*/
+ @Deprecated
public String getCoreConstraintsVersion();
+ /**
+ * Getter for the Core Constraints schema URI.
+ * @return URI for the Core Constraints schema
+ */
+ @Nonnull public String getCoreConstraintsSchema();
+
/**
* Getter for the essence VirtualTracks in this Composition
*
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationCompositionFactory.java b/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationCompositionFactory.java
index c4e28e16..b6bc84e5 100755
--- a/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationCompositionFactory.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/ApplicationCompositionFactory.java
@@ -44,6 +44,7 @@ public class ApplicationCompositionFactory {
private static final Set namespacesApplication2EComposition = Collections.unmodifiableSet(new HashSet() {{
add("http://www.smpte-ra.org/schemas/2067-21/2014");
add("http://www.smpte-ra.org/schemas/2067-21/2016");
+ add("http://www.smpte-ra.org/ns/2067-21/2020");
}});
private static final Set namespacesApplication5Composition = Collections.unmodifiableSet(new HashSet() {{
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2013.java b/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2013.java
index 7c8b5d25..f8c4aa2e 100755
--- a/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2013.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2013.java
@@ -62,6 +62,22 @@ private CompositionModel_st2067_2_2013(){
// Parse the ApplicationIdentification values
Set applicationIDs = parseApplicationIds(compositionPlaylistType, imfErrorLogger);
+ // Identify the Core Constraints version
+ String coreConstraintsSchema = CoreConstraints.fromApplicationId(applicationIDs);
+ if (coreConstraintsSchema == null)
+ {
+ // Get the namespaces of each Sequence being used
+ Set sequenceNamespaces = compositionPlaylistType.getSegmentList().getSegment().get(0)
+ .getSequenceList().getAny().stream().filter(JAXBElement.class::isInstance)
+ .map(je -> ((JAXBElement>) je).getName().getNamespaceURI()).collect(Collectors.toSet());
+ // Find the Core Constraints version, based on the namespaces of the Sequences
+ coreConstraintsSchema = CoreConstraints.fromElementNamespaces(sequenceNamespaces);
+
+ // If all else fails, assume the minimum version applicable to this CPL version
+ if (coreConstraintsSchema == null)
+ coreConstraintsSchema = CoreConstraints.NAMESPACE_IMF_2013;
+ }
+
return new IMFCompositionPlaylistType( compositionPlaylistType.getId(),
compositionPlaylistType.getEditRate(),
(compositionPlaylistType.getAnnotation() == null ? null : compositionPlaylistType.getAnnotation().getValue()),
@@ -71,7 +87,8 @@ private CompositionModel_st2067_2_2013(){
(compositionPlaylistType.getContentTitle() == null ? null : compositionPlaylistType.getContentTitle().getValue()),
segmentList,
essenceDescriptorList,
- "org.smpte_ra.schemas.st2067_2_2013", applicationIDs
+ coreConstraintsSchema,
+ applicationIDs
);
}
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2016.java b/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2016.java
index 8a871220..968e0dd5 100755
--- a/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2016.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/CompositionModel_st2067_2_2016.java
@@ -62,6 +62,22 @@ private CompositionModel_st2067_2_2016(){
// Parse the ApplicationIdentification values
Set applicationIDs = parseApplicationIds(compositionPlaylistType, imfErrorLogger);
+ // Identify the Core Constraints version
+ String coreConstraintsSchema = CoreConstraints.fromApplicationId(applicationIDs);
+ if (coreConstraintsSchema == null)
+ {
+ // Get the namespaces of each Sequence being used
+ Set sequenceNamespaces = compositionPlaylistType.getSegmentList().getSegment().get(0)
+ .getSequenceList().getAny().stream().filter(JAXBElement.class::isInstance)
+ .map(je -> ((JAXBElement>) je).getName().getNamespaceURI()).collect(Collectors.toSet());
+ // Find the Core Constraints version, based on the namespaces of the Sequences
+ coreConstraintsSchema = CoreConstraints.fromElementNamespaces(sequenceNamespaces);
+
+ // If all else fails, assume the minimum version applicable to this CPL version
+ if (coreConstraintsSchema == null)
+ coreConstraintsSchema = CoreConstraints.NAMESPACE_IMF_2016;
+ }
+
return new IMFCompositionPlaylistType( compositionPlaylistType.getId(),
compositionPlaylistType.getEditRate(),
(compositionPlaylistType.getAnnotation() == null ? null : compositionPlaylistType.getAnnotation().getValue()),
@@ -71,7 +87,8 @@ private CompositionModel_st2067_2_2016(){
(compositionPlaylistType.getContentTitle() == null ? null : compositionPlaylistType.getContentTitle().getValue()),
segmentList,
essenceDescriptorList,
- "org.smpte_ra.schemas.st2067_2_2016", applicationIDs
+ coreConstraintsSchema,
+ applicationIDs
);
}
@@ -290,7 +307,8 @@ private static JAXBContext createJAXBContext()
try
{
return JAXBContext.newInstance(
- org.smpte_ra.schemas.st2067_2_2016.ObjectFactory.class); // 2016 CPL and Core constraints
+ org.smpte_ra.schemas.st2067_2_2016.ObjectFactory.class, // 2016 CPL and Core constraints
+ org.smpte_ra.schemas.st2067_2_2020.ObjectFactory.class); // 2020 Core constraints also use 2016 CPL
}
catch(JAXBException e)
{
@@ -311,6 +329,7 @@ private static Schema createValidationSchema()
InputStream xsd_dcmlTypes = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st0433_2008/dcmlTypes/dcmlTypes.xsd");
InputStream xsd_cpl_2016 = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_3_2016/imf-cpl-20160411.xsd");
InputStream xsd_core_constraints_2016 = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_2_2016/imf-core-constraints-20160411.xsd");
+ InputStream xsd_core_constraints_2020 = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_2_2020/imf-core-constraints-2020.xsd")
)
{
// Build a schema from all of the XSD files provided
@@ -320,6 +339,7 @@ private static Schema createValidationSchema()
new StreamSource(xsd_dcmlTypes),
new StreamSource(xsd_cpl_2016),
new StreamSource(xsd_core_constraints_2016),
+ new StreamSource(xsd_core_constraints_2020),
});
}
catch(IOException | SAXException e)
@@ -328,15 +348,4 @@ private static Schema createValidationSchema()
}
}
}
-
- /**
- * Getter for the CoreConstraintsURI corresponding to this CompositionPlaylist
- *
- * @return the uri for the CoreConstraints schema for this CompositionPlaylist
- * @deprecated This is an instance method of a class declared final, with a private constructor. Should never be callable
- */
- @Deprecated
- public String getCoreConstraintsVersion() {
- return "org.smpte_ra.schemas.st2067_2_2016";
- }
}
\ No newline at end of file
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/CoreConstraints.java b/src/main/java/com/netflix/imflibrary/st2067_2/CoreConstraints.java
new file mode 100644
index 00000000..6b36d474
--- /dev/null
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/CoreConstraints.java
@@ -0,0 +1,88 @@
+package com.netflix.imflibrary.st2067_2;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public final class CoreConstraints
+{
+ private CoreConstraints() {} // Prevent instantiation. This class is constants and utilities only
+
+ // SMPTE ST 2067-2 version namespaces
+ public static final String NAMESPACE_IMF_2013 = "http://www.smpte-ra.org/schemas/2067-2/2013";
+ public static final String NAMESPACE_IMF_2016 = "http://www.smpte-ra.org/schemas/2067-2/2016";
+ public static final String NAMESPACE_IMF_2020 = "http://www.smpte-ra.org/ns/2067-2/2020";
+
+ static final List SUPPORTED_NAMESPACES = Collections.unmodifiableList(Arrays.asList(
+ NAMESPACE_IMF_2013, NAMESPACE_IMF_2016, NAMESPACE_IMF_2020));
+
+ /**
+ * @deprecated Remove once all deprecated, package-based, 'getCoreConstraintsVersion' methods are removed.
+ */
+ @Deprecated
+ static String packageFromSchema(String coreConstraintsSchema)
+ {
+ if (coreConstraintsSchema.equals(NAMESPACE_IMF_2013))
+ return "org.smpte_ra.schemas.st2067_2_2013";
+ else if (coreConstraintsSchema.equals(NAMESPACE_IMF_2016))
+ return "org.smpte_ra.schemas.st2067_2_2016";
+ else if (coreConstraintsSchema.equals(NAMESPACE_IMF_2020))
+ return "org.smpte_ra.schemas.st2067_2_2020";
+ else
+ return coreConstraintsSchema; // No mapping, just return the schema value
+ }
+
+ // Determine the highest Core Constraints version based on the ApplicationIds used
+ @Nullable public static String fromApplicationId(@Nonnull Collection applicationIds)
+ {
+ // NOTE- When adding new namespaces or core constraint versions, be sure that the most recent core constraints
+ // are checked first. That way if there are multiple ApplicationIdentifications, the newest version is returned.
+ if (applicationIds.contains(Application2ExtendedComposition.SCHEMA_URI_APP2E_2020))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2020;
+ }
+ else if (applicationIds.contains(Application5Composition.SCHEMA_URI_APP5_2017)
+ || applicationIds.contains(Application2ExtendedComposition.SCHEMA_URI_APP2E_2016)
+ || applicationIds.contains(Application2Composition.SCHEMA_URI_APP2_2016))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2016;
+ }
+ else if (applicationIds.contains(Application2ExtendedComposition.SCHEMA_URI_APP2E_2014)
+ || applicationIds.contains(Application2Composition.SCHEMA_URI_APP2_2013))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2013;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ // Determine the most recent core constraints version, based on a collection of element namespaces
+ static String fromElementNamespaces(@Nonnull Collection namespaces)
+ {
+ // NOTE- When adding new namespaces or core constraint versions, be sure that the most recent core constraints
+ // are checked first. That way if there are multiple different namespaces, the newest version is returned.
+ if (namespaces.contains(CoreConstraints.NAMESPACE_IMF_2020))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2020;
+ }
+ else if (namespaces.contains(CoreConstraints.NAMESPACE_IMF_2016))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2016;
+ }
+ else if (namespaces.contains(CoreConstraints.NAMESPACE_IMF_2013))
+ {
+ return CoreConstraints.NAMESPACE_IMF_2013;
+ }
+ else
+ {
+ // TODO- Consider identify core constraints based on other namespaces
+ // Example- IABSequence "http://www.smpte-ra.org/ns/2067-201/2019" requires core constraints ST 2067-2:2016
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/IMFCompositionPlaylistType.java b/src/main/java/com/netflix/imflibrary/st2067_2/IMFCompositionPlaylistType.java
index b01b52d5..6ddb1579 100644
--- a/src/main/java/com/netflix/imflibrary/st2067_2/IMFCompositionPlaylistType.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/IMFCompositionPlaylistType.java
@@ -60,7 +60,7 @@ final class IMFCompositionPlaylistType {
private final List segmentList;
private final List essenceDescriptorList;
private final IMFErrorLogger imfErrorLogger;
- private final String coreConstraintsVersion;
+ private final String coreConstraintsSchema;
private final Set applicationIdSet;
/**
@@ -79,10 +79,10 @@ public IMFCompositionPlaylistType(String id,
String contentTitle,
List segmentList,
List essenceDescriptorList,
- String coreConstraintsVersion,
+ String coreConstraintsSchema,
String applicationId)
{
- this(id, editRate, annotation, issuer, creator, contentOriginator, contentTitle, segmentList, essenceDescriptorList, coreConstraintsVersion, (applicationId == null ? new HashSet<>() : new HashSet(Arrays.asList(applicationId))));
+ this(id, editRate, annotation, issuer, creator, contentOriginator, contentTitle, segmentList, essenceDescriptorList, coreConstraintsSchema, (applicationId == null ? new HashSet<>() : new HashSet(Arrays.asList(applicationId))));
}
public IMFCompositionPlaylistType(String id,
@@ -94,7 +94,7 @@ public IMFCompositionPlaylistType(String id,
String contentTitle,
List segmentList,
List essenceDescriptorList,
- String coreConstraintsVersion,
+ String coreConstraintsSchema,
@Nonnull Set applicationIds)
{
this.id = UUIDHelper.fromUUIDAsURNStringToUUID(id);
@@ -117,7 +117,7 @@ public IMFCompositionPlaylistType(String id,
this.contentTitle = contentTitle;
this.segmentList = Collections.unmodifiableList(segmentList);
this.essenceDescriptorList = Collections.unmodifiableList(essenceDescriptorList);
- this.coreConstraintsVersion = coreConstraintsVersion;
+ this.coreConstraintsSchema = coreConstraintsSchema;
this.applicationIdSet = Collections.unmodifiableSet(applicationIds);
if(imfErrorLogger.hasFatalErrors())
@@ -318,12 +318,12 @@ public List getEssenceDescriptorList(){
}
/**
- * Getter for the CoreConstraintsURI corresponding to this CompositionPlaylist
+ * Getter for the CoreConstraints URI corresponding to this CompositionPlaylist
*
* @return the uri for the CoreConstraints schema for this CompositionPlaylist
*/
- public String getCoreConstraintsVersion() {
- return this.coreConstraintsVersion;
+ @Nonnull public String getCoreConstraintsSchema() {
+ return this.coreConstraintsSchema;
}
/**
diff --git a/src/main/java/com/netflix/imflibrary/st2067_2/IMFCoreConstraintsChecker.java b/src/main/java/com/netflix/imflibrary/st2067_2/IMFCoreConstraintsChecker.java
index 66120f3a..5998f9d1 100644
--- a/src/main/java/com/netflix/imflibrary/st2067_2/IMFCoreConstraintsChecker.java
+++ b/src/main/java/com/netflix/imflibrary/st2067_2/IMFCoreConstraintsChecker.java
@@ -274,7 +274,11 @@ else if( virtualTrack.getSequenceTypeEnum().equals(Composition.SequenceTypeEnum.
}
//Section 6.3.2 st2067-2:2016 and Section 6.9.3 st2067-3:2016
- if(!foundMainAudioEssence){
+ //Section 6.3.2 st2067-2:2020 allows CPLs without Audio Virtual Tracks
+ if(!foundMainAudioEssence
+ && (compositionPlaylistType.getCoreConstraintsSchema().equals(CoreConstraints.NAMESPACE_IMF_2013)
+ || compositionPlaylistType.getCoreConstraintsSchema().equals(CoreConstraints.NAMESPACE_IMF_2016)))
+ {
imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CORE_CONSTRAINTS_ERROR, IMFErrorLogger.IMFErrors.ErrorLevels.FATAL, String.format("The Composition represented by Id %s does not contain a single audio essence in its first segment, one or more is required", compositionPlaylistType.getId().toString()));
}
diff --git a/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2013.java b/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2013.java
index 91e972a5..57e47e12 100755
--- a/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2013.java
+++ b/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2013.java
@@ -22,6 +22,7 @@
import com.netflix.imflibrary.IMFErrorLoggerImpl;
import com.netflix.imflibrary.exceptions.IMFAuthoringException;
import com.netflix.imflibrary.st2067_2.Composition;
+import com.netflix.imflibrary.st2067_2.CoreConstraints;
import com.netflix.imflibrary.st2067_2.IMFEssenceComponentVirtualTrack;
import com.netflix.imflibrary.st2067_2.IMFEssenceDescriptorBaseType;
import com.netflix.imflibrary.st2067_2.IMFMarkerResourceType;
@@ -36,7 +37,6 @@
import org.smpte_ra.schemas.st2067_2_2013.CompositionPlaylistType;
import org.smpte_ra.schemas.st2067_2_2013.CompositionTimecodeType;
import org.smpte_ra.schemas.st2067_2_2013.ContentVersionType;
-import org.smpte_ra.schemas.st2067_2_2013.SequenceType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@@ -63,10 +63,12 @@
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -94,10 +96,9 @@ public class CompositionPlaylistBuilder_2013 {
public final static String defaultHashAlgorithm = "http://www.w3.org/2000/09/xmldsig#sha1";
private final static String defaultContentKindScope = "http://www.smpte-ra.org/schemas/2067-3/XXXX#content-kind";
private final String cplFileName;
-
- private final String applicationId;
- Map trackResourceSourceEncodingMap;
-
+ private final String coreConstraintsSchema;
+ private final Set applicationIds;
+ private final Map trackResourceSourceEncodingMap;
/**
* A constructor for CompositionPlaylistBuilder class to build a CompositionPlaylist document compliant with st2067-2:2013 schema
@@ -107,11 +108,12 @@ public class CompositionPlaylistBuilder_2013 {
* @param creator a free form human readable text describing the tool used to create the CompositionPlaylist document
* @param virtualTracks a list of VirtualTracks of the Composition
* @param compositionEditRate the edit rate of the Composition
- * @param applicationId ApplicationId for the composition
+ * @param applicationIds ApplicationIds for the composition
* @param totalRunningTime a long value representing in seconds the total running time of this composition
* @param trackFileInfoMap a map of the IMFTrackFile's UUID to the track file info
* @param workingDirectory a folder location where the constructed CPL document can be written to
* @param imfEssenceDescriptorBaseTypeList List of IMFEssenceDescriptorBaseType
+ * @param coreConstraintsSchema schema defining core constraints version
*/
public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
@Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType annotationText,
@@ -119,29 +121,29 @@ public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
@Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType creator,
@Nonnull List extends Composition.VirtualTrack> virtualTracks,
@Nonnull Composition.EditRate compositionEditRate,
- @Nonnull String applicationId,
+ @Nonnull Set applicationIds,
long totalRunningTime,
@Nonnull Map trackFileInfoMap,
@Nonnull File workingDirectory,
- @Nonnull List imfEssenceDescriptorBaseTypeList){
+ @Nonnull List imfEssenceDescriptorBaseTypeList,
+ @Nonnull String coreConstraintsSchema){
this.uuid = uuid;
this.annotationText = annotationText;
this.issuer = issuer;
this.creator = creator;
this.issueDate = IMFUtils.createXMLGregorianCalendar();
this.virtualTracks = Collections.unmodifiableList(virtualTracks);
- List editRate = new ArrayList() {{add(compositionEditRate.getNumerator());
- add(compositionEditRate.getDenominator());}};
- this.compositionEditRate = Collections.unmodifiableList(editRate);
+ this.compositionEditRate = Collections.unmodifiableList(Arrays.asList(compositionEditRate.getNumerator(), compositionEditRate.getDenominator()));
this.totalRunningTime = totalRunningTime;
this.trackFileInfoMap = Collections.unmodifiableMap(trackFileInfoMap);
this.workingDirectory = workingDirectory;
this.imfErrorLogger = new IMFErrorLoggerImpl();
- cplFileName = "CPL-" + this.uuid.toString() + ".xml";
- this.applicationId = applicationId;
- this.trackResourceSourceEncodingMap = new HashMap<>();//Map of TrackFileId -> SourceEncodingElement of each resource of this VirtualTrack
+ this.cplFileName = "CPL-" + this.uuid.toString() + ".xml";
+ this.applicationIds = Collections.unmodifiableSet(applicationIds);
this.imfEssenceDescriptorBaseTypeList = Collections.unmodifiableList(imfEssenceDescriptorBaseTypeList);
+ this.coreConstraintsSchema = coreConstraintsSchema;
+ Map trackEncodingMap = new HashMap<>(); //Map of TrackFileId -> SourceEncodingElement of each resource of this VirtualTrack
for(Composition.VirtualTrack virtualTrack : virtualTracks) {
if (!(virtualTrack instanceof IMFEssenceComponentVirtualTrack)) {
continue; // Skip non-essence tracks
@@ -149,13 +151,42 @@ public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
IMFEssenceComponentVirtualTrack essenceTrack = (IMFEssenceComponentVirtualTrack) virtualTrack;
for (IMFTrackFileResourceType trackResource : essenceTrack.getTrackFileResourceList()) {
- UUID sourceEncoding = trackResourceSourceEncodingMap.get(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()));
+ UUID sourceEncoding = trackEncodingMap.get(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()));
if (sourceEncoding == null) {
- trackResourceSourceEncodingMap.put(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()), UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getSourceEncoding()));
+ trackEncodingMap.put(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()), UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getSourceEncoding()));
}
}
}
+ this.trackResourceSourceEncodingMap = Collections.unmodifiableMap(trackEncodingMap);
+ }
+ /**
+ * A constructor for CompositionPlaylistBuilder class to build a CompositionPlaylist document compliant with st2067-2:2013 schema
+ * @param uuid identifying the CompositionPlaylist document
+ * @param annotationText a free form human readable text
+ * @param issuer a free form human readable text describing the issuer of the CompositionPlaylist document
+ * @param creator a free form human readable text describing the tool used to create the CompositionPlaylist document
+ * @param virtualTracks a list of VirtualTracks of the Composition
+ * @param compositionEditRate the edit rate of the Composition
+ * @param applicationId ApplicationId for the composition
+ * @param totalRunningTime a long value representing in seconds the total running time of this composition
+ * @param trackFileInfoMap a map of the IMFTrackFile's UUID to the track file info
+ * @param workingDirectory a folder location where the constructed CPL document can be written to
+ * @param imfEssenceDescriptorBaseTypeList List of IMFEssenceDescriptorBaseType
+ */
+ @Deprecated
+ public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType annotationText,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType issuer,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType creator,
+ @Nonnull List extends Composition.VirtualTrack> virtualTracks,
+ @Nonnull Composition.EditRate compositionEditRate,
+ @Nonnull String applicationId,
+ long totalRunningTime,
+ @Nonnull Map trackFileInfoMap,
+ @Nonnull File workingDirectory,
+ @Nonnull List imfEssenceDescriptorBaseTypeList){
+ this(uuid, annotationText, issuer, creator, virtualTracks, compositionEditRate, Collections.singleton(applicationId), totalRunningTime, trackFileInfoMap, workingDirectory, imfEssenceDescriptorBaseTypeList, CoreConstraints.NAMESPACE_IMF_2013);
}
@@ -172,6 +203,7 @@ public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
* @param trackFileInfoMap a map of the IMFTrackFile's UUID to the track file info
* @param workingDirectory a folder location where the constructed CPL document can be written to
*/
+ @Deprecated
public CompositionPlaylistBuilder_2013(@Nonnull UUID uuid,
@Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType annotationText,
@Nonnull org.smpte_ra.schemas.st2067_2_2013.UserTextType issuer,
@@ -241,24 +273,15 @@ public List build() throws IOException, ParserConfigura
cplRoot.setSegmentList(buildSegmentList(new ArrayList(){{add(segmentType);}}));
cplRoot.setSigner(null);
cplRoot.setSignature(null);
- try {
- String nodeString = "" +
- this.applicationId +
- "";
-
- Element element = DocumentBuilderFactory
- .newInstance()
- .newDocumentBuilder()
- .parse(new ByteArrayInputStream(nodeString.getBytes("UTF-8")))
- .getDocumentElement();
+ if (!this.applicationIds.isEmpty())
+ {
+ JAXBElement> appIdElement = new org.smpte_ra.schemas.st2067_2_2013.ObjectFactory()
+ .createApplicationIdentification(new ArrayList<>(this.applicationIds));
+
org.smpte_ra.schemas.st2067_2_2013.CompositionPlaylistType.ExtensionProperties extensionProperties = new org.smpte_ra.schemas.st2067_2_2013.CompositionPlaylistType.ExtensionProperties();
- extensionProperties.getAny().add(element);
+ extensionProperties.getAny().add(appIdElement);
cplRoot.setExtensionProperties( extensionProperties);
}
- catch(SAXException ex) {
- imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR, IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
- "Failed to create DOM node for ApplicationIdentification");
- }
File outputFile = new File(this.workingDirectory + File.separator + this.cplFileName);
List errors = serializeCPLToXML(cplRoot, outputFile);
diff --git a/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2016.java b/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2016.java
index 9b230e83..55cd48c4 100755
--- a/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2016.java
+++ b/src/main/java/com/netflix/imflibrary/writerTools/CompositionPlaylistBuilder_2016.java
@@ -21,6 +21,7 @@
import com.netflix.imflibrary.IMFErrorLoggerImpl;
import com.netflix.imflibrary.exceptions.IMFAuthoringException;
import com.netflix.imflibrary.st2067_2.Composition;
+import com.netflix.imflibrary.st2067_2.CoreConstraints;
import com.netflix.imflibrary.st2067_2.IMFEssenceComponentVirtualTrack;
import com.netflix.imflibrary.st2067_2.IMFEssenceDescriptorBaseType;
import com.netflix.imflibrary.st2067_2.IMFMarkerResourceType;
@@ -37,7 +38,7 @@
import org.smpte_ra.schemas.st2067_2_2016.ContentVersionType;
import org.smpte_ra.schemas.st2067_2_2016.EssenceDescriptorBaseType;
import org.smpte_ra.schemas.st2067_2_2016.SegmentType;
-import org.smpte_ra.schemas.st2067_2_2016.SequenceType;
+import org.smpte_ra.schemas.st2067_2_2016.UserTextType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@@ -64,10 +65,12 @@
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -94,23 +97,25 @@ public class CompositionPlaylistBuilder_2016 {
public final static String defaultHashAlgorithm = "http://www.w3.org/2000/09/xmldsig#sha1";
private final static String defaultContentKindScope = "http://www.smpte-ra.org/schemas/2067-3/XXXX#content-kind";
private final String cplFileName;
- private final String applicationId;
- Map trackResourceSourceEncodingMap;
+ private final Set applicationIds;
+ private final String coreConstraintsSchema;
+ private final Map trackResourceSourceEncodingMap;
/**
- * A constructor for CompositionPlaylistBuilder class to build a CompositionPlaylist document compliant with st2067-2:2013 schema
+ * A constructor for CompositionPlaylistBuilder class to build a CompositionPlaylist document compliant with st2067-2:2016 schema
* @param uuid identifying the CompositionPlaylist document
* @param annotationText a free form human readable text
* @param issuer a free form human readable text describing the issuer of the CompositionPlaylist document
* @param creator a free form human readable text describing the tool used to create the CompositionPlaylist document
* @param virtualTracks a list of VirtualTracks of the Composition
* @param compositionEditRate the edit rate of the Composition
- * @param applicationId ApplicationId for the composition
+ * @param applicationIds ApplicationIds for the composition
* @param totalRunningTime a long value representing in seconds the total running time of this composition
* @param trackFileInfoMap a map of the IMFTrackFile's UUID to the track file info
* @param workingDirectory a folder location where the constructed CPL document can be written to
* @param imfEssenceDescriptorBaseTypeList List of IMFEssenceDescriptorBaseType
+ * @param coreConstraintsSchema schema defining core constraints version
*/
public CompositionPlaylistBuilder_2016(@Nonnull UUID uuid,
@Nonnull org.smpte_ra.schemas.st2067_2_2016.UserTextType annotationText,
@@ -118,29 +123,29 @@ public CompositionPlaylistBuilder_2016(@Nonnull UUID uuid,
@Nonnull org.smpte_ra.schemas.st2067_2_2016.UserTextType creator,
@Nonnull List extends Composition.VirtualTrack> virtualTracks,
@Nonnull Composition.EditRate compositionEditRate,
- @Nonnull String applicationId,
+ @Nonnull Set applicationIds,
long totalRunningTime,
@Nonnull Map trackFileInfoMap,
@Nonnull File workingDirectory,
- @Nonnull List imfEssenceDescriptorBaseTypeList){
+ @Nonnull List imfEssenceDescriptorBaseTypeList,
+ @Nonnull String coreConstraintsSchema){
this.uuid = uuid;
this.annotationText = annotationText;
this.issuer = issuer;
this.creator = creator;
this.issueDate = IMFUtils.createXMLGregorianCalendar();
this.virtualTracks = Collections.unmodifiableList(virtualTracks);
- List editRate = new ArrayList() {{add(compositionEditRate.getNumerator());
- add(compositionEditRate.getDenominator());}};
- this.compositionEditRate = Collections.unmodifiableList(editRate);
+ this.compositionEditRate = Collections.unmodifiableList(Arrays.asList(compositionEditRate.getNumerator(), compositionEditRate.getDenominator()));
this.totalRunningTime = totalRunningTime;
this.trackFileInfoMap = Collections.unmodifiableMap(trackFileInfoMap);
this.workingDirectory = workingDirectory;
this.imfErrorLogger = new IMFErrorLoggerImpl();
- cplFileName = "CPL-" + this.uuid.toString() + ".xml";
- this.applicationId = applicationId;
- this.trackResourceSourceEncodingMap = new HashMap<>();//Map of TrackFileId -> SourceEncodingElement of each resource of this VirtualTrack
+ this.cplFileName = "CPL-" + this.uuid.toString() + ".xml";
+ this.applicationIds = Collections.unmodifiableSet(applicationIds);
this.imfEssenceDescriptorBaseTypeList = Collections.unmodifiableList(imfEssenceDescriptorBaseTypeList);
+ this.coreConstraintsSchema = coreConstraintsSchema;
+ Map trackEncodingMap = new HashMap<>(); //Map of TrackFileId -> SourceEncodingElement of each resource of this VirtualTrack
for(Composition.VirtualTrack virtualTrack : virtualTracks) {
if (!(virtualTrack instanceof IMFEssenceComponentVirtualTrack)) {
continue; // Skip non-essence tracks
@@ -148,13 +153,43 @@ public CompositionPlaylistBuilder_2016(@Nonnull UUID uuid,
IMFEssenceComponentVirtualTrack essenceTrack = (IMFEssenceComponentVirtualTrack) virtualTrack;
for (IMFTrackFileResourceType trackResource : essenceTrack.getTrackFileResourceList()) {
- UUID sourceEncoding = trackResourceSourceEncodingMap.get(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()));
+ UUID sourceEncoding = trackEncodingMap.get(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()));
if (sourceEncoding == null) {
- trackResourceSourceEncodingMap.put(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()), UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getSourceEncoding()));
+ trackEncodingMap.put(UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getTrackFileId()), UUIDHelper.fromUUIDAsURNStringToUUID(trackResource.getSourceEncoding()));
}
}
}
+ this.trackResourceSourceEncodingMap = Collections.unmodifiableMap(trackEncodingMap);
+ }
+ /**
+ * @deprecated Instead use {{@link #CompositionPlaylistBuilder_2016(UUID, UserTextType, UserTextType, UserTextType, List, Composition.EditRate, Set, long, Map, File, List, String)}}
+ * A constructor for CompositionPlaylistBuilder class to build a CompositionPlaylist document compliant with st2067-2:2016 schema
+ * @param uuid identifying the CompositionPlaylist document
+ * @param annotationText a free form human readable text
+ * @param issuer a free form human readable text describing the issuer of the CompositionPlaylist document
+ * @param creator a free form human readable text describing the tool used to create the CompositionPlaylist document
+ * @param virtualTracks a list of VirtualTracks of the Composition
+ * @param compositionEditRate the edit rate of the Composition
+ * @param applicationId ApplicationId for the composition
+ * @param totalRunningTime a long value representing in seconds the total running time of this composition
+ * @param trackFileInfoMap a map of the IMFTrackFile's UUID to the track file info
+ * @param workingDirectory a folder location where the constructed CPL document can be written to
+ * @param imfEssenceDescriptorBaseTypeList List of IMFEssenceDescriptorBaseType
+ */
+ @Deprecated
+ public CompositionPlaylistBuilder_2016(@Nonnull UUID uuid,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2016.UserTextType annotationText,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2016.UserTextType issuer,
+ @Nonnull org.smpte_ra.schemas.st2067_2_2016.UserTextType creator,
+ @Nonnull List extends Composition.VirtualTrack> virtualTracks,
+ @Nonnull Composition.EditRate compositionEditRate,
+ @Nonnull String applicationId,
+ long totalRunningTime,
+ @Nonnull Map trackFileInfoMap,
+ @Nonnull File workingDirectory,
+ @Nonnull List imfEssenceDescriptorBaseTypeList){
+ this(uuid, annotationText, issuer, creator, virtualTracks, compositionEditRate, Collections.singleton(applicationId), totalRunningTime, trackFileInfoMap, workingDirectory, imfEssenceDescriptorBaseTypeList, CoreConstraints.NAMESPACE_IMF_2016);
}
/**
@@ -217,24 +252,25 @@ public List build() throws IOException, ParserConfigura
cplRoot.setSegmentList(buildSegmentList(new ArrayList(){{add(segmentType);}}));
cplRoot.setSigner(null);
cplRoot.setSignature(null);
- try {
- String nodeString = "" +
- this.applicationId +
- "";
-
- Element element = DocumentBuilderFactory
- .newInstance()
- .newDocumentBuilder()
- .parse(new ByteArrayInputStream(nodeString.getBytes("UTF-8")))
- .getDocumentElement();
+
+ if (!this.applicationIds.isEmpty())
+ {
+ JAXBElement> appIdElement;
+ if (this.coreConstraintsSchema.equals(CoreConstraints.NAMESPACE_IMF_2020))
+ {
+ appIdElement = new org.smpte_ra.schemas.st2067_2_2020.ObjectFactory().createApplicationIdentification(new ArrayList<>(this.applicationIds));
+ }
+ else
+ {
+ appIdElement = new org.smpte_ra.schemas.st2067_2_2016.ObjectFactory().createApplicationIdentification(new ArrayList<>(this.applicationIds));
+ }
+
org.smpte_ra.schemas.st2067_2_2016.CompositionPlaylistType.ExtensionProperties extensionProperties = new org.smpte_ra.schemas.st2067_2_2016.CompositionPlaylistType.ExtensionProperties();
- extensionProperties.getAny().add(element);
+ extensionProperties.getAny().add(appIdElement);
cplRoot.setExtensionProperties( extensionProperties);
}
- catch(SAXException ex) {
- imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR, IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
- "Failed to create DOM node for ApplicationIdentification");
- }File outputFile = new File(this.workingDirectory + File.separator + this.cplFileName);
+
+ File outputFile = new File(this.workingDirectory + File.separator + this.cplFileName);
serializeCPLToXML(cplRoot, outputFile);
return imfErrorLogger.getErrors();
}
@@ -260,7 +296,8 @@ else if (virtualTrack instanceof IMFMarkerVirtualTrack)
return Collections.unmodifiableList(trackResourceList);
}
- private void serializeCPLToXML(org.smpte_ra.schemas.st2067_2_2016.CompositionPlaylistType cplRoot, File outputFile) throws IOException, JAXBException, SAXException{
+ // TODO- Refactor this and consolidate all marshall/unmarshall logic into CompositionModel_st2067_2_2016.java
+ private void serializeCPLToXML(org.smpte_ra.schemas.st2067_2_2016.CompositionPlaylistType cplRoot, File outputFile) throws IOException, JAXBException, SAXException{
int numErrors = imfErrorLogger.getNumberOfErrors();
boolean formatted = true;
@@ -270,18 +307,22 @@ private void serializeCPLToXML(org.smpte_ra.schemas.st2067_2_2016.CompositionPla
InputStream dcmlSchemaAsAStream = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st0433_2008/dcmlTypes/dcmlTypes.xsd");
InputStream cplSchemaAsAStream = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_3_2016/imf-cpl-20160411.xsd");
InputStream coreConstraintsSchemaAsAStream = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_2_2016/imf-core-constraints-20160411.xsd");
+ InputStream xsd_core_constraints_2020 = contextClassLoader.getResourceAsStream("org/smpte_ra/schemas/st2067_2_2020/imf-core-constraints-2020.xsd");
OutputStream outputStream = new FileOutputStream(outputFile)
)
{
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI );
- StreamSource[] schemaSources = new StreamSource[4];
+ StreamSource[] schemaSources = new StreamSource[5];
schemaSources[0] = new StreamSource(dsigSchemaAsAStream);
schemaSources[1] = new StreamSource(dcmlSchemaAsAStream);
schemaSources[2] = new StreamSource(cplSchemaAsAStream);
schemaSources[3] = new StreamSource(coreConstraintsSchemaAsAStream);
+ schemaSources[4] = new StreamSource(xsd_core_constraints_2020);
Schema schema = schemaFactory.newSchema(schemaSources);
- JAXBContext jaxbContext = JAXBContext.newInstance("org.smpte_ra.schemas.st2067_2_2016");
+ JAXBContext jaxbContext = JAXBContext.newInstance(
+ org.smpte_ra.schemas.st2067_2_2016.ObjectFactory.class, // 2016 CPL and Core constraints
+ org.smpte_ra.schemas.st2067_2_2020.ObjectFactory.class); // 2020 Core constraints also use 2016 CPL
Marshaller marshaller = jaxbContext.createMarshaller();
ValidationEventHandlerImpl validationEventHandler = new ValidationEventHandlerImpl(true);
marshaller.setEventHandler(validationEventHandler);
@@ -522,29 +563,56 @@ public org.smpte_ra.schemas.st2067_2_2016.SequenceType.ResourceList buildResourc
*/
public void populateSequenceListForSegment(List sequenceTypeTuples,
org.smpte_ra.schemas.st2067_2_2016.SegmentType segment) {
-
- org.smpte_ra.schemas.st2067_2_2016.ObjectFactory objectFactory = new org.smpte_ra.schemas.st2067_2_2016.ObjectFactory();
List