in src/main/java/com/netflix/imflibrary/st0377/HeaderPartition.java [92:477]
public HeaderPartition(ByteProvider byteProvider, long byteOffset, long maxPartitionSize, IMFErrorLogger imfErrorLogger) throws IOException
{
this.imfErrorLogger = imfErrorLogger;
long numBytesRead = 0;
int numErrors = imfErrorLogger.getNumberOfErrors(); //Number of errors prior to parsing and reading the HeaderPartition
//read partition pack
if(byteOffset != IMF_MXF_HEADER_PARTITION_OFFSET){
throw new MXFException(String.format("Expected the header partition to be at offset %d, whereas it is located at offset %d in the MXF file", IMF_MXF_HEADER_PARTITION_OFFSET, byteOffset));
}
this.partitionPack = new PartitionPack(byteProvider, IMF_MXF_HEADER_PARTITION_OFFSET, false, imfErrorLogger);
if(!this.partitionPack.isValidHeaderPartition())
{
throw new MXFException("Found an invalid header partition");
}
numBytesRead += this.partitionPack.getKLVPacketSize();
Long byteOffsetOfNextKLVPacket = byteOffset + numBytesRead;
//read primer pack or a single KLV fill item followed by primer pack
{
KLVPacket.Header header = new KLVPacket.Header(byteProvider, byteOffsetOfNextKLVPacket);
byte[] key = Arrays.copyOf(header.getKey(), header.getKey().length);
numBytesRead += header.getKLSize();
if (PrimerPack.isValidKey(key))
{
this.primerPack = new PrimerPack(byteProvider, header);
numBytesRead += header.getVSize();
}
else
{
byteProvider.skipBytes(header.getVSize());
numBytesRead += header.getVSize();
header = new KLVPacket.Header(byteProvider, byteOffsetOfNextKLVPacket);
key = Arrays.copyOf(header.getKey(), header.getKey().length);
numBytesRead += header.getKLSize();
if (PrimerPack.isValidKey(key))
{
this.primerPack = new PrimerPack(byteProvider, header);
numBytesRead += header.getVSize();
}
else
{
throw new MXFException("Could not find primer pack");
}
}
}
byteOffsetOfNextKLVPacket = byteOffset + numBytesRead;
//read structural metadata + KLV fill items
while (numBytesRead < maxPartitionSize)
{
KLVPacket.Header header = new KLVPacket.Header(byteProvider, byteOffsetOfNextKLVPacket);
//logger.info(String.format("Found KLV item with key = %s, length field size = %d, length value = %d", new MXFUID(header.getKey()), header.getLSize(), header.getVSize()));
byte[] key = Arrays.copyOf(header.getKey(), header.getKey().length);
numBytesRead += header.getKLSize();
if (StructuralMetadata.isStructuralMetadata(Arrays.copyOf(header.getKey(), header.getKey().length)) || StructuralMetadata.isDescriptiveMetadata(Arrays.copyOf(header.getKey(), header.getKey().length)))
{
Class clazz = StructuralMetadata.getStructuralMetadataSetClass(key);
if(!clazz.getSimpleName().equals(Object.class.getSimpleName())){
//logger.info(String.format("KLV item with key = %s corresponds to class %s", new MXFUID(header.getKey()), clazz.getSimpleName()));
InterchangeObject.InterchangeObjectBO interchangeObjectBO = this.constructInterchangeObjectBO(clazz, header, byteProvider, this.primerPack.getLocalTagEntryBatch().getLocalTagToUIDMap(), imfErrorLogger);
List<InterchangeObject.InterchangeObjectBO> list = this.interchangeObjectBOsMap.get(interchangeObjectBO.getClass().getSimpleName());
if(list == null){
list = new ArrayList<>();
this.interchangeObjectBOsMap.put(interchangeObjectBO.getClass().getSimpleName(), list);
}
list.add(interchangeObjectBO);
uidToBOs.put(interchangeObjectBO.getInstanceUID(), interchangeObjectBO);
if(interchangeObjectBO instanceof MaterialPackage.MaterialPackageBO
|| interchangeObjectBO instanceof SourcePackage.SourcePackageBO){
GenericPackage.GenericPackageBO genericPackageBO = (GenericPackage.GenericPackageBO)interchangeObjectBO;
uidToBOs.put(genericPackageBO.getPackageUID(), genericPackageBO);
}
}
else
{
byteProvider.skipBytes(header.getVSize());
}
}
else
{
byteProvider.skipBytes(header.getVSize());
}
numBytesRead += header.getVSize();
byteOffsetOfNextKLVPacket = byteOffset + numBytesRead;
}
//header partition validation
int prefaceSetCount = (this.interchangeObjectBOsMap.containsKey(Preface.PrefaceBO.class.getSimpleName()) && this.interchangeObjectBOsMap.get(Preface.PrefaceBO.class.getSimpleName()) != null)
? this.interchangeObjectBOsMap.get(Preface.PrefaceBO.class.getSimpleName()).size() : 0;
if (prefaceSetCount != 1)
{
imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_ESSENCE_COMPONENT_ERROR, IMFErrorLogger.IMFErrors.ErrorLevels.FATAL,
HeaderPartition.ERROR_DESCRIPTION_PREFIX + String.format("Found %d Preface sets, only one is allowed in header partition",
prefaceSetCount));
}
if (imfErrorLogger.getNumberOfErrors() > numErrors)//Flag an exception if any errors were accumulated while parsing and reading the HeaderPartition
{
List<ErrorLogger.ErrorObject> errorObjectList = imfErrorLogger.getErrors();
for(int i=numErrors; i< errorObjectList.size(); i++) {
logger.error(errorObjectList.get(i).getErrorDescription());
}
throw new MXFException(String.format("%d errors encountered when reading header partition", imfErrorLogger.getNumberOfErrors() - numErrors));
}
Set<InterchangeObject.InterchangeObjectBO> parsedInterchangeObjectBOs = new LinkedHashSet<>();
for (Map.Entry<MXFUID, InterchangeObject.InterchangeObjectBO> entry : uidToBOs.entrySet())
{
parsedInterchangeObjectBOs.add(entry.getValue());
}
Map<MXFUID, Node> instanceIDToNodes = new LinkedHashMap<>();
for(InterchangeObject.InterchangeObjectBO interchangeObjectBO : parsedInterchangeObjectBOs)
{
instanceIDToNodes.put(interchangeObjectBO.getInstanceUID(), new Node(interchangeObjectBO.getInstanceUID()));
}
for (Map.Entry<MXFUID, Node> entry : instanceIDToNodes.entrySet())
{
Node node = entry.getValue();
InterchangeObject.InterchangeObjectBO interchangeObjectBO = uidToBOs.get(node.uid);
List<MXFUID> dependentUIDs = MXFPropertyPopulator.getDependentUIDs(interchangeObjectBO);
for(MXFUID MXFUID : dependentUIDs)
{
InterchangeObject.InterchangeObjectBO dependentInterchangeObjectBO = uidToBOs.get(MXFUID);
if (dependentInterchangeObjectBO != null)
{
Node providerNode = instanceIDToNodes.get(dependentInterchangeObjectBO.getInstanceUID());
// providerNode.provides.add(node);
node.depends.add(providerNode);
}
}
}
List<Node> nodeList = new ArrayList<>(instanceIDToNodes.values());
List<Node> resolvedList = resolve(nodeList);
for(Node node : resolvedList) {
InterchangeObject.InterchangeObjectBO interchangeObjectBO = uidToBOs.get(node.uid);
if (node.depends.size() == 0
&& !interchangeObjectBO.getClass().equals(SourceClip.SourceClipBO.class)
&& !interchangeObjectBO.getClass().equals(Sequence.SequenceBO.class)
&& !interchangeObjectBO.getClass().equals(TimedTextDescriptor.TimedTextDescriptorBO.class)){
InterchangeObject interchangeObject = this.constructInterchangeObject(interchangeObjectBO.getClass().getEnclosingClass(), interchangeObjectBO, node);
this.cacheInterchangeObject(interchangeObject);
this.uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), interchangeObject);
if (interchangeObjectBO instanceof GenericPackage.GenericPackageBO) {
this.uidToMetadataSets.put(((GenericPackage.GenericPackageBO) interchangeObjectBO).getPackageUID(), interchangeObject);
}
}
else {
if (interchangeObjectBO.getClass().getEnclosingClass().equals(SourceClip.class)) {
GenericPackage genericPackage = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericPackage) {
genericPackage = (GenericPackage) dependentInterchangeObject;
}
}
SourceClip sourceClip = new SourceClip((SourceClip.SourceClipBO) interchangeObjectBO, genericPackage);
this.cacheInterchangeObject(sourceClip);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), sourceClip);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(Sequence.class)) {
List<StructuralComponent> structuralComponents = new ArrayList<>();
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof StructuralComponent) {
structuralComponents.add((StructuralComponent) dependentInterchangeObject);
}
}
Sequence sequence = new Sequence((Sequence.SequenceBO) interchangeObjectBO, structuralComponents);
this.cacheInterchangeObject(sequence);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), sequence);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(TimelineTrack.class)) {
Sequence sequence = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof Sequence) {
sequence = (Sequence) dependentInterchangeObject;
}
TimelineTrack timelineTrack = new TimelineTrack((TimelineTrack.TimelineTrackBO) interchangeObjectBO, sequence);
this.cacheInterchangeObject(timelineTrack);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), timelineTrack);
}
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(StaticTrack.class)) {
Sequence sequence = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof Sequence) {
sequence = (Sequence) dependentInterchangeObject;
}
StaticTrack staticTrack = new StaticTrack((StaticTrack.StaticTrackBO) interchangeObjectBO, sequence);
this.cacheInterchangeObject(staticTrack);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), staticTrack);
}
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(SourcePackage.class)) {
List<GenericTrack> genericTracks = new ArrayList<>();
GenericDescriptor genericDescriptor = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericTrack) {
genericTracks.add((GenericTrack) dependentInterchangeObject);
} else if (dependentInterchangeObject instanceof GenericDescriptor) {
genericDescriptor = (GenericDescriptor) dependentInterchangeObject;
}
}
SourcePackage sourcePackage = new SourcePackage((SourcePackage.SourcePackageBO) interchangeObjectBO, genericTracks, genericDescriptor);
this.cacheInterchangeObject(sourcePackage);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), sourcePackage);
uidToMetadataSets.put(((SourcePackage.SourcePackageBO) interchangeObjectBO).getPackageUID(), sourcePackage);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(MaterialPackage.class)) {
List<GenericTrack> genericTracks = new ArrayList<>();
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericTrack) {
genericTracks.add((GenericTrack) dependentInterchangeObject);
}
}
MaterialPackage materialPackage = new MaterialPackage((MaterialPackage.MaterialPackageBO) interchangeObjectBO, genericTracks);
this.cacheInterchangeObject(materialPackage);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), materialPackage);
uidToMetadataSets.put(((MaterialPackage.MaterialPackageBO) interchangeObjectBO).getPackageUID(), materialPackage);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(EssenceContainerData.class)) {
GenericPackage genericPackage = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericPackage) {
genericPackage = (GenericPackage) dependentInterchangeObject;
}
}
EssenceContainerData essenceContainerData = new EssenceContainerData(
(EssenceContainerData.EssenceContainerDataBO) interchangeObjectBO, genericPackage);
this.cacheInterchangeObject(essenceContainerData);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), essenceContainerData);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(ContentStorage.class)) {
List<GenericPackage> genericPackageList = new ArrayList<>();
List<EssenceContainerData> essenceContainerDataList = new ArrayList<>();
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericPackage) {
genericPackageList.add((GenericPackage) dependentInterchangeObject);
} else if (dependentInterchangeObject instanceof EssenceContainerData) {
essenceContainerDataList.add((EssenceContainerData) dependentInterchangeObject);
}
}
ContentStorage contentStorage = new ContentStorage(
(ContentStorage.ContentStorageBO) interchangeObjectBO, genericPackageList, essenceContainerDataList);
this.cacheInterchangeObject(contentStorage);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), contentStorage);
} else if (interchangeObjectBO.getClass().getEnclosingClass().equals(Preface.class)) {
GenericPackage genericPackage = null;
ContentStorage contentStorage = null;
for (Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if (dependentInterchangeObject instanceof GenericPackage) {
genericPackage = (GenericPackage) dependentInterchangeObject;
} else if (dependentInterchangeObject instanceof ContentStorage) {
contentStorage = (ContentStorage) dependentInterchangeObject;
}
}
Preface preface = new Preface((Preface.PrefaceBO) interchangeObjectBO, genericPackage, contentStorage);
this.cacheInterchangeObject(preface);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), preface);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(CDCIPictureEssenceDescriptor.class)){
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
/*Although we do retrieve the dependent SubDescriptor for this CDCIPictureEssenceDescriptor we do not really have a need for it,
* since it can always be retrieved using the strong reference present in the subDescriptors collection of the CDCIPictureEssenceDescriptor
* on the other hand passing a reference to the SubDescriptor to the constructor can be problematic since SubDescriptors are optional*/
JPEG2000PictureSubDescriptor jpeg2000PictureSubDescriptor = null;
if(dependentInterchangeObject instanceof JPEG2000PictureSubDescriptor){
jpeg2000PictureSubDescriptor = (JPEG2000PictureSubDescriptor) dependentInterchangeObject;
}
/*Add similar casting code for other sub descriptors when relevant*/
}
CDCIPictureEssenceDescriptor cdciPictureEssenceDescriptor = new CDCIPictureEssenceDescriptor((CDCIPictureEssenceDescriptor.CDCIPictureEssenceDescriptorBO) interchangeObjectBO);
this.cacheInterchangeObject(cdciPictureEssenceDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), cdciPictureEssenceDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(RGBAPictureEssenceDescriptor.class)){
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
/*Although we do retrieve the dependent SubDescriptor for this RGBAPictureEssenceDescriptor we do not really have a need for it,
* since it can always be retrieved using the strong reference present in the subDescriptors collection of the RGBAPictureEssenceDescriptor
* on the other hand passing a reference to the SubDescriptor to the constructor can be problematic since SubDescriptors are optional*/
JPEG2000PictureSubDescriptor jpeg2000PictureSubDescriptor = null;
if(dependentInterchangeObject instanceof JPEG2000PictureSubDescriptor){
jpeg2000PictureSubDescriptor = (JPEG2000PictureSubDescriptor) dependentInterchangeObject;
}
ACESPictureSubDescriptor acesPictureSubDescriptor = null;
if(dependentInterchangeObject instanceof ACESPictureSubDescriptor){
acesPictureSubDescriptor = (ACESPictureSubDescriptor) dependentInterchangeObject;
}
TargetFrameSubDescriptor targetFrameSubDescriptor = null;
if(dependentInterchangeObject instanceof TargetFrameSubDescriptor){
targetFrameSubDescriptor = (TargetFrameSubDescriptor) dependentInterchangeObject;
}
/*Add similar casting code for other sub descriptors when relevant*/
}
RGBAPictureEssenceDescriptor rgbaPictureEssenceDescriptor = new RGBAPictureEssenceDescriptor((RGBAPictureEssenceDescriptor.RGBAPictureEssenceDescriptorBO) interchangeObjectBO);
this.cacheInterchangeObject(rgbaPictureEssenceDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), rgbaPictureEssenceDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(WaveAudioEssenceDescriptor.class)){
List<InterchangeObject> subDescriptors = new ArrayList<InterchangeObject>();
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
/*
* Although we do retrieve the dependent SubDescriptors for this WaveAudioEssenceDescriptor we do not really have a need for it,
* since it can always be retrieved using the strong reference present in the subDescriptors collection of the WaveAudioEssenceDescriptor.
* On the other hand passing a reference to a SubDescriptor to the WaveAudioEssenceDescriptor's constructor can be problematic since
* SubDescriptors are optional
*/
AudioChannelLabelSubDescriptor audioChannelLabelSubDescriptor = null;
SoundFieldGroupLabelSubDescriptor soundFieldGroupLabelSubDescriptor = null;
if(dependentInterchangeObject instanceof AudioChannelLabelSubDescriptor){
audioChannelLabelSubDescriptor = (AudioChannelLabelSubDescriptor) dependentInterchangeObject;
subDescriptors.add(audioChannelLabelSubDescriptor);
}
else if (dependentInterchangeObject instanceof SoundFieldGroupLabelSubDescriptor){
soundFieldGroupLabelSubDescriptor = (SoundFieldGroupLabelSubDescriptor) dependentInterchangeObject;
subDescriptors.add(soundFieldGroupLabelSubDescriptor);
}
}
if(node.depends.size() > 0
&& subDescriptors.size() == 0){
throw new MXFException(String.format("The WaveAudioEssenceDescriptor in the essence has dependencies, but neither of them is a AudioChannelLabelSubDescriptor nor SoundFieldGroupLabelSubDescriptor"));
}
WaveAudioEssenceDescriptor waveAudioEssenceDescriptor = new WaveAudioEssenceDescriptor((WaveAudioEssenceDescriptor.WaveAudioEssenceDescriptorBO) interchangeObjectBO);
this.cacheInterchangeObject(waveAudioEssenceDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), waveAudioEssenceDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(IABEssenceDescriptor.class)){
IABEssenceDescriptor iabEssenceDescriptor = new IABEssenceDescriptor((IABEssenceDescriptor.IABEssenceDescriptorBO) interchangeObjectBO);
this.cacheInterchangeObject(iabEssenceDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), iabEssenceDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(MGASoundEssenceDescriptor.class)){
MGASoundEssenceDescriptor mgaSoundEssenceDescriptor = new MGASoundEssenceDescriptor((MGASoundEssenceDescriptor.MGASoundEssenceDescriptorBO) interchangeObjectBO);
this.cacheInterchangeObject(mgaSoundEssenceDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), mgaSoundEssenceDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(TimedTextDescriptor.class)){
List<TimeTextResourceSubDescriptor> subDescriptorList = new ArrayList<>();
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if(dependentInterchangeObject instanceof TimeTextResourceSubDescriptor) {
subDescriptorList.add((TimeTextResourceSubDescriptor)dependentInterchangeObject);
}
}
TimedTextDescriptor timedTextDescriptor = new TimedTextDescriptor((TimedTextDescriptor.TimedTextDescriptorBO) interchangeObjectBO, subDescriptorList);
this.cacheInterchangeObject(timedTextDescriptor);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), timedTextDescriptor);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(TextBasedDMFramework.class)){
TextBasedObject textBasedObject = null;
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if(dependentInterchangeObject instanceof TextBasedObject) {
textBasedObject = (TextBasedObject)dependentInterchangeObject;
}
}
TextBasedDMFramework textBasedDMFramework = new TextBasedDMFramework((TextBasedDMFramework.TextBasedDMFrameworkBO) interchangeObjectBO, textBasedObject);
this.cacheInterchangeObject(textBasedDMFramework);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), textBasedDMFramework);
} else if(interchangeObjectBO.getClass().getEnclosingClass().equals(DescriptiveMarkerSegment.class)){
DMFramework dmFramework = null;
for(Node dependent : node.depends) {
InterchangeObject dependentInterchangeObject = uidToMetadataSets.get(dependent.uid);
if(dependentInterchangeObject instanceof TextBasedDMFramework) {
dmFramework = (TextBasedDMFramework)dependentInterchangeObject;
}
}
DescriptiveMarkerSegment descriptiveMarkerSegment = new DescriptiveMarkerSegment((DescriptiveMarkerSegment.DescriptiveMarkerSegmentBO) interchangeObjectBO, dmFramework);
this.cacheInterchangeObject(descriptiveMarkerSegment);
uidToMetadataSets.put(interchangeObjectBO.getInstanceUID(), descriptiveMarkerSegment);
}
}
}
}