예제 #1
0
        /// <summary>
        ///  Execute all validation tests
        /// </summary>
        public void ExecuteValidationTest(BackgroundWorker worker, bool extendedTest)
        {
            // Reset results
            this.m_results.Clear();

            // Execute validation tests
            List <MXFValidator> allTest = new List <MXFValidator>();

            allTest.Add(new MXFValidatorInfo());
            allTest.Add(new MXFValidatorPartitions());
            allTest.Add(new MXFValidatorRIP());
            if (extendedTest)
            {
                allTest.Add(new MXFValidatorIndex());
            }
            foreach (MXFValidator mxfTest in allTest)
            {
                mxfTest.Initialize(this, worker);
                mxfTest.ExecuteTest(ref m_results);
            }

            if (!extendedTest)
            {
                MXFValidationResult valResult = new MXFValidationResult("Index Table");
                this.m_results.Add(valResult);
                valResult.SetWarning("Index table test not executed in partial loading mode (to execute test press the execute all test button).");
                //MXFValidationResult valResult = new MXFValidationResult("Index Tables");
                //this.Results.Add(valResult); // And directly add the results
            }
        }
예제 #2
0
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            this.Task = "Track Info";
            int not = this.File.NumberOfTracks;

            for (int n = 1; n <= not; n++)
            {
                ReportProgress(n * 100 / not);
                MXFValidationResult valResult = new MXFValidationResult(string.Format("Track {0}", n));
                valResult.Category = "Track Info";
                results.Add(valResult);                 // And directly add the results
                valResult.SetInfo(this.File.GetTrackInfo(n));
            }
        }
예제 #3
0
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            this.Task = "Track Info";
            MXFMaterialPackage     mp     = this.File.GetContentStorage()?.GetFirstMaterialPackage();
            List <MXFGenericTrack> tracks = mp.GetGenericTracks().ToList();

            foreach (var t in tracks)
            {
                int n = tracks.IndexOf(t);
                ReportProgress(n * 100 / tracks.Count);
                MXFValidationResult valResult = new MXFValidationResult(string.Format("Track {0}", n));
                valResult.Category = "Track Info";
                valResult.SetInfo(this.File.GetTrackInfo(t));
                results.Add(valResult); // And directly add the results
            }
        }
예제 #4
0
        /// <summary>
        /// Check if the RIP is present and valid
        /// </summary>
        /// <param name="this.File"></param>
        /// <param name="results"></param>
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            MXFValidationResult valResult = new MXFValidationResult("Random Index Pack Test");

            results.Add(valResult);
            valResult.Category = "Random Index Pack";

            Stopwatch sw = Stopwatch.StartNew();

            if (this.File.RIP == null)
            {
                valResult.SetError(string.Format("Error! No RIP found."));
                return;
            }

            if (this.File.RIPEntryCount != this.File.PartitionCount)
            {
                valResult.SetError(string.Format("Error! Number of RIP entries is not equal to the number of partitions ({0} vs {1}).", this.File.RIPEntryCount, this.File.PartitionCount));
                return;
            }

            int ripErrorCount = 0;

            for (int n = 0; n < this.File.RIPEntryCount; n++)
            {
                MXFEntryRIP rip = this.File.RIP.Children[n] as MXFEntryRIP;
                if (rip != null)
                {
                    MXFPartition part = this.File.Partitions.Where(a => (ulong)a.Offset == rip.PartitionOffset).FirstOrDefault();
                    if (part == null)
                    {
                        ripErrorCount++;
                        valResult.AddError(string.Format("Error! RIP entry {0} not pointing to a valid partion.", n));
                        return;
                    }
                }
            }
            if (ripErrorCount > 0)
            {
                valResult.SetError(string.Format("Error! {0} RIP entries are not pointing to a valid partion.", ripErrorCount));
                return;
            }

            valResult.SetSuccess("Random Index Pack (RIP) is valid.");

            LogInfo("Validation completed in {0} msec", sw.ElapsedMilliseconds);
        }
예제 #5
0
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            this.Task = "Checking MXF Keys";
            Stopwatch sw = Stopwatch.StartNew();

            var klvWithUnknownKeys = this.File.Descendants()
                                     .OfType <MXFKLV>()
                                     .Where(klv => string.IsNullOrEmpty(klv.Key.Name))
                                     .OrderBy(klv => klv.Offset);

            foreach (var unkownKLV in klvWithUnknownKeys)
            {
                MXFValidationResult valResult = new MXFValidationResult("Keys");
                valResult.SetWarning(string.Format("Unknown key {0} @ {1}.", unkownKLV.Key, unkownKLV.Offset));
                results.Add(valResult);                 // And directly add the results
            }

            LogInfo("MXF Key check completed in {0} msec", sw.ElapsedMilliseconds);
        }
예제 #6
0
        /// <summary>
        /// Check the essence range
        /// </summary>
        /// <param name="file"></param>
        /// <param name="results"></param>
        protected void CheckContinuityCounter(MXFFile file, List <MXFValidationResult> results)
        {
            MXFValidationResult valResult = new MXFValidationResult("System Items");

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

            // Check for continous range
            int cc         = -1;
            int errorCount = 0;

            foreach (MXFSystemItem si in this.m_systemItems)
            {
                if (si.ContinuityCount - cc != 1)
                {
                    errorCount++;
                    //valResult.SetError(string.Format("Invalid continuity count for system item at offset {0}. CC should be {1} but is {2}!", si.Offset, cc + 1, si.ContinuityCount));
                    //return;
                }
                cc = si.ContinuityCount;
            }

            if (errorCount > 0)
            {
                if (errorCount >= this.m_systemItems.Count() - 1)
                {
                    valResult.SetWarning(string.Format("All continuity counter values are not set!"));
                }
                else
                {
                    valResult.SetError(string.Format("Found {0} invalid continuity counter values (total system items {1})!", errorCount, this.m_systemItems.Count()));
                }
            }
            else
            {
                valResult.SetSuccess(string.Format("Continuity counter values are correct!"));
            }
        }
예제 #7
0
        /// <summary>
        /// Check the essence range
        /// </summary>
        /// <param name="file"></param>
        /// <param name="results"></param>
        protected void CheckUserDates(MXFFile file, List <MXFValidationResult> results)
        {
            List <MXFSystemItem> items = this.m_systemItems.OrderBy(a => a.ContinuityCount).ToList();

            if (items.Count > 1)
            {
                MXFTimeStamp ts = new MXFTimeStamp(items.First().UserDate);
                if (ts != null)
                {
                    MXFValidationResult valResult = new MXFValidationResult("System Items");
                    results.Add(valResult);                     // And directly add the results

                    MXFTimeStamp tsLast = null;
                    for (int n = 1; n < items.Count() - 1; n++)                     // Skip last one (always invalid??)
                    {
                        ts.Increase();
                        if (!items[n].UserDate.IsEmpty())
                        {
                            if (!items[n].UserDate.IsSame(ts))
                            {
                                valResult.SetError(string.Format("Invalid user date at offset {0} (was {1}, expected {2})!", items[n].Offset, items[n].UserDate, ts));
                                return;
                            }
                            tsLast = items[n].UserDate;
                        }
                    }
                    if (tsLast != null)
                    {
                        valResult.SetSuccess(string.Format("UserDates are continious from {0} to {1}, at {2} fps!", items.First().UserDate, tsLast, ts.FrameRate));
                    }
                    else
                    {
                        valResult.SetSuccess(string.Format("UserDates are continious!"));
                    }
                }
            }
        }
예제 #8
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);
        }
예제 #9
0
        /// <summary>
        /// Check if all partitions are valid
        /// </summary>
        /// <param name="results"></param>
        public override void OnExecuteTest(ref List <MXFValidationResult> results)
        {
            this.Task = "Validating partitions";

            MXFValidationResult valResult = new MXFValidationResult("Partition Test");

            results.Add(valResult);
            valResult.Category = "Partitions";

            Stopwatch sw = Stopwatch.StartNew();

            if (this.File.Partitions == null || this.File.Partitions.Count == 0)
            {
                valResult.SetError(string.Format("Error! No partitions present."));
                return;
            }


            // Check if only a single header is present
            if (this.File.Partitions.Where(a => a.PartitionType == PartitionType.Header).Count() > 1)
            {
                valResult.SetError(string.Format("Error! More then 1 header partion present!"));
                return;
            }
            MXFPartition header = this.File.Partitions.Where(a => a.PartitionType == PartitionType.Header).FirstOrDefault();

            if (header == null)
            {
                valResult.SetError(string.Format("Error! No header partition present!"));
                return;
            }

            // Check if only a single footer is present
            if (this.File.Partitions.Where(a => a.PartitionType == PartitionType.Footer).Count() > 1)
            {
                valResult.SetError(string.Format("Error! More then 1 footer partion present!"));
                return;
            }
            MXFPartition footer         = this.File.Partitions.Where(a => a.PartitionType == PartitionType.Footer).FirstOrDefault();
            long         footerExpected = 0;

            if (footer == null)
            {
                valResult.SetWarning(string.Format("Error! No footer partition present!"));
                footerExpected = 0;
            }
            else
            {
                footerExpected = footer.Offset;
            }

            // Check if all partitions point to the previous partition and check the this pointer
            // Note that this is more serious and less likely to go wrong then the footer check
            for (int n = 0; n < this.File.Partitions.Count(); n++)
            {
                if (this.File.Partitions[n].ThisPartition != (ulong)this.File.Partitions[n].Offset)
                {
                    valResult.SetError(string.Format("Error! Partition[{0}] has an invalid 'ThisPartition' pointer.", n));
                    return;
                }

                if (n > 0)
                {
                    if (this.File.Partitions[n].PreviousPartition != (ulong)this.File.Partitions[n - 1].Offset)
                    {
                        valResult.SetError(string.Format("Error! Partition[{0}] has no valid link to the previous partition.", n));
                        return;
                    }
                }
            }

            // Check if all partitions point to the footer
            int errorCount = 0;

            for (int n = 0; n < this.File.Partitions.Count(); n++)
            {
                if (this.File.Partitions[n].Closed && this.File.Partitions[n].FooterPartition != (ulong)footerExpected)
                {
                    errorCount++;
                }
            }
            if (errorCount > 0)
            {
                valResult.SetWarning(string.Format("There are {0} partitions that do not point to the footer partition.", errorCount));
                return;
            }

            valResult.SetSuccess("Partition structure is valid.");

            LogInfo("Validation completed in {0} msec", sw.ElapsedMilliseconds);
        }