예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        /// <summary>
        /// Check all index tables
        /// </summary>
        /// <param name="file"></param>
        /// <param name="results"></param>
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            MXFValidationResult valResult = new MXFValidationResult("Index Tables");

            results.Add(valResult);             // And directly add the results

            Stopwatch sw = Stopwatch.StartNew();

            // Clear list
            m_indexTables = new List <MXFIndexTableSegment>();
            m_systemItems = new List <MXFSystemItem>();

            // Load all partitions
            this.Task = "Loading partitions";
            List <MXFPartition> partitionsToLoad = this.File.Partitions.Where(a => !a.IsLoaded).ToList();

            for (int n = 0; n < partitionsToLoad.Count(); n++)
            {
                int progress = (n * 50) / partitionsToLoad.Count();
                ReportProgress(progress);
                partitionsToLoad[n].Load();
            }

            // Find all index tables (and the first system index)
            this.Task = "Locating index tables";
            FindIndexTableAndSystemItems(this.File);
            ReportProgress(55);
            LogInfo("Found {0} index table segments in {1} ms", this.m_indexTables.Count, sw.ElapsedMilliseconds);
            sw.Restart();

            // Check if first index table is CBE
            if (this.m_indexTables.Count == 0)
            {
                valResult.SetError(string.Format("No index tables found!", m_indexTables.Count));
                return;
            }


            MXFIndexTableSegment firstTable = this.m_indexTables.FirstOrDefault();

            if (firstTable != null)
            {
                if (firstTable.EditUnitByteCount > 0)
                {
                    // Check other tables
                    for (int n = 1; n < this.m_indexTables.Count; n++)
                    {
                        if (this.m_indexTables[n].EditUnitByteCount != firstTable.EditUnitByteCount &&
                            this.m_indexTables[n].BodySID == firstTable.BodySID)
                        {
                            valResult.SetError(string.Format("Constant Bytes per Element ({0} bytes) but index table {1} has other CBE: {2} (both have BodySID {3}).", firstTable.EditUnitByteCount, n, this.m_indexTables[n].EditUnitByteCount, firstTable.BodySID));
                            return;
                        }
                    }

                    // CBE for this BodySID
                    if (firstTable.IndexDuration == 0 && firstTable.IndexStartPosition == 0)
                    {
                        valResult.SetSuccess(string.Format("Constant Bytes per Element ({0} bytes) for the whole duration of BodySID {1}", firstTable.EditUnitByteCount, firstTable.BodySID));
                        // TODO Check if the size of all compounds is the same??
                        return;
                    }
                    else
                    {
                        // Complicated, mixed file
                        valResult.SetWarning(string.Format("Constant Bytes per Element ({0} bytes) but not for the whole file for BodySID {1}. Duration: {2}, StartOffset: {3}", firstTable.EditUnitByteCount, firstTable.BodySID, firstTable.IndexDuration, firstTable.IndexStartPosition));
                        return;
                    }
                }
            }

            // Check if there are multiple index table segments pointing to the same data
            int invalidCt        = 0;
            int validCt          = 0;
            int totalSystemItems = 0;
            int counter          = 0;

            this.Task = "Checking for duplicates";
            foreach (MXFIndexTableSegment ids in this.m_indexTables)
            {
                ReportProgress(55 + (counter * 20) / this.m_indexTables.Count());

                // And all index entries
                if (ids.IndexEntries != null)
                {
                    List <MXFIndexTableSegment> sameStuff = this.m_indexTables.Where(a => a != ids && a.IndexSID == ids.IndexSID && a.IndexStartPosition == ids.IndexStartPosition).ToList();
                    foreach (MXFIndexTableSegment sameIds in sameStuff)
                    {
                        if (sameIds.IndexEntries.Count != ids.IndexEntries.Count)
                        {
                            valResult.AddError(string.Format("Index {0} in partition {1} is not the same length as in partition {2}!", sameIds.IndexSID, sameIds.Partition.ToString(), ids.Partition.ToString()));
                            invalidCt++;
                        }
                        else
                        {
                            for (int n = 0; n < sameIds.IndexEntries.Count; n++)
                            {
                                if (ids.IndexEntries[n].KeyFrameOffset != sameIds.IndexEntries[n].KeyFrameOffset ||
                                    ids.IndexEntries[n].StreamOffset != sameIds.IndexEntries[n].StreamOffset ||
                                    ids.IndexEntries[n].TemporalOffset != sameIds.IndexEntries[n].TemporalOffset)
                                {
                                    valResult.AddError(string.Format("The indexentry {0} of Index {1} in partition {2} is not the same data as in partition {3}!", n, sameIds.IndexSID, sameIds.Partition.ToString(), ids.Partition.ToString()));
                                    invalidCt++;
                                    break;
                                }
                            }
                        }
                    }
                }
                counter++;
            }


            // First try to match system items
            if (m_systemItems.Count != 0)
            {
                // For each index table segment
                totalSystemItems = m_systemItems.Count();
                counter          = 0;
                this.Task        = "Checking essence offsets";
                foreach (MXFIndexTableSegment ids in this.m_indexTables)
                {
                    ReportProgress(75 + (counter * 20) / this.m_indexTables.Count());

                    // And all index entries
                    if (ids.IndexEntries != null)
                    {
                        foreach (MXFEntryIndex index in ids.IndexEntries)
                        {
                            // Check if there is a system item at this offset
                            long          searchIndex = (long)(index.StreamOffset);
                            MXFSystemItem si          = this.m_systemItems.Where(a => a.EssenceOffset == searchIndex).FirstOrDefault();
                            if (si != null)
                            {
                                // Yes, found
                                validCt++;
                                si.Indexed = true;
                            }
                            else
                            {
                                // Not found
                                valResult.AddError(string.Format("Index {0} not pointing to valid essence!", index.Index));
                                invalidCt++;
                            }
                        }
                    }
                    counter++;
                }
            }
            else if (m_pictureItems.Count != 0)
            {
                // Now try to match the picture essences

                // For each index table segment
                counter          = 0;
                totalSystemItems = m_pictureItems.Count();
                this.Task        = "Checking picture offsets";
                foreach (MXFIndexTableSegment ids in this.m_indexTables)
                {
                    ReportProgress(75 + (counter * 20) / this.m_indexTables.Count());

                    // And all index entries
                    if (ids.IndexEntries != null)
                    {
                        foreach (MXFEntryIndex index in ids.IndexEntries)
                        {
                            // Check if there is a system item at this offset
                            long searchIndex     = (long)(index.StreamOffset);
                            MXFEssenceElement ee = this.m_pictureItems.Where(a => a.EssenceOffset == searchIndex).FirstOrDefault();
                            if (ee != null)
                            {
                                // Yes, found
                                validCt++;
                                ee.Indexed = true;
                            }
                            else
                            {
                                // Not found
                                valResult.AddError(string.Format("Index {0} not pointing to a valid picture essence!", index.Index));
                                invalidCt++;
                            }
                        }
                    }
                }
            }
            else
            {
                valResult.SetError(string.Format("No system items and/or picture essences found (found {0} index table segments)", m_indexTables.Count));
                return;
            }


            bool fError = false;

            if (this.m_systemItems.Count() > 0)
            {
                if (this.m_systemItems.Count(a => !a.Indexed) != 0)
                {
                    // Hmm still some items left in the array
                    valResult.SetError(string.Format("There are {0} essence elements (of the total {1}) that are not referenced in an index table!", this.m_systemItems.Count, totalSystemItems));
                    fError = true;
                }
            }
            else if (this.m_pictureItems.Count() > 0)
            {
                if (this.m_pictureItems.Count(a => !a.Indexed) != 0)
                {
                    // Hmm still some items left in the array
                    valResult.SetError(string.Format("There are {0} essence elements (of the total {1}) that are not referenced in an index table!", this.m_pictureItems.Count, totalSystemItems));
                    fError = true;
                }
            }


            if (!fError)
            {
                if (invalidCt > 0)
                {
                    valResult.SetError(string.Format("Found {0} index errors! There are {0} indices that are NOT pointing to valid essence data (valid {1})!", invalidCt, validCt));
                }
                else if (validCt > 0)
                {
                    valResult.SetSuccess(string.Format("Index table is valid! All {0} index entries point to valid essences!", validCt));
                }
                if (validCt == 0 && invalidCt == 0)
                {
                    valResult.SetError(string.Format("No valid indexes found in this file!"));
                }
            }
            LogInfo("Validation completed in {0} msec", sw.ElapsedMilliseconds);


            // Check system item range
            if (this.m_systemItems.Count() > 0)
            {
                CheckUserDates(this.File, results);
                CheckContinuityCounter(this.File, results);
            }
            ReportProgress(100);
        }