/// <summary> /// Find the next object of a specific type /// </summary> /// <param name="currentObject"></param> /// <returns></returns> public MXFObject FindPreviousibling(Type typeToFind, bool skipFillers) { MXFObject found = null; if (this.Parent != null && this.Parent.HasChildren) { int index = this.Parent.Children.FindIndex(a => a == this); if (index > 0) { for (int n = index - 1; n >= 0; n--) { MXFObject child = this.Parent.Children[n]; if (child.GetType() == typeToFind && child.IsVisible(skipFillers)) { // Yes found next sibling of the same type return this.Parent.Children[n]; } // Not the correct type, try its children found = this.Parent.Children[n].FindChildReverse(typeToFind, skipFillers); if (found != null) return found; } } // Hmm still not found, try our grand-parent: found = this.Parent.FindPreviousibling(typeToFind, skipFillers); } return found; }
/// <summary> /// Read a list of keys /// </summary> /// <param name="reader"></param> /// <param name="categoryName"></param> /// <returns></returns> protected UInt32 ReadKeyList(MXFReader reader, string categoryName, string singleItem) { MXFObject keylist = reader.ReadKeyList(categoryName, singleItem); this.AddChild(keylist); return((UInt32)keylist.ChildCount); }
/// <summary> /// Add all children (recursively) /// </summary> /// <param name="lObj"></param> protected MXFLogicalObject LogicalAddChilds(MXFLogicalObject lObj) { // Check properties for reference MXFObject obj = lObj.Object; if (obj != null) { var desc = obj.Descendants().OfType <IResolvable>(); foreach (var r in desc) { // create and add the logical child var refObj = r.GetReference(); if (refObj != null) { MXFLogicalObject newLObj = refObj.CreateLogicalObject(); lObj.AddChild(newLObj); if (refObj.Children.Any()) { LogicalAddChilds(newLObj); } } } } return(lObj); }
/// <summary> /// Add a child /// </summary> /// <param name="child"></param> /// <returns></returns> public MXFObject AddChild(MXFObject child) { if (this.Children == null) this.Children = new List<MXFObject>(); child.Parent = this; this.Children.Add(child); if (child.Offset < this.m_lOffset) this.m_lOffset = child.Offset; return child; }
/// <summary> /// Add all children (recusive) /// </summary> /// <param name="parent"></param> protected MXFLogicalObject LogicalAddChilds(MXFLogicalObject parent) { // Check properties for reference MXFObject reference = parent.Object; if (reference != null) { foreach (PropertyInfo propertyInfo in reference.GetType().GetProperties()) { if (propertyInfo.CanRead) { if (propertyInfo.PropertyType == typeof(MXFRefKey)) { // Found one! MXFRefKey refKey = (MXFRefKey)propertyInfo.GetValue(reference, null); if (refKey != null && refKey.Reference != null) { // Add the child MXFLogicalObject lo = new MXFLogicalObject(refKey.Reference, refKey.Reference.ToString()); parent.AddChild(lo); // Add all sub stuff LogicalAddChilds(lo); } } } } if (reference.HasChildren) { foreach (MXFObject child in reference.Children) { if (child.HasChildren) { foreach (MXFObject grandchild in child.Children) { MXFRefKey refKey = grandchild as MXFRefKey; if (refKey != null && refKey.Reference != null) { MXFLogicalObject lo = new MXFLogicalObject(refKey.Reference, refKey.Reference.ToString()); // Add the child parent.AddChild(lo); // Add all sub stuff LogicalAddChilds(lo); } } } } } } return(parent); }
/// <summary> /// Locate all index table segments RECURSIVELY /// </summary> /// <param name="current"></param> public void FindIndexTableAndSystemItems(MXFObject current) { // LOAD the object (when not yet loaded) // This may take some time!!! if (current is ILazyLoadable loadable) { loadable.Load(); } MXFKLV klv = current as MXFKLV; if (klv != null) { if (klv.Key.Type == KeyType.IndexSegment) { MXFIndexTableSegment its = klv as MXFIndexTableSegment; if (its != null) { this.m_indexTables.Add(its); } } else if (klv.Key.Type == KeyType.SystemItem) { MXFSystemItem si = klv as MXFSystemItem; if (si != null) { si.Indexed = false; this.m_systemItems.Add(si); } } else if (klv.Key.Type == KeyType.Essence) { MXFEssenceElement ee = klv as MXFEssenceElement; if (ee != null) { if (ee.IsPicture) { ee.Indexed = false; this.m_pictureItems.Add(ee); } } } } if (!current.Children.Any()) { return; } foreach (MXFObject child in current.Children) { FindIndexTableAndSystemItems(child); } }
public static int GetMaxOffsetDigitCount(this MXFObject obj) { // get the object with the greatest offset value long maxOffset = obj.Root().Descendants().Max(o => o.Offset); // count the digits int digits = 1; while ((maxOffset /= 10) != 0) { ++digits; } return(digits); }
/// <summary> /// Create a list of all keys in the file and their objects (recursive) /// </summary> /// <param name="refKey"></param> protected void CreateKeyList(Dictionary <string, MXFObject> allKeys, MXFObject parent) { // This will only use public properties. Is that enough? MXFMetadataBaseclass meta = parent as MXFMetadataBaseclass; if (meta != null) { if (meta.InstanceUID != null) { if (!allKeys.ContainsKey(meta.InstanceUID.ShortKey.ToString())) { allKeys.Add(meta.InstanceUID.ShortKey.ToString(), parent); } } } // Loop through all properties of this object // This will only use public properties. Is that enough? //int xtraCnt = 0; //foreach (PropertyInfo propertyInfo in parent.GetType().GetProperties()) //{ // if (propertyInfo.CanRead) // { // if (propertyInfo.PropertyType == typeof(MXFKey)) // { // // Found one! // MXFKey key = (MXFKey)propertyInfo.GetValue(parent); // if (key != null) // { // if (!allKeys.ContainsKey(key.ShortKey.ToString())) // { // allKeys.Add(key.ShortKey.ToString(), parent); // xtraCnt++; // } // } // } // } //} if (parent.Children != null) { foreach (MXFObject child in parent.Children) { CreateKeyList(allKeys, child); } } }
public MXFPartition(MXFReader reader, MXFKLV headerKLV) : base(headerKLV, "Partition", KeyType.Partition) { this.m_eType = MXFObjectType.Partition; this.IsLoaded = false; // Determine the partition type switch (this.Key[13]) { case 2: this.PartitionType = PartitionType.Header; break; case 3: this.PartitionType = PartitionType.Body; break; case 4: this.PartitionType = PartitionType.Footer; break; default: this.PartitionType = PartitionType.Unknown; Log(MXFLogType.Error, "unknown partition type"); break; } this.Closed = (this.PartitionType == PartitionType.Footer) || (this.Key[14] & 0x01) == 0x00; this.Complete = (this.Key[14] > 2); // Make sure we read at the data position reader.Seek(this.DataOffset); this.MajorVersion = reader.ReadUInt16(); this.MinorVersion = reader.ReadUInt16(); this.KagSize = reader.ReadUInt32(); this.ThisPartition = reader.ReadUInt64(); this.PreviousPartition = reader.ReadUInt64(); this.FooterPartition = reader.ReadUInt64(); this.HeaderByteCount = reader.ReadUInt64(); this.IndexByteCount = reader.ReadUInt64(); this.IndexSID = reader.ReadUInt32(); this.BodyOffset = reader.ReadUInt64(); this.BodySID = reader.ReadUInt32(); this.OP = reader.ReadULKey(); MXFObject essenceContainers = reader.ReadAUIDSet("Essence Containers", "Essence Container"); this.AddChild(essenceContainers); }
/// <summary> /// Loop through all items, when an item with a reference is found, /// </summary> /// <param name="parent"></param> protected void ResolveReferences(Dictionary <string, MXFObject> allKeys, MXFObject parent) { MXFRefKey refParent = parent as MXFRefKey; if ((object)refParent != null) { if (allKeys.ContainsKey(refParent.Key.ShortKey.ToString())) { MXFObject referencedObject = allKeys[refParent.Key.ShortKey.ToString()]; Debug.WriteLine(string.Format("Found reference: {0} -> {1}", refParent.ToString(), referencedObject.ToString())); refParent.Reference = referencedObject; } } // Loop through all properties of this object // This will only use public properties. Is that enough? foreach (PropertyInfo propertyInfo in parent.GetType().GetProperties()) { if (propertyInfo.CanRead) { if (propertyInfo.PropertyType == typeof(MXFRefKey)) { // Found one! MXFRefKey refKey = (MXFRefKey)propertyInfo.GetValue(parent, null); if (refKey != null) { if (allKeys.ContainsKey(refKey.Key.ShortKey.ToString())) { MXFObject referencedObject = allKeys[refKey.Key.ShortKey.ToString()]; Debug.WriteLine(string.Format("Found reference: {0} -> {1}", propertyInfo.Name, referencedObject.ToString())); refKey.Reference = referencedObject; } } } } } if (parent.Children != null) { foreach (MXFObject child in parent.Children) { ResolveReferences(allKeys, child); } } }
/// <summary> /// Find the first child of a specific type /// </summary> /// <param name="currentObject"></param> /// <returns></returns> public MXFObject FindChild(Type typeToFind, bool skipFillers) { if (this.Children != null) { MXFObject found = null; foreach(MXFObject child in this.Children) { if (child.GetType() == typeToFind && child.IsVisible(skipFillers)) return child; if (child.HasChildren) { found = child.FindChild(typeToFind, skipFillers); if (found != null) return found; } } return null; } return null; }
/// <summary> /// Find the first child of a specific type /// </summary> /// <param name="currentObject"></param> /// <returns></returns> public MXFObject FindChildReverse(Type typeToFind, bool skipFillers) { if (this.Children != null) { MXFObject found = null; for (int n = this.Children.Count - 1; n >= 0; n--) { MXFObject child = this.Children[n]; if (child.GetType() == typeToFind && child.IsVisible(skipFillers)) return child; if (child.HasChildren) { found = child.FindChildReverse(typeToFind, skipFillers); if (found != null) return found; } } return null; } return null; }
/// <summary> ///Default constructor /// </summary> /// <param name="reader"></param> public MXFLogicalObject(MXFObject obj, string name) { this.Object = obj; this.Name = name; }
/// <summary> /// Process a new KLV object /// </summary> /// <param name="klv"></param> /// <param name="partitions"></param> /// <param name="currentPartition"></param> /// <param name="partitionNumber"></param> /// <param name="allPrimerKeys"></param> private void ProcessKLVObject(MXFKLV klv, MXFObject partitions, ref MXFPartition currentPartition, ref int partitionNumber, ref Dictionary <UInt16, MXFEntryPrimer> allPrimerKeys) { // Is this a header, add to the partitions switch (klv.Key.Type) { case KeyType.Partition: currentPartition = klv as MXFPartition; currentPartition.File = this; currentPartition.PartitionNumber = partitionNumber; this.Partitions.Add(currentPartition); partitions.AddChild(currentPartition); partitionNumber++; break; case KeyType.PrimerPack: if (currentPartition != null) { MXFPrimerPack primer = klv as MXFPrimerPack; if (primer != null) // Just to be sure { // Let the partition know all primer keys allPrimerKeys = primer.AllKeys; currentPartition.PrimerKeys = primer.AllKeys; } currentPartition.AddChild(klv); // Add the primer } break; case KeyType.RIP: // Only add the RIP when not yet present if (this.RIP == null) { this.AddChild(klv); this.RIP = klv as MXFRIP; } break; case KeyType.SystemItem: if (currentPartition != null) { // Store the first system item for every partition // (required to calculate essence positions) if (currentPartition.FirstSystemItem == null) { currentPartition.FirstSystemItem = klv as MXFSystemItem; } currentPartition.AddChild(klv); } else { this.AddChild(klv); } // Store the first and the last system item if (this.FirstSystemItem == null) { this.FirstSystemItem = klv as MXFSystemItem; } this.LastSystemItem = klv as MXFSystemItem; break; case KeyType.Essence: if (currentPartition != null) { // Store the first system item for every partition // (required to calculate essence positions) MXFEssenceElement ee = klv as MXFEssenceElement; if (ee.IsPicture && currentPartition.FirstPictureEssenceElement == null) { currentPartition.FirstPictureEssenceElement = ee; } currentPartition.AddChild(klv); } else { this.AddChild(klv); } break; case KeyType.Preface: this.LogicalBase = new MXFLogicalObject(klv, klv.ToString()); // Normal if (currentPartition != null) { currentPartition.AddChild(klv); } else { this.AddChild(klv); } break; default: // Normal if (currentPartition != null) { currentPartition.AddChild(klv); } else { this.AddChild(klv); } break; } }
/// <summary> /// Returns true if a child with a certain offset already exists /// </summary> /// <param name="currentObject"></param> /// <returns></returns> public bool ChildExists(MXFObject child) { if (this.Children != null && child != null) return this.Children.Exists(a => a.Offset == child.Offset); return false; }
/// <summary> ///Default constructor /// </summary> /// <param name="reader"></param> public MXFLogicalObject(MXFObject obj) { this.Object = obj; }